while循环中无限循环的switch语句

Switch-statement inside a while-loop which loop infinitely

本文关键字:switch 语句 无限循环 循环 while      更新时间:2023-10-16

下面是我的代码:

int main()
{
    int nothing;
    string name;
    int classnum;
    bool classchosen;
    string classname;
    cout << "Welcome adventurer, your journey is about to begin.nn";
    cout << "Firstly, what's your name? ";
    cin >> name;
    classchosen = false;
    while (classchosen == false)
    {
        cout << "nnNow, " << name << ", choose your class entering its number.nn";
        cout << "1- Warriorn" << "2- Magen" << "3- Paladinn" << "4- Monknn";
        cout << "Class number: ";
        cin >> classnum;
        switch(classnum){
            case 1:
                    classname = "Warrior";
                    classchosen = true;
                    break;
            case 2:
                    classname = "Mage";
                    classchosen = true;
                    break;
            case 3:
                    classname = "Paladin";
                    classchosen = true;
                    break;
            case 4:
                    classname = "Monk";
                    classchosen = true;
                    break;
            default:
                    cout << "nWrong choice, you have to enter a number between 1 and 4.n" << endl;
                    break;
        }
    }
    cout << "nSo you are a " << classname << " ? Well, tell me something more about you...n";
    cin >> nothing;
    return 0;
}

现在,当我运行它并输入一个字符串(例如"fjdfhdk")时,当它询问类号时,程序会无限循环,而不是进入默认语句,再次编写问题并让我选择另一个类。为什么?

试试这样:

#include <sstream>
#include <string>
using namespace std;
int getInt(const int defaultValue = -1){
  std::string input;
  cin >> input;
  stringstream stream(input);
  int result = defaultValue;
  if(stream >> result) return result;
  else return defaultValue;

}

//..in main
cout << "Class number: ";
int classNum = getInt();
switch(classNum){ .... }

在您的例子中失败的原因是因为cin试图将一堆字符读入int变量。您可以将其作为字符串读取并根据需要进行转换,也可以在读入int变量时通过检查是否设置了任何失败位来显式检查cin状态。例如,如果您尝试将一堆字符读入int,则会设置失败位。

因为您正在读取int,而读取失败。这有两个效果:

  1. 之后使用classnum是未定义行为,
  2. 流已经记住了错误条件,所以您可以稍后再检查。

只要错误条件没有被清除,所有进一步流上的操作是无操作的。最简单的变化你的程序可以这样做:

std::cin >> classnum;
if ( !std::cin ) {
    classnum = 0;
    std::cin.clear();
    std::cin.ignore( std::numeric_limits<std::streamsize>::max(), 'n' );
}
switch ( classnum ) // ...

如果发生错误,将classnum设置为已知值,清除错误状态,并跳过所有输入直到下一个换行符。(否则,你只会再次失败,因为触发错误的字符仍然存在。)

但是,考虑使用一个单独的函数来提取int,和使用getline,按照user814628的建议。上面的更多的是向你解释发生了什么,以及你为什么看到你看到的症状User814628的建议要好得多软件工程。