【问题标题】:Using a while loop to check for input errors within a switch case使用 while 循环检查 switch case 中的输入错误
【发布时间】:2015-10-04 18:15:15
【问题描述】:

我有一个开关,其中一种情况要求用户输入几个输入以用于构造类对象。这些输入之一应该是数字的形式。如果没有输入数字,它会破坏开关并最终终止程序。我想设置一个 while(){} 条件,这样如果输入了一个非整数,它将提示用户输入一个整数,然后继续执行程序。

int main(){
  int in_yob, ranking;
  string in_first_name, in_last_name, in_genre, in_fact, last_name, in_composer;
  char selection, choice;
    do {
      DisplayMenu();
      cin >> selection;
      cout << endl;
      while (!cin || selection < 48 || selection > 53){
        cin.clear();
        cout << "Please make a valid selection" << endl;
        DisplayMenu();
        cin >> selection;
      }
      switch (selection) {
        case 49 : {
            cout << "First Name: ";
            cin >> in_first_name;
            cout << "Last Name: ";
            cin >> in_last_name;
            cout << "Genre: ";
            cin >> in_genre;
            cout << "Year of Birth: ";
            cin >> in_yob;
            cout << "Fact: ";
            cin >> in_fact;
            last_name = in_last_name;
            transform(last_name.begin(), last_name.end(), last_name.begin(), ::tolower);
            Composer& last_name = myDB.AddComposer(in_first_name, in_last_name,
                                                        in_genre, in_yob, in_fact);
            cin.clear();
        }   break;
...
        default: 
            cout << "Please make a valid selection" << endl;
      }
  } while (selection != 48);
}

我尝试在cin &gt;&gt; in_yob; 之后插入一个while循环:

while(!cin || in_yob > 1){
    cin.clear();
    cout << "Enter a positive enter for year of birth: ";
    cin >> in_yob;
}

但结果是“输入一个正数的出生年份:”的无限循环。我知道这个用于错误检查的构造在开关盒之外工作,那么在开关盒中我得到这个结果的原因是什么?另外,您将如何解决此问题,以便我可以检查并防止输入错误?谢谢。

【问题讨论】:

  • 什么是selection?它是什么类型的?以及为什么与幻数进行比较而不是使用例如std::isdigit 以确保您有数字?或者至少使用正确的字符文字,例如'0' 而不是神秘的48。
  • 输入一个负数会给你一些线索。
  • @JoachimPileborg 选择是char,而且这个数字并不神奇。它是用户菜单选择的字符代码。
  • “幻数”是"Unnamed numerical constant",对于您的代码的读者来说,它只是一个没有任何特殊含义的数字。字符文字'0' 具有含义,给出了一些上下文,并且无论字符编码如何始终是可移植的,“幻数”48 可以表示任何含义,并且不适用于不是从 ASCII 派生的编码。
  • 另外,由于selection 是一个字符,您的输入验证功能将无法按预期工作,第二个输入操作将读取您为第一个输入操作输入的换行符。

标签: c++ oop while-loop switch-statement


【解决方案1】:

[为了用更多的空间和更好的格式比在评论中更好地解释我自己,我将其发布为答案而不是评论。]

当你输入输入时,例如

1

输入缓冲区实际上包含两个字符,首先是数字'1',然后是换行符'\n'。

当您读取单个字符时,输入操作会提取第一个字符,即数字,并将其写入您的变量。

如果您随后读取另一个字符,它将读取换行符,而不是后面的任何内容。

有一个技巧可以“忽略”字符,例如换行符,这是通过使用 std::istream::ignore 完成的,如果您点击参考链接,您将看到一个很好的示例,说明如何忽略包括换行符在内的任何内容。

因此,在您的情况下,仅调用 clear 是不够的,您还需要在输入验证循环中调用 ignore。如果你继续阅读单个字符,你也需要在此之前调用ignore。

【讨论】:

  • 哦,现在我明白你的意思了。我还在学习这个,但这很明显,我觉得很愚蠢。以下输入请求如何在换行符上发布,在输入字符之后保存换行符。谢谢。
【解决方案2】:

您需要清除输入流。

#include <iostream>
#include <string>
int in_yob = 0;
int main()
{
    while(std::cin.good() && in_yob < 1){
        std::cin.clear();
        std::cout << "Enter a positive enter for year of birth: ";
        if( !(std::cin >> in_yob) ) {
            std::cin.clear();
            std::cin.ignore(10000,'\n');
        }
    }
    std::cout << "YOB " << in_yob << std::endl;

}

【讨论】:

  • 我试过这个。同样的结果,无限循环“输入出生年份的正整数:”
  • 代码已更改。现在工作。不妨明确表示您希望 cin 好。您还想检查 in_yob 是否无效。
  • 现在它只是在没有输入的情况下为 switch case 的其余部分运行 cout,拉出菜单,然后运行 ​​default case 错误。
  • 如果您在上面的开关内运行它,它不会。这就是为什么我很困惑,因为您的代码确实在开关之外工作。见c++ shell example
  • 出错时清除输入流。见stackoverflow.com/questions/5131647/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-05
  • 2023-04-10
相关资源
最近更新 更多