3

I am following the LearnRubyTheHardWay tutorial and having a difficulty in modifying the exercise 29. Everything works fine if I define the variables like (as in the tutorial):

people = 100000
cats = 34
dogs = 56

However, if I try to get the variables from STDIN like:

puts "How many people are here?"
people = STDIN.gets.chomp()
puts "How many cats?"
cats = STDIN.gets.chomp()
puts "And how many dogs?"
dogs = STDIN.gets.chomp()

The equality operators return false results as if they only do calculate the results using the first two digits of the numbers. So if I type 100000000 to people and 11, 12 or 13 to cats, the methods return "Too many cats.." If I type 150000000 to people and anything <15 to cats, they return "Not many cats.." Additionally I have to modify

dogs += 5

to

dogs += "5"

otherwise I get the following error: in `+': can't convert Fixnum into String (TypeError)

If I leave the double quotes in place and revert to people = 10000 stuff, I get the following error: in `+': String can't be coerced into Fixnum (TypeError)

So to say, I have no problem with the code in the tutorial, just try to learn what causes the errors introduced by the STDIN methods. I looked into the RubyDoc.org, to see whether it is an issue with fixnum, integer or string classes or anything related to chomp or gets methods but couldn't find the reason. I also tried to_i and to_s before or after but didn't get any result.

The full source code of the file is below:

puts "How many people are here?"
people = STDIN.gets
puts "How many cats?"
cats = STDIN.gets
puts "And how many dogs?"
dogs = STDIN.gets

#people = 100000
#cats = 34
#dogs = 56

puts "So, %d people, %d cats and %d dogs, huh?" % [people,cats,dogs]

if people < cats
  puts "Too many cats! The world is doomed!"
end

if people > cats
  puts "Not many cats! The world is saved!"
end

if people < dogs
  puts "The world is drooled on!"
end

if people > dogs
  puts "The world is dry!"
end

dogs += "5"
puts "Now there are #{dogs} dogs."

if people >= dogs
  puts "People are greater than or equal to dogs."
end

if people <= dogs
  puts "People are less than or equal to dogs."
end

if people == dogs
  puts "People are dogs."
end

1 Answer 1

4

The problem is that STDIN.gets returns a string. All the comparison operations will therefore operate on strings. Example:

people = "100000000"
cats = "11"

puts people < cats  # => true!

This is because < will compare the strings lexicographically (and 1000... comes before 11 in the alphabet). There is actually one point in your example that makes it pretty obvious what's going on here:

dogs = STDIN.gets
dogs += "5"

If you input 7 here, it should print out 75. You see, it just concatenates the strings.

How to fix this? Easy, just convert the strings to integers:

puts "How many people are here?"
people = STDIN.gets.to_i
puts "How many cats?"
cats = STDIN.gets.to_i
puts "And how many dogs?"
dogs = STDIN.gets.to_i
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, I tried people.to_i but now I see that I forgot to do it like "people = people.to_i". I haven't seen anything like STDIN.geti instead of gets. Is there any placeyou can suggest to study methods other than rubydoc.org?
@barerd: There exists no such thing as STDIN.geti. You use gets.to_i, so the gets method is called on the STDIN file stream object, and then to_i is called on the resulting String object. If you want to get an overview over the available methods, you can use apidock, which is a bit more structered then rubydoc. However, it's probably better to get a basic understanding of the language first (tutorials are good for that).
Apidock is going to be a nice compliment to the tutorial. Thank you for that, too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.