Ruby-как проверить наличие нулевой или пустой строки из консоли (stdin)



Я очень новичок в Руби, поэтому, пожалуйста, потерпите меня... В тексте на Ruby есть пример кода, который делает это:



str = gets
exit if str.nil? || str.empty?
str.chomp!
temp, scale = str.split(" ")


Мои запросы следующие:



Учитывая, что gets будет возвращаться только до и включая cr зачем тестировать пустую строку?



Если вы проверяете следующее:



puts nil.to_s.empty?
puts "".to_s.empty?
puts "".length #the empty string : equates to 0
puts nil.to_s.length #the 'to string' method: equates to 0


Оба будут оцениваться как истинные и иметь нулевую длину. Однако единственное, что есть в потоке, если есть только cr, это возврат кареты сам по себе. str будет иметь длину 1 в следующем, если вы просто нажмете клавишу enter.



print "enter a string or hit the enter key : "
str = gets
puts str.length
puts str


Кроме того, nil в ruby является объект. Как, черт возьми, я должен захватить это из stdin?



Теперь я вижу, что chomp! неуместно в тексте, ошибка автора не моя:



str = gets
str.chomp!
exit if str.nil? || str.empty? #test for zero length string will now work
temp, scale = str.split(" ")


Конечно, я пришел из java и некоторого общего Лиспа и поэтому, возможно, слишком устарел, чтобы грокнуть это, но я все еще не вижу, как в этом контексте уместен тест для nil. Возможно, есть некоторые концептуальные различия в потоках, которые находятся дальше, чем мое чтение. Заранее спасибо.



Редактировать:



Чтобы прояснить некоторую путаницу, здесь код переписан только с изменением размещения оператора chomp!:



#temperature-converter.rb
#code changed by poster, otherwise as written by author
print "Please enter a temperature and scale (C or F) : "
STDOUT.flush #self explanatory....
str = gets
str.chomp! #new placement of method call -- edit by poster
exit if str.nil? || str.empty?
#chomp! original position -- by author
temp, scale = str.split(" ")
abort "#{temp} is not a valid number." if temp !~ /-?d+/
temp = temp.to_f
case scale
when "C", "c"
f = 1.8 * temp + 32
when "F", "f"
c = (5.0/9.0) * (temp - 32)
else
abort "Must specify C or F."
end
if f.nil?
puts "#{c} degrees C"
else
puts "#{f} degrees F"
end


И вывод:



=>ruby temperature-converter.rb
Please enter a temperature and scale (C or F) : 30 c
86.0 degrees F
=>ruby temperature-converter.rb
Please enter a temperature and scale (C or F) : j c
j is not a valid number.
=>ruby temperature-converter.rb
Please enter a temperature and scale (C or F) : 30 p
Must specify C or F.
=>ruby temperature-converter.rb
Please enter a temperature and scale (C or F) : #just the enter key
=> #did this just exit?!


Но выбранный мной ответ верен, если вы используете Ctl+D (U) или Ctl+Z (W)
eof может быть эмулирован, и ошибка in '<main>': undefined method 'chomp!' for nil:NilClass (NoMethodError) является брошенный. Тем не менее, строка никогда не бывает пустой, поэтому проверка условия не имеет смысла для меня.

884   2  

2 ответов:

Из документации , gets может возвращать строку или nil:

Возвращает (и присваивает$_) следующую строку из списка файлов в ARGV (или $*), или из стандартного ввода, если на диске нет файлов. командная строка. Возвращает значение nil в конце файла.

Из стандартного ввода

Смотрите @MarkoAvlijaš ' ответ С CTRL+D.

Из ARGV

Можно создать пустой файл с именем empty.txt и запустить его :

ruby your_script.rb empty.txt

Ничего не должно случиться.

Если убрать вторую строку, то:

your_script.rb:3:in `<main>': undefined method `chomp!' for nil:NilClass (NoMethodError)

Я не вижу, как str может быть пустым с указанным выше кодом. По крайней мере, будет новая строка, если str не nil.

Обратите внимание, что если вы используете chomp! перед проверкой, что str не является nil, Вы можете получить NoMethodError.

gets может вернуть nil, если нажать CTRL+D (по крайней мере в irb)

CTRL+D-это сигнал unix, который означает, что я закончил печатать или конец файла.

Вот почему код в книге правильный. Ваша версия произведет NoMethodError в этом случае.
gets.chomp!
NoMethodError: undefined method `chomp!' for nil:NilClass
Вот почему он сначала тестирует для nil, а затем вызывает chomp!

Загляните в историю редактирования этого ответа, если вы хотите получить больше полезных советов для новичков. Я удалил их, потому что они не имеют отношения к этому ответу.

Comments

    Ничего не найдено.