Hi! I’m very new to this site so sorry if this is in the wrong place, as well new to coding in general. I have this project for a class (Honestly the last assignment I’m doing since I’ve decided coding is not for me so I’m switching majors.) where I am trying to create a journal or diary that accepts user input and allows them to search by index entry or by string. I have been successful in finding by index but getting to where I can determine if the user input is string or not is the problem. Here is my code so far.
puts 'Type in as many words as you\'d like. When you\'re finished, press enter on an empty line'
array = []
input = ' '
while input != ''
input = gets.chomp
array.push input
end
loop do
puts "Great! If you wish to recall a previous entry please insert the number of it below! If you can not recall the number of the entry then please type Search"
ans = gets.chomp.to_i
if ans > 0 && ans <= array.length
puts "The element at position #{ans} is " + array[ans-1]
break
elsif ans < 0
puts "You have to pick a number greater than 0!"
if ans == "Search"
puts 'What would you like to search for?'
else
puts 'That is not a valid search!'
end
end
end
So the problem with the above code currently is that I made ans = gets.chomp.to_i therefore string input is made into an integer. I realize this but I am unsure how to code it to determine whether or not user input is string or integer and giving a different response based on that. Hoping to get something like this
if user input = string and user input == Search,
then put “Please type your search here!”
if user input = integer
puts "The element at position #{ans} is " + array[ans-1] (this is what I already have)
print 'Type a Number: '
puts STDIN.gets.tap(&:strip!).then { |x| x.to_i.to_s == x ? x.to_i : "Enter a number \xF0\x9F\x98\x92" }
Running:
bash [$] ruby p.rb
Type a Number: 5
5
bash [$] ruby p.rb
Type a Number: hi
Enter a number 😒
Do note that sometimes STDIN.gets can return nil. For example if you run this on Atom Runner or Code Runner, it will not work. It’s a good idea to write STDIN.gets.to_s this will ensure you get a string, and this doesn’t create new string if STDIN.gets returns string, on the other hand, nil.to_s does create a new string.
if usr_input > 0
puts “do stuff”
else
puts “invalid entry”
end
Basically what’s going on here is you are coverting the gets value into a integer. 0 is your place holder, or how you can tell the code is a string or not. Example:
puts “any kind of string data when paired with .to_i always comes back 0. even if numbers are present.”.to_i
=> 0
puts “123”.to_i
=> 123.
puts “a1 b3 c3”.to_i
=> 0
So knowing this,
If the gets.to_i returns a 0, means there’s a letter in the user input given. If it returns any integer higher than 0 then it will act accordingly.
Hi @Cufe, I want to mention that the chomp in usr_input = gets.chomp.to_i is not needed. It’s just wastage of computing. gets.to_i will do the job fine…
Tiny thing but commented because IDK but many newbies write chomp and chain to_i. Let me tell that “100\n” or “100abcd1234” when chained to to_i will return 100 always.
Also gets is not only used to get a string, it first checks for command line arguments. If you have the argument it reads the file passed as argument. For example, on my shell:
archlinux% cat p.rb
#!/usr/bin/env ruby
$-v = true
puts gets.to_i
archlinux% ruby p.rb
hi
0
archlinux% ruby p.rb 123
Traceback (most recent call last):
2: from p.rb:4:in `<main>'
1: from p.rb:4:in `gets'
p.rb:4:in `gets': No such file or directory @ rb_sysopen - 123 (Errno::ENOENT)
archlinux%
Believe me, the .chomp is not useless. Especially when you are working with the Kernel, File, and Dir classes.
gets will always return a string. Always. So there isn’t really a way to check between a string or integer using gets method. However, you can convert the gets string data into a integer.
For example, if you’re trying to build a menu base, and want to use numbers, gets.chomp.to_i is the best way to go. . chomp cleans up and makes sure that it only takes the data you need.
With this being said, It’s a rookie mistake to try to use gets to try to figure out strings and integers. It can only a string, or a integer if .to_i is applied. eval is better suited for this job. Gets always returns as a string, that can be converted. eval evaluates user input and runs it accordingly.
In other words, building a REPL using gets method makes it Static because you have to hard code everything and all user options.
Where using eval gives you more dynamic functions. In fact That’s what a REPL is. Read Eval Print Loop. Now pay attention because this is what seperates beginner programmers and pros in ANY language. If you understand how a REPL works, you understand the core concept of computer science and command line operating systems. The Linux CLI is a REPL. IRB and let are REPLs. In fact, I will show you the line of code that IRB and pry are built on.
def repl
loop{ puts eval.$stdin.readline)
end
If course it’s not called repl, however that is the one line of code that makes IRB and pry.
Knowing the difference between gets and eval helps greatly.