Reputation: 27
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
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:
print
rather than puts
to that the user's entry will be shown on the same line as the prompt.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.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
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
Reputation: 136
Note these few things:
get.chomp.to_i
will convert every input to integer. ("stop" or any non integer string will be 0)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