Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do user input in Crystal

Tags:

crystal-lang

puts "Input a number"
A = gets.try(&.to_i) || 0
puts "Ok now another number"
B = gets.try(&.to_i) || 0

def main 
    puts "Value of multiplication is #{A} * #{B}, Which equals = #{A * B}"
    puts "Value of addition is #{A} + #{B}, Which equals = #{A + B}"
    puts "Value of division is #{A} / #{B}, Which equals = #{A / B}"
    puts "Value of minus is #{A} - #{B}, Which equals = #{A - B}"
    puts "Value of modulus is #{A} % #{B}, Which equals = #{A % B}"
end 

main

I am wondering what the most simplest way to get user inputs from integers in Crystal would be? Similar to Ruby's gets.chomp.to_i

like image 964
learncodes123 Avatar asked Jul 26 '18 06:07

learncodes123


2 Answers

To get user input you have to understand how gets works. It will return a String when the user inputs something, or nil when the user didn't input anything (for example the user pressed ctrl+C).

In Ruby if you do:

x = gets.chomp.to_i

and run it, but press ctrl+C you get an ugly exception printed on the screen. Maybe that's acceptable, but it's something that Crystal won't less you pass that easily because Crystal is type safe and you will have to deal with this case. Maybe you want to print something nice to the user instead of an exception?

Ways to deal with Nil are explained here: https://crystal-lang.org/api/0.25.1/Nil.html

For example you can do:

a = gets
if a # if a is a String
  a = a.chomp.to_i # turn it into an integer
else
  exit # just silently quit the program
end

Another way is to use to_nil!, which will essentially raise an exception in case the value is nil:

a = gets.not_nil!.chomp.to_i

That's more similar to Ruby, in that you'll get an exception shown in the console when the user quits with ctrl+C. The key difference is that Crystal is letting you know (through nil) that this possibility can happen and that you should choose what to do in this case.

There are more ways to deal with this case (like the try solution suggested in other comments), depending on how terse you want the code to be.

A final alternative which is closer to Ruby is to use read_line, which will raise in case there's no input, so you can just do:

a = read_line.chomp.to_i

(though in my experiment right now it doesn't seem to be raising, I have no idea why, probably some bug...)

like image 200
asterite Avatar answered Nov 08 '22 07:11

asterite


This will do what you want such that the program will not continue until the user gives you a valid int. If you want to simply throw an error instead then you don't need a loop or a try-catch statement.

while true
  puts "give me a valid int:"
  begin
    i = gets.not_nil!.to_i
    break
  rescue
    puts "that wasn't a valid int."
  end
end
puts "you gave me: #{i}"
like image 2
Sam Johnson Avatar answered Nov 08 '22 09:11

Sam Johnson