fairyduststars
fairyduststars

Reputation: 27

Simple program but so very stuck- Loops in Ruby

I have to write a program which asks the user to enter a number. The program keeps on asking the user for a number until the user types 'Stop' at which point the sum of the numbers that the user has entered should be printed. I've tried many,many things and none of my ideas work. This is what I have - but I can that it isn't correct. What am I doing wrong?

I've only used while loops and arrays

total_user_input = []
# As long as the user inputs a number, the program will keep putting Give me a number
# and then adding that number to the total_user_input array.
puts "Give me a number: "
while user_input = gets.chomp.to_i
  #add the input to the array total_user_input
  total_user_input.push(user_input.to_i)
  puts "Give me a number: "
  # If the user however types stop, then the loop is broken and we jump down to the
  # sum bit - where all of the numbers in the total_user_input array are added together
  # and printed. End of program!
  if user_input == "stop"
    break
  end
  sum = 0
  total_user_input.each { |num| 
    sum += num
  }
  puts sum
end

The output isn't as it should be.

Upvotes: 1

Views: 680

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110665

As others have identified the problems with your code let me suggest how you might reorganize it. Ruby provides many ways to execute loops but you many find it desirable to primarily relay on the method Kernel#loop and the keyword break. (As you will learn in time, loop is particularly convenient when used with enumerators.)

def sum_numbers
  tot = 0
  loop do
    print 'Gimme a number: '
    s = gets.chomp
    break if s == 'Stop'
    tot += s.to_i
  end
  tot
end

The keyword break can optionally take an argument (though why that is not mentioned in the doc I cannot say), in which case it (if a literal) or its value (if a variable or method) is returned by loop. Here one would generally see

    break tot if s == 'Stop'

without the final line, tot. As the loop returns tot and that is the last calculation performed by the method, the method will return the final value of tot.

You could have instead written

return tot if user_input == 'Stop'

but I think most coders believe best practice dictates that one should not return from a method from within a loop (or from within nested loops) unless there is a good reason for doing so.

Some small points:

  • I used print rather than puts to that the user's entry will be shown on the same line as the prompt.
  • I used s (for "string") rather than user_input because it reduces the chance of spelling mistakes (e.g., user_imput), speeds reading, and (possibly a foible of mine), looks neater. True, s is not descriptive, but one only has to remember its meaning for three consecutive lines of code. Others may disagree.
  • You could write, break if s.downcase == 'stop' if you want, say, 'stop' or 'STOP' to have the same effect as 'Stop'.
  • '23O3'.to_i #=> 23 (that's an an oh, not a zero), so in real life you'd want to confirm that either 'Stop' or the string representation of a number had been typed.

Upvotes: 2

lacostenycoder
lacostenycoder

Reputation: 11196

This is how I would do this preferring to use loop do end syntax with a break when it should. Also added a bit more text so user knows what's happening.

total_user_input = []
puts 'Give me a number or "stop" to end: '
loop do
  user_input = gets.chomp
  total_user_input << user_input.to_i
  puts "Give me a number: "
  break if user_input.downcase == "stop"
end
puts "Total entered: #{total_user_input.inject(&:+)}" unless total_user_input.empty?
puts 'goodbye!'

Upvotes: 1

blitzblade
blitzblade

Reputation: 136

Note these few things:

  1. get.chomp.to_i will convert every input to integer. ("stop" or any non integer string will be 0)
  2. Arrangement of the flow is quite messy.
total_user_input = []

puts "Give me a number: "
while user_input = gets.chomp.strip
  total_user_input.push(user_input.to_i)
  sum = 0
  total_user_input.each { |num| 
    sum += num
  }
  puts sum

  if user_input == "stop"
    break
  end

end

Hope you understand this.

Upvotes: 0

Related Questions