Ruby - cannot convert individual chars in string to ASCII - ruby

I am trying to run the following code on http://repl.it/languages/Ruby/, but I am encountering a NoMethodError:
a = "string"
a.each_char do |c|
puts c.ord
end
The error details are as follows:
(eval):1: undefined method `ord' for "s":String (NoMethodError)
from (eval):0:in `each_char'
from (eval):0
Please could somebody explain to me why my code does not work?

The each_char method of String yields each character as a separate String.
The Ruby version running on repl.it is quite old (1.8.7). The String class in that version of Ruby doesn't define an ord method, so your code fails to run with a NoMethodError.
ord was added to String in Ruby 1.9, so your code will run on newer versions of Ruby.
On Ruby 1.8.7 (and repl.it), you could use one of the following alternatives instead:
a = "string"
a.each_char do |c|
puts c[0]
end
a = "string"
a.each_byte do |c|
puts c
end
However, please note that these examples won't behave identically to your original code if your string uses a multi-byte encoding. The ord method returns a Unicode code point. The Ruby 1.8.7 examples will give you individual bytes.

The code as is will print the ascii code of each letter. Perhaps you're looking at the return value which would be the original string "string"?

Related

TryRuby raises undefined method `[]=' for String

I am working to replace a character in a string, changing "cat" into "hat".
Here's my code:
str = "cat"
str[0] = 'h'
puts str
But when I run this code in TryRuby I get this error:
NoMethodError: undefined method `[]=' for "cat"
l am using Try ruby's editor
ruby.github.io/TryRuby uses Opal (a Ruby-to-JavaScript compiler) to evaluate the code in the browser. Opal provides its own String class which doesn't implement []=.
This seems to be a known limitation (among others). From the documentation: (emphasis added)
For performance and ease of runtime features, all strings in Opal are immutable, i.e. #<<, #gsub!, etc. do not exist.
You can use the gsub method and do it like this:
str = 'cat'
puts str.gsub(str[0], 'h')

ruby 1.8 has find function, however after 1.9 there is not

In ruby1.8, String class has methods like find and find_all. The find usage is like following:
test.rb
a="123 123\n234 234\n456 456"
b = a.find { |ln| a.split[0] == ARGV[0] }
print b
I can get the following result:
# ./test.rb 123
123 123
However, after ruby 1.9, it fails because there is no find for the String instance. I need to handle these scripts. And I prefer to use the latest stable ruby.
I don't know if I can add a customized method for find and find_all, and how. I thought I can open String class, and add find method. However, I don't know how to receive the block as arguments, e.g., { |ln| a.split[0] == ARGV[0] }. Does anyone know any solutions?
You can use each_line which turns the list into an array of strings, and use Array's find to do the job
b = a.each_line.find { |ln| ln.split[0] == ARGV[0] }
# => "123 123\n"
If you want to patch String itself, you could create a delegation method in String.
class String
def find(*args, &block)
each_line.find(*args, &block)
end
end
now you should be able to keep your old code, and it should work.

Ruby's to_s method question (from Axe book 2nd edition)

According to the axe book (2nd edition), we can use to_s as follows.
class Song
def to_s
"Song"
end
end
song = Song.new()
song.to_s
But, it doesn't give me anything, in order to print something to the stdout, I should run
def to_s
p "Song"
end
Is there any change since the ruby 1.8.2 when the book was written for?
My ruby version info is 1.8.7 for Mac.
ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0]
The Pickaxe book uses a common notation of e.g.
song.to_s → "Song: My Way--Sinatra (225)"
to indicate that "Song: My Way--Sinatra (225)" is the value of the expression on the left. However it isn't printed out unless you explictly use a puts.
An appropriate implementation of to_s on an object will return a string representation of that object (e.g. the name for a person or the title and ID for a blog post) but won't actually have any side effects itself (such as outputting something.)
If you use irb, the interactive Ruby interpreter it prints out the value of each expression for you without an explicit puts. e.g.
$ irb
irb(main):001:0> 2 + 2
=> 4
That example might be meant to be typed into a REPL like irb, which would look like this:
irb> class Song
.. def to_s
.. "Song"
.. end
.. end
=> nil
irb> song = Song.new()
=> Song
irb> song.to_s
=> "Song"
In your case you would want your last lines to be:
song = Song.new
puts song.to_s
Right, to_s has always just converted the object to a string. It is up to your program to then use that string - for example, by writing it to stdout.
This is because the above method simply returns "song", it doesn't print it. Your program should do the printing itself.

iterating over each character of a String in ruby 1.8.6 (each_char)

I am new to ruby and currently trying to operate on each character separately from a base String in ruby. I am using ruby 1.8.6 and would like to do something like:
"ABCDEFG".each_char do |i|
puts i
end
This produces a undefined method `each_char' error.
I was expecting to see a vertical output of:
A
B
C
D
..etc
Is the each_char method defined only for 1.9? I tried using the plain each method, but the block simply ouputs the entire string in one line. The only way I figure how to do this, which is rather inconvenient is to create an array of characters from the begining:
['A','B','C','D','...'].each do|i|
puts i
end
This outputs the desired:
A
B
C
..etc
Is there perhaps a way to achive this output using an unmodified string to begin with?
I think the Java equivalent is:
for (int i = 0; i < aString.length(); i++){
char currentChar = aString.charAt(i);
System.out.println(currentChar);
}
I have the same problem. I usually resort to String#split:
"ABCDEFG".split("").each do |i|
puts i
end
I guess you could also implement it yourself like this:
class String
def each_char
self.split("").each { |i| yield i }
end
end
Edit: yet another alternative is String#each_byte, available in Ruby 1.8.6, which returns the ASCII value of each char in an ASCII string:
"ABCDEFG".each_byte do |i|
puts i.chr # Fixnum#chr converts any number to the ASCII char it represents
end
Extending la_f0ka's comment, esp. if you also need the index position in your code, you should be able to do
s = 'ABCDEFG'
for pos in 0...s.length
puts s[pos].chr
end
The .chr is important as Ruby < 1.9 returns the code of the character at that position instead of a substring of one character at that position.
"ABCDEFG".chars.each do |char|
puts char
end
also
"ABCDEFG".each_char {|char| p char}
Ruby version >2.5.1
there is really a problem in 1.8.6.
and it's ok after this edition
in 1.8.6,you can add this:
requre 'jcode'
But now you can do much more:
a = "cruel world"
a.scan(/\w+/) #=> ["cruel", "world"]
a.scan(/.../) #=> ["cru", "el ", "wor"]
a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
Returns an array of characters in str. This is a shorthand for str.each_char.to_a. If a block is given, which is a deprecated form, works the same as each_char.
from ruby-doc.org
also now you can do string.chars

What's the opposite of chr() in Ruby?

In many languages there's a pair of functions, chr() and ord(), which convert between numbers and character values. In some languages, ord() is called asc().
Ruby has Integer#chr, which works great:
>> 65.chr
A
Fair enough. But how do you go the other way?
"A".each_byte do |byte|
puts byte
end
prints:
65
and that's pretty close to what I want. But I'd really rather avoid a loop -- I'm looking for something short enough to be readable when declaring a const.
If String#ord didn't exist in 1.9, it does in 2.0:
"A".ord #=> 65
In Ruby up to and including the 1.8 series, the following will both produce 65 (for ASCII):
puts ?A
'A'[0]
The behavior has changed in Ruby 1.9, both of the above will produce "A" instead. The correct way to do this in Ruby 1.9 is:
'A'[0].ord
Unfortunately, the ord method doesn't exist in Ruby 1.8.
Try:
'A'.unpack('c')
I'd like to +1 dylanfm and AShelly's comment but add the [0]:
'A'.unpack('C')[0]
The unpack call returns an Array containing a single integer, which is not always accepted where an integer is wanted:
$ ruby -e 'printf("0x%02X\n", "A".unpack("C"))'
-e:1:in `printf': can't convert Array into Integer (TypeError)
from -e:1
$ ruby -e 'printf("0x%02X\n", "A".unpack("C")[0])'
0x41
$
I'm trying to write code that works on Ruby 1.8.1, 1.8.7 and 1.9.2.
Edited to pass C to unpack in uppercase, because unpack("c") gives me -1 where ord() gives me 255 (despite running on a platform where C's char is signed).
Just came across this while putting together a pure Ruby version of Stringprep via RFCs.
Beware that chr fails outside [0,255], instead use 1.9.x - 2.1.x portable replacements:
[22] pry(main)> "\u0221".ord.chr
RangeError: 545 out of char range
from (pry):2:in 'chr'
[23] pry(main)> x = "\u0221".unpack('U')[0]
=> 545
[24] pry(main)> [x].pack('U')
=> "ȡ"
[25] pry(main)>
Additionally, if you have the char in a string and you want to decode it without a loop:
puts 'Az'[0]
=> 65
puts 'Az'[1]
=> 122
How about
puts ?A
You can have these:
65.chr.ord
'a'.ord.chr
If you don't mind pulling the values out of an array, you can use "A".bytes
I'm writing code for 1.8.6 and 1.9.3 and I couldn't get any of these solutions to work in both environments :(
However, I came across another solution:
http://smajnr.net/2009/12/ruby-1-8-nomethoderror-undefined-method-ord-for-string.html
That didn't work for me either but I adapted it for my use:
unless "".respond_to?(:ord)
class Fixnum
def ord
return self
end
end
end
Having done that, then the following will work in both environments
'A'[0].ord

Resources