Difference between gets, gets.chomp and gets.chomp!? - ruby

What is the difference between these three:
gets - it gets a line with '\n'
gets.chomp - it gets a line, but removes '\n'
Is that correct? What about gets.chomp! ?

gets - it gets a string with '\n' at the end ( or better to say the line separator $/ at the end) , then #chomp removes the \n ( or I would say the default value of $/),and give you a new string. But #chomp! did the same change in the receiver or the source string itself, on which you called #chomp! method.
Note : #chomp! is a bang version of #chomp.

Related

How do I receive multiple paragraphs from a user in Ruby2.6.3?

I'm trying to receive multiple paragraphs at once from a user.
I've tried using gets, but it doesn't seem to be working... it discards the second paragraph:
#The code:
print("Paste your text here: ")
.. essay = gets
.. puts(essay)
# Getting user imput (the second sentance is a separate paragraph)
Paste your text here: I like cake.
It makes me happy.
# What the computer did for puts(essay):
I like cake.
=> nil
I expected the result to be something like this:
"I like cake.\nIt makes me happy.\n"
But it gave me "I like cake." instead.
How could I end up with my expected result?
Add paragraphs to a string until the input consists of a empty line:
str = ""
para = "init"
str << (para = gets) until para.chomp.empty? #or para == "\n"
p str
Here's an alternative, with a slightly different logic
def getps
save, $/ = $/, "\n\n"
gets.chomp
ensure
$/ = save
end
str = getps
The global variable $/ is what Ruby uses to find out what line end is. gets gets things till line end. If we tell Ruby that line end is two newlines, then gets waits till we have two newlines in a row till it exits. Since we don't need them, we'll just chomp them off. The rest of the code is just to ensure that $/ gets restored properly afterwards so normal gets is not messed up forever.

index out of string, ruby

Here's a small part of my code, pretty self explanatory, it copies all characters to temp from input and skips spaces.
input = gets.to_s.chomp
temp=String.new
for i in 0..input.length-1
if (input[i]==" ")
next
else
temp[i]=input[i]
end
end
puts "#{temp},END"
gets
However, i tested it with a 'hello world' input, and it should've given me helloworld But i'm getting
8:in '[]=':index 6 out of string(IndexError)
meaning the problem starts while it's skipping the space, for some reason.
keep in mind that i don't get any errors if i put a string that doesn't contain a space
Whenever string manipulation is required, it may be desirable to convert the string to an array of its parts, manipulate those parts and then join them back into a string, but more often as not it is simpler to just operate on the string itself, mainly using methods from the class String. Here you could Kernel#puts the following.
"%s END" % gets.delete(" \n")
#=> "helloworld"
String#delete removes both spaces and the return character ("\n") that Kernel#gets tacks onto the end of the string that is entered. A variant of this is "%s END" % gets.chomp.delete(" ").
Another way would be to puts
"%s END" % gets.gsub(/\s/, '')
#=> "helloworld"
The regular expression /\s/, causes String#gsub to remove all whitespace, which includes both spaces (and tabs) that are entered and the "\n" that gets tacks on to the end of the string.
I guess your error is due to the difference between the string 'hello world' and that you're "rejecting" whitespaces. In such case, for each whitespace in the string being used, the temp will have one less.
You can assign the input[i] when isn't a whitespace to the temp variable in the position temp.size, this way you don't skip indexes.
It could be temp[temp.size] or just modifying temp with +=.
for i in 0...input.size
if input[i] == ' '
next
else
temp[temp.size] = input[i]
end
end
Note you can replace the for loop for each (the Ruby way):
input = 'hello world'
temp = ''
(0...input.size).each do |index|
input[index] == ' ' ? next : temp[temp.size] = input[index]
end
# helloworld
If you want to skip all white spaces from your input and print the output, you can do so with a one-liner:
puts "#{gets.chomp.split.join}, END"
In ruby, you hardly need to write loops using for construct unlike other traditional languages like Java.

How to use "gets" and "gets.chomp" in Ruby

I learned that gets creates a new line and asks the user to input something, and gets.chomp does the same thing except that it does not create a new line. gets must return an object, so you can call a method on it, right? If so, lets name that object returned by gets as tmp, then you can call the chomp method of tmp. But before gets returns tmp, it should print a new line on the screen. So what does chomp do? Does it remove the new line after the gets created it?
Another way to re-expound my question is: Are the following actions performed when I call gets.chomp?
gets prints a new line
gets returns tmp
tmp.chomp removes the new line
User input
Is this the right order?
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.
The question shouldn't be "Is this the right order?" but more "is this is the right way of approaching this?"
Consider this, which is more or less what you want to achieve:
You assign a variable called tmp the return value of gets, which is a String.
Then you call String's chomp method on that object and you can see that chomp removed the trailing new-line.
Actually what chomp does, is remove the Enter character ("\n") at the end of your string. When you type h e l l o, one character at a time, and then press Enter gets takes all the letters and the Enter key's new-line character ("\n").
1. tmp = gets
hello
=>"hello\n"
2. tmp.chomp
"hello"
gets is your user's input. Also, it's good to know that *gets means "get string" and puts means "put string". That means these methods are dealing with Strings only.
chomp is the method to remove trailing new line character i.e. '\n' from the the string.
whenever "gets" is use to take i/p from user it appends new line character i.e.'\n' in the end of the string.So to remove '\n' from the string 'chomp' is used.
str = "Hello ruby\n"
str = str.chomp
puts str
o/p
"Hello ruby"
chomp returns a new String with the given record separator removed from the end of str (if present).
See the Ruby String API for more information.
"gets" allows user input but a new line will be added after the string (string means text or a sequence of characters)
"gets.chomp" allows user input as well just like "gets", but there is
not going to be a new line that is added after the string.
Proof that there are differences between them:
Gets.chomp
puts "Enter first text:"
text1 = gets.chomp
puts "Enter second text:"
text2 = gets.chomp
puts text1 + text2
Gets:
puts "Enter first text:"
text1 = gets
puts "Enter second text:"
text2 = gets
puts text1 + text2
Copy paste the code I gave you, run and you will see and know that they are both different.
For example:
x = gets
y = gets
puts x+y
and
x = gets.chomp
y = gets.chomp
puts x+y
Now run the two examples separately and see the difference.

