需要澄清退出和中止脚本Ruby
我正在用需要澄清退出和中止脚本Ruby,ruby,Ruby,我正在用if和else编写一个小练习程序。代码如下: puts "What is your name?" user_name = $stdin.gets.chomp print "Hello #{user_name}! Welcome to Puzzles and Riddles v.1!" puts "There are two doors \n 1. Riddles \n 2. Puzzles. \n Which door do you go through?" answer_1 = $
if
和else
编写一个小练习程序。代码如下:
puts "What is your name?"
user_name = $stdin.gets.chomp
print "Hello #{user_name}! Welcome to Puzzles and Riddles v.1!"
puts "There are two doors \n 1. Riddles \n 2. Puzzles. \n Which door do you go through?"
answer_1 = $stdin.gets.chomp
if
answer_1 == "1"
puts "You have taken the Riddle room!"
print "Here is your riddle: \n You use a knife to slice my head and weep beside me when I am dead. \n What am I?"
end
riddle_1_answer = $stdin.gets.chomp
if
riddle_1_answer == ( riddle_1_answer == "An onion" ) || ( riddle_1_answer == "an onion" ) || ( riddle_1_answer == "Onion" ) || ( riddle_1_answer == "onion" )
puts "The correct answer is: An onion! \n You have advanced to round two."
else
puts "Sorry, your answer is incorrect. Think about it."
end
puts "Riddle 2. \n What has 4 fingers and a thumb, but is not living?"
riddle_2_answer = $stdin.gets.chomp
现在,如果用户答错了ridle\u 1\u answer
,我该如何使程序退出/中止?
我尝试将exit(0)添加到else部分,它将终止程序,但也会出现错误。因此,我不确定错误是否导致程序结束或退出(0)命令从您的问题、示例代码和对@AndrewMarshall的回答中可以明显看出,您需要一些指导 给你 首先,ruby是许多编程语言中的一种,许多有经验的程序员最终被它所吸引是有原因的:ruby是面向对象的、有表现力的、功能强大的,并且相当简洁,但不自然地简洁。所以,如果你想学习ruby,就要通过阅读大量优秀的ruby代码来学习,从中你会学到很多好的实践 其次,外观很重要,因为它影响或增强可读性和理解力。良好的外观有助于提高可读性和更快速的理解。坏的外表恰恰相反 代码中的
if
、else
和end
标记缺乏对齐是错误的;这使得很难看到代码逻辑的结构
编程有很多经验法则。以下是适用于大多数语言的一些规则:
- 正确使用对齐和缩进
- 始终考虑“边缘情况”(或错误)
- 限制和隔离复杂性(使用函数、模块、类和方法)
- 不要重复你自己(干)
puts "What is your name?"
user_name = $stdin.gets.chomp
- 如果用户输入CTRL-D(EOF)怎么办
- 如果用户输入一个空行怎么办
nil
,这会导致chomp
上出现错误
是否可以接受空字符串(零长度)名称?如果没有,我们该怎么办
如果在做一些相对简单的事情时存在复杂性,比如获取用户名,则将复杂性封装在函数或方法中,这样需要用户名的代码就不会因为获取用户名的复杂性而变得混乱
这是一个替代品。首先,让我们在一个小函数中管理获取用户名的细节(和复杂性)
def get_user_name
name = ''
while name.size == 0 do
print "What is your name? "
name = gets
exit(1) if name.nil? # exit program on EOF
name.strip!
end
name
end
请注意,在我们确保它不是nil
之前,我们不会在name
上使用chomp
。许多程序对输入的EOF作出反应,即退出、中止或继续,而不再提出任何问题。在本例中,我们假设用户想要退出
还要注意,我们使用了strip代码>而不是chomp代码>?那是因为strip
将删除前导和尾随空格,包括尾随换行符
还要注意,我们没有使用$stdin.get
,而是使用get
?这是因为获取的默认对象是$stdin
在小型函数(方法)中管理异常情况的更好方法可能是引发
异常,并让更高级别的应用程序逻辑决定如何管理它。考虑到这一点,这里有一个修订的定义:
def get_user_name
name = ''
while name.size < 1 do
print "What is your name? "
name = gets
raise "End of input" if name.nil? # raise exception on EOF
name.strip!
end
name
end
现在,让我们完成原始代码的其余部分,但要正确对齐和缩进
print "Hello #{user_name}! Welcome to Puzzles and Riddles v.1!"
puts "There are two doors \n 1. Riddles \n 2. Puzzles. \n Which door do you go through?"
answer_1 = $stdin.gets.chomp
if answer_1 == "1"
puts "You have taken the Riddle room!"
print "Here is your riddle: \n You use a knife to slice my head and weep beside me when I am dead. \n What am I?"
end
riddle_1_answer = $stdin.gets.chomp
if riddle_1_answer == ( riddle_1_answer == "An onion" ) || ( riddle_1_answer == "an onion" ) || ( riddle_1_answer == "Onion" ) || ( riddle_1_answer == "onion" )
puts "The correct answer is: An onion! \n You have advanced to round two."
else
puts "Sorry, your answer is incorrect. Think about it."
end
puts "Riddle 2. \n What has 4 fingers and a thumb, but is not living?"
riddle_2_answer = $stdin.gets.chomp
既然对齐和缩进是正确的,就更容易看到逻辑及其缺陷。查看逻辑模式也更容易,每当您看到一个模式时,就将其晾干,并制作方法(函数)来封装重复
但首先,让我们修复明显的bug
if
表达式已损坏。再看一遍,你会看到:
if riddle_1_answer == TEST1 || TEST2 || TEST3 || TEST4
在这里,我使用了TEST
n来替换您进行的各种区分大小写的测试
此if
表达式将始终失败,因为谜语1\u答案的值永远不会是true
或false
,并且各种测试的结果总是true
或false
。我很确定你想要这个:
if TEST1 || TEST2 || TEST3 || TEST4
其次,在测试字符串值时,不必测试所有的大小写变化。只需downcase
答案和测试小写测试值(除非区分大小写很重要)。或者,如果简单的字符串测试不够,则使用正则表达式
并使用i
选项进行不区分大小写的匹配。例如:
if riddle_1_answer =~ /(?:an )?onion/i
将以大写、小写和混合格式测试“洋葱”或“洋葱”
也许比这些小错误更重要的是,我们应该避免重复。总的模式似乎是:
提问
接受回答
核对答案
根据答案更改程序状态
重复
当您看到这样的情况时,您应该开始考虑数组和散列。当可以对值进行数字索引时,使用数组;当希望获取与不同键关联的值时,使用哈希。然后,可以使用一个简单的循环来迭代数组或散列的值
因此,从上面的模式可以看出,我们需要一种方法来提示问题,获取答案,处理可能的EOF和空字符串,验证非空答案,可能在需要时重复问答
让我们定义一个小方法来得到答案
# prompt_and_get_answer PROMPT, ANSWERS_DATA
#
# issue PROMPT, and get an answer, which must be one of the
# values in ANSWERS_DATA array, or one of the keys of the
# ANSWERS_DATA hash.
def prompt_and_get_answer prompt, answers_data
ans = ''
while ans.size < 1
print prompt
ans = $stdin.gets
if ans.nil?
raise "End of input"
end
ans.strip!
if answers_data.class == Hash # hash?
answers = answers_data.keys.sort
else
answers = answers_data.sort
end
matches = answers.grep(/#{ans}/i) # match possible valid answers
case matches.size # how many items found?
when 0
puts "#{ans} is not a valid answer. Use one of:"
puts answers.join(', ')
ans = ''
when 1 # return the match or the value of the matching key
ans = answers_data.class == Hash ? answers_data[matches[0]] : matches[0]
else
puts "#{ans} is ambiguous; be more specific to match one of:"
puts answers.join(', ')
ans = ''
end
end
ans
end
从中可以看出,我们使用了方法(函数)将逻辑分解为更小的部分,并将获取答案的细节与测试答案的细节分开
稍后,我们可以看到如何使用表和散列来建立问题列表
# prompt_and_get_answer PROMPT, ANSWERS_DATA
#
# issue PROMPT, and get an answer, which must be one of the
# values in ANSWERS_DATA array, or one of the keys of the
# ANSWERS_DATA hash.
def prompt_and_get_answer prompt, answers_data
ans = ''
while ans.size < 1
print prompt
ans = $stdin.gets
if ans.nil?
raise "End of input"
end
ans.strip!
if answers_data.class == Hash # hash?
answers = answers_data.keys.sort
else
answers = answers_data.sort
end
matches = answers.grep(/#{ans}/i) # match possible valid answers
case matches.size # how many items found?
when 0
puts "#{ans} is not a valid answer. Use one of:"
puts answers.join(', ')
ans = ''
when 1 # return the match or the value of the matching key
ans = answers_data.class == Hash ? answers_data[matches[0]] : matches[0]
else
puts "#{ans} is ambiguous; be more specific to match one of:"
puts answers.join(', ')
ans = ''
end
end
ans
end
$prompt1 = <<EOQ
There are two doors
1. Riddles
2. Puzzles
Which door do you go through?
EOQ
$answer1 = [ '1', '2' ]
$prompt2 = <<EOQ
Here is your riddle:
You use a knife to slice my head and weep beside me when I am dead.
What am I?
EOQ
$answer2 = [ 'onion' ]
ans1 = prompt_and_get_answer $prompt1, $answer1
if ans1 == '1'
do_riddles
elsif ans1 == '2'
do_puzzles
else
raise "Bad answer to prompt1"
end
def do_riddles
while true
ans = prompt_and_get_answer $prompt2, $answer2
if ans == 'onion'
puts "yay! you're right!"
break
else
puts "nope. Try again"
end
end
end