What's the difference between gets.chomp() vs. STDIN.gets.chomp()?
gets
will use Kernel#gets
, which first tries to read the contents of files passed in through ARGV
. If there are no files in ARGV
, it will use standard input instead (at which point it's the same as STDIN.gets
.
Note: As echristopherson pointed out, Kernel#gets
will actually fall back to $stdin
, not STDIN
. However, unless you assign $stdin
to a different input stream, it will be identical to STDIN
by default.
http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-gets
Difference between $stdin and others gets.chomp
When invoking gets
without specifying the stream, we are invoking Kernel#gets and when stream is specified we are invoking IO#gets
I believe Kernel#gets
wraps around IO#gets
under the hood but before it needs to create an IO object, that IO object will be a concatenation of all command line arguments(ARGV) ( it will try to open every single one as file in positional order) and them read from it. If there are no elements left on ARGV it will then read from stdin.
That behavior can be tested with this simple snippet:
while gets
puts $_
end
When running ruby myscript.rb
without parameters it will read stdin, if parameters are specified it will try to open as files and read from it, it will works similarly to cat
command .
That stream could be tty, socket, file etc:
stream = File.open('/etc/passwd','r')
puts stream.gets
stream.close
A simple http client using sockets:
require 'socket'
s = TCPSocket.new 'icanhazip.com',80
s.puts <<~EOF
GET / HTTP/1.1
Host: icanhazip.com
EOF
while line = s.gets
puts line
end
s.close
More about Kernel#gets here
More about IO#gets
Ruby: What's the difference between STDIN.gets() and gets.chomp()?
Easiest way to do what you describe here is Integer(gets)
, since Integer()
ignores the trailing newline, so chomp
is unnecessary. There's also no need explicitly specify STDIN
as the receiver, as that's what Kernel#gets will do if there are no arguments to the script.
How to use gets and gets.chomp in Ruby
gets
lets the user input a line and returns it as a value to your program. This value includes the trailing line break. If you then call chomp
on that value, this line break is cut off. So no, what you have there is incorrect, it should rather be:
gets
gets a line of text, including a line break at the end.- This is the user input
gets
returns that line of text as a string value.- Calling
chomp
on that value removes the line break
The fact that you see the line of text on the screen is only because you entered it there in the first place. gets
does not magically suppress output of things you entered.
Difference between ways to use gets method
"Flushing" the output ensures that it shows the printed message before it waits for your input; this may be just someone being certain unnecessarily, or it may be that on certain operating systems you need it. Alternatively you can use STDOUT.sync = true
to force a flush after every output. (You may wonder, "Why wouldn't I always use this?" Well, if your code is outputting a lot of content, repeatedly flushing it may slow it down.)
chomp
removes the newline from the end of the input. If you want the newline (the result of the user pressing "Enter" after typing their name) then don't chomp
it.
Cannot get the correct input using STDIN.gets.chomp() in ruby
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
Gets.chomp input comparison returning an error
The input is a string. Try something like this
puts "Age: "
user_input = gets.chomp
begin
age = Integer(user_input)
# your code
rescue ArgumentError
puts "Age must be an integer"
end
How do I combine gets.chomp and ARGV in Ruby?
I answered a question about this yesterday, which you can read here, but to address your situation specifically:
After first, second, third = ARGV
, call ARGV.clear
to empty it out.
Alternatively you could do first, second, third = 3.times.map { ARGV.shift }
The reason is that gets
reads from ARGV if there's anything in it. You need to empty ARGV out before calling gets
.
Related Topics
Problems with the Rails Console, Rvm and Readline
How Can an Activerecord::Relation Object Call Class Methods
Colon (:) Appears as Forward Slash (/) When Creating File Name
Ruby 1.9 Hash with a Dash in a Key
Mocha Mock Carries to Another Test
Nokogiri Was Built Against Libxml Version 2.7.7, But Has Dynamically Loaded 2.7.3
Tell Ruby Program to Wait Some Amount of Time
Create Module Variables in Ruby
Calling Another Method in Super Class in Ruby
What's the Best Way to Handle Exceptions from Net::Http
How Does Shovel (<<) Operator Work in Ruby Hashes
How to Run a Ruby Script Using Rbenv with Cron
Set Attribute Dynamically of Ruby Object
How to Make Part of a Regular Expression Optional in Ruby
Double-Splat Operator Destructively Modifies Hash - Is This a Ruby Bug