簡體   English   中英

如何驗證 Ruby 中多選提示的命令行輸入?

[英]How to validate command line input from multiple choice prompt in Ruby?

我正在寫一個多項選擇測驗,用戶必須通過輸入從ad的字母來選擇答案。 每個問題提示如下所示:

What is the last letter in alphabet?
(a) Y
(b) R
(c) Z
(d) Q

如果用戶輸入其他任何內容,我想顯示一條消息並再次打印整個問題,直到輸入為abcd

這是我嘗試過的:(簡化)

question = "What is the last letter in alphabet?\n(a) Y\n(b) R\n(c) Z\n(d) Q"

puts question
answer = gets.chomp.to_s
while answer > "d"
  puts "Please enter a, b, c, or d"
  puts
  puts question
  answer = gets.chomp.to_s
end

它在輸入efg等時工作正常,但它不會捕獲像ab1Z之類的輸入,或者當用戶只是按下回車鍵時。

您只有四個允許的輸入。 直接檢查那些。 即使像不雅一樣if.(answer == "a" || answer == "b"... )。 其他任何東西都會接受一些無效的輸入。 特別是, if answer > "d"允許"ab"作為有效答案。

您的方法不起作用,因為answer > "d"使用它們的(Unicode)代碼點按字符比較兩個字符串。 要了解這意味着什么,請查看基本拉丁圖表:(它相當於一個 ASCII 表)

基本拉丁圖表

“d”的代碼點為 U+0064。 任何較小的代碼點(即圖表中“d”之前的每個字符)都被視為較小。 這包括所有(常規)數字、所有(基本拉丁語)大寫字母和幾個符號:

"0" > "d"  #=> false
"Z" > "d"  #=> false

您可以添加一個下限,例如answer < "a" || answer > "d" answer < "a" || answer > "d"但這仍然允許所有以允許的字符之一開頭的字符串,例如:

"apple" < "a" || "apple" > "d" #=> false

要實際將答案限制為四個允許值,您必須將字符串與每個值進行比較。 您可以結合這些比較:

answer == 'a' || answer == 'b' || answer == 'c' || answer == 'd'

在允許值的數組上使用循環:

['a', 'b', 'c', 'd'].any? { |letter| answer == letter }

檢查數組是否包含答案:

['a', 'b', 'c', 'd'].include?(answer)

# or

%w[a b c d].include?(answer)

或使用正則表達式將a匹配到d

answer.match?(/\A[a-d]\z/)

請注意,如果answerad之間,則上述示例真。 您可以通過.(...)否定條件:

while !(%w[a b c d].include?(answer))
  # ...
end

或使用until而不是while

until %w[a b c d].include?(answer)
  # ...
end

其他答案已回答您問題標題中給出的問題。

我建議您考慮采用以下代碼的一些變體。

def get_answer(question, answers)
  choices_to_answers = construct_choices_to_answers(answers)
  loop do 
    puts "#{question}"
    display_choices(choices_to_answers)
    print "answer: "
    choice = gets.chomp
    puts choice
    break choices_to_answers[choice] if choices_to_answers.key?(choice)
    puts "\nThat answer is invalid."
  puts "Enter a letter between 'a' and '#{choices_to_answers.keys.last}'\n"
  end
end
def construct_choices_to_answers(answers)
  ('a'..('a'.ord + answers.size - 1).chr).to_a.zip(answers).to_h
end
def display_choices(choices_to_answers)
  choices_to_answers.each { |k,v| puts "(#{k}): #{v}" }
end

假設可能的答案如下。

answers = %w| Y R Z Q |
  #=> ["Y", "R", "Z", "Q"]

然后

choices_to_answers = construct_choices_to_answers(answers)
  #=> {"a"=>"Y", "b"=>"R", "c"=>"Z", "d"=>"Q"}

display_choices(choices_to_answers)

印刷

(a): Y
(b): R
(c): Z
(d): Q

在這里,我假設選擇總是以"a"開頭的連續字母。 如果該假設正確,則無需手動將這些字母與可能的答案相關聯。


現在讓我展示與該方法的可能對話( answers如上定義)。

question = "What is the last letter in the alphabet?"
get_answer(question, answers)
  #=> "R"

顯示以下內容。

What is the last letter in the alphabet?
(a): Y
(b): R
(c): Z
(d): Q    
answer: e

That answer is invalid.
Enter a letter between 'a' and 'd'

What is the last letter in the alphabet?
(a): Y
(b): R
(c): Z
(d): Q
answer: b

然后,您可以構建一個散列數組,提供問題、可能的答案、正確答案、可能問題的權重以及指示是否給出了正確答案的 boolean。

questions = [
  ...
  { question: "What is the last letter in the alphabet?",
    answers: ["Y", "R", "Z", "Q"],
    correct_answer: "Z",
    weight: 1,
    correct_answer_given: nil
  },
  ...
]

回答問題時,每個問題的:correct_answer_given值都會更新為truefalse 回答完所有questions后,可以使用問題來確定考試的分數。


如果你想為每個問題分配一個數字,你可以寫

question_number = 0
questions.each do |h|
  question_number += 1
  g = h.merge(question: "#{question_number}. #{h[:question]}")
  answer = get_answer(question, g[:answers])      
  h[:correct_answer_given] = h[:correct_answer] == answer
end

如果question_number #=> 12並且

h[:question]
  #=> "What is the last letter in the alphabet?",

然后

g[:question]
  #=> "12. What is the last letter in the alphabet?"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM