需要帮助修复奇怪的cin行为

时间:2013-11-30 03:20:29

标签: c++ c++11

我正在构建一个产品结帐软件,我不断遇到一个奇怪的错误。我有一个中央菜单,可以获得用户输入。函数完成任务后,会将用户返回菜单。但是,对于某些函数,菜单提示符后面的cin.get()会出现错误,并且不会接受给定的第一个命令。以下是相关的代码片段:

主菜单循环:

bool foreverLoopFlag = true;
while (foreverLoopFlag) {

    cout << "\nC[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? ";
    cin.get(actionChoice);
    std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    cout << endl;

    actionChoice = toupper(actionChoice);

    switch (actionChoice) {
        case 'C':
            checkoutSoftware(studentMap, productList);
            break;
        case 'R':
            returnSoftware(studentMap, productList);
            break;
        case 'S':
            studentDisplay(studentMap, productList);
            break;
        case 'P':
            productDisplay(studentMap, productList);
            break;
        case 'Q':
            foreverLoopFlag = false;
            break;
        default:
            cout << "Invalid command.\n";
            break;
    }
}

问题 - 子功能,studentDisplay:

void studentDisplay(map<string, Student> & studentMap, list<Product> & productList) {
string inputCLID;

cout << "Please enter student CLID: ";
cin >> inputCLID;

if (studentMap.find(inputCLID) != studentMap.end()) {
    cout << "\nStudent: " << studentMap[inputCLID].name << " (" << inputCLID << ")\n";
    cout << "\tBorrowed items: " << endl;
    for (list<Student::LentProduct>::iterator it = studentMap[inputCLID].checkedOut.begin(); 
         it != studentMap[inputCLID].checkedOut.end(); it++) {
        cout << "\t\tProduct: " << (*it).name;
        cout << "\tDue Date: " << (*it).dateDue << endl;
    }


} else {
    cout << "\nError: CLID not in database.\n";
}
}

有一些压痕被转移到SE,我道歉。这是我遇到的问题的一个例子:

C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? s

Please enter student CLID: mrx8394

Student: Mark Xeno (mrx8394)
    Borrowed items:
        Product: Bluebeard  Due Date: 12/14/2013

C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? c

Invalid command.

C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice? q

我尝试在菜单循环的开头放置一个std :: cin.flush(),但这不起作用。我尝试在菜单循环开始时执行std :: cin.ignore(std :: INT_MAX),但这使得菜单从未出现过。我也尝试了一个std :: cin.sync(),但这只是一个无限循环:

C[heckout], R[eturn], S[tudent], P[roduct], Q[uit]. Choice?
Please enter a product to checkout:
Error: No such product.

我不知道从哪里开始。我知道这可能只是我不喜欢的iostream的一些怪癖。任何助理都将不胜感激。

编辑:我没有足够的声誉对特定答案进行upvote或评论(我的所有代表都在Math.SE !!!),所以我在这里发表评论。 @ Igor-tandetnik的解决方案完美无缺。我已经将其他所有内容都移到了getline上,但我认为那个人刚刚离开了。我的谢意成群结队。

@qwrrty虽然这可能是愚蠢的,但我有一个规范要见(你不喜欢低级大学课程)。我通常不会要求帮助调试任务,但这是最后一个错误,我对iostream的了解不是那么深,但我知道有人在这里会知道什么是我的流状态。

再次感谢大家,欢呼!

2 个答案:

答案 0 :(得分:1)

cin >> inputCLID读取字符,但不包括第一个空白字符(在您的示例中为换行符)。该字符留在流中。这是cin.get(actionChoice)后来检索的字符。

答案 1 :(得分:0)

我倾向于认为对于交互式输入,尝试使用stdin和/或cin读取除完整输入行之外的任何内容都是愚蠢的。您的程序有太多方法让您对输入流中的内容感到困惑,并最终处于不可恢复的状态。

至少我会修改程序,说它认为无效的命令,或者不存在的产品:

    default:
        cout << "Invalid command '" << actionChoice << "'\n";

    cout << "Error: No such product '" << productChoice << "'\n";

至少你可以了解程序实际用于这些变量的输入。