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) является брошенный. Тем не менее, строка никогда не бывает пустой, поэтому проверка условия не имеет смысла для меня.
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:NilClassnil, а затем вызываетchomp!Загляните в историю редактирования этого ответа, если вы хотите получить больше полезных советов для новичков. Я удалил их, потому что они не имеют отношения к этому ответу.
Comments