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
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.
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
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.
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
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
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
How to See the Dependency Tree Just from Gemfile
Modify Ruby Hash in Place( Rails Strong Params)
Writing Over Previously Output Lines in the Command Prompt with Ruby
Repairing Postgresql After Upgrade to Osx Mavericks
Ruby - Determine If a Number Is a Prime
Full Url for an Image-Path in Rails 3
Ruby Methods and Optional Parameters
How to Get Elapsed Time in Milliseconds in Ruby
Rails 4 How to Ignore Pending Migrations
Should One Use Dashes or Underscores When Naming a Gem with More Than One Word
Is There a "Main" Method in Ruby Like in C
How to Display a PDF in Ror (Ruby)
Rails Migration Changing Column to Use Postgres Arrays
How to Do Basic Authentication with Restclient
Bundler Could Not Find Compatible Versions for Gem "Bundler":
How to Use the Rails Helper "Distance_Of_Time_In_Words" in Plain Old Ruby (Non-Rails)