How to receive data from user without ruby adding an extra newline

I am trying to create a program that alphabetizes a users' word entries. However, inspection of the users entries reveals that ruby is for some reason adding a newline character to each word. For instance, If i enter Dog, Cat, Rabbit the program returns ["Cat\n", "Dog\n", "Rabbit\n"] How do i prevent this from happening?
words = []
puts "Enter a word: "
until (word = gets).to_s.chomp.empty?
puts "Enter a word: "
words << word
end
puts words.sort.inspect
Change your code to:
until (word = gets.chomp).empty?
The way you're doing it now:
(word = gets).to_s.chomp.empty?
gets the string from the keyboard input, but it isn't returned to your code until the user presses Return, which adds the new-line, or carriage-return + new-line on Windows.
to_s isn't necessary because you're already getting the value from the keyboard as a string.
chomp needs to be tied to gets if you want all the input devoid of the trailing new-line or new-line/carriage-return. That will work fine when testing for empty?.
Ruby 2.4 has a solution for this:
input = gets(chomp: true)
# "abc"

ruby code for modifying outer quotes on strings?

Does anyone know of a Ruby gem (or built-in, or native syntax, for that matter) that operates on the outer quote marks of strings?
I find myself writing methods like this over and over again:
remove_outer_quotes_if_quoted( myString, chars ) -> aString
add_outer_quotes_unless_quoted( myString, char ) -> aString
The first tests myString to see if its beginning and ending characters match any one character in chars. If so, it returns the string with quotes removed. Otherwise it returns it unchanged. chars defaults to a list of quote mark characters.
The second tests myString to see if it already begins and ends with char. If so, it returns the string unchanged. If not, it returns the string with char tacked on before and after, and any embedded occurrance of char is escaped with backslash. char defaults to the first in a default list of characters.
(My hand-cobbled methods don't have such verbose names, of course.)
I've looked around for similar methods in the public repos but can't find anything like this. Am I the only one that needs to do this alot? If not, how does everyone else do this?
If you do it a lot, you may want to add a method to String:
class String
def strip_quotes
gsub(/\A['"]+|['"]+\Z/, "")
end
end
Then you can just call string.strip_quotes.
Adding quotes is similar:
class String
def add_quotes
%Q/"#{strip_quotes}"/
end
end
This is called as string.add_quotes and uses strip_quotes before adding double quotes.
This might 'splain how to remove and add them:
str1 = %["We're not in Kansas anymore."]
str2 = %['He said, "Time flies like an arrow, Fruit flies like a banana."']
puts str1
puts str2
puts
puts str1.sub(/\A['"]/, '').sub(/['"]\z/, '')
puts str2.sub(/\A['"]/, '').sub(/['"]\z/, '')
puts
str3 = "foo"
str4 = 'bar'
[str1, str2, str3, str4].each do |str|
puts (str[/\A['"]/] && str[/['"]\z/]) ? str : %Q{"#{str}"}
end
The original two lines:
# >> "We're not in Kansas anymore."
# >> 'He said, "Time flies like an arrow, Fruit flies like a banana."'
Stripping quotes:
# >> We're not in Kansas anymore.
# >> He said, "Time flies like an arrow, Fruit flies like a banana."
Adding quotes when needed:
# >> "We're not in Kansas anymore."
# >> 'He said, "Time flies like an arrow, Fruit flies like a banana."'
# >> "foo"
# >> "bar"
I would use the value = value[1...-1] if value[0] == value[-1] && %w[' "].include?(value[0]). In short, this simple code checks whether first and last char of string are the same and removes them if they are single/double quote. Additionally as many as needed quote types can be added.
%w["adadasd" 'asdasdasd' 'asdasdasd"].each do |value|
puts 'Original value: ' + value
value = value[1...-1] if value[0] == value[-1] && %w[' "].include?(value[0])
puts 'Processed value: ' + value
end
The example above will print the following:
Original value: "adadasd"
Processed value: adadasd
Original value: 'asdasdasd'
Processed value: asdasdasd
Original value: 'asdasdasd"
Processed value: 'asdasdasd"

Resources