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

Need help fixing strange cin behavior

本文关键字:cin 行为 帮助      更新时间:2023-10-16

我正在构建一个产品结账软件,但我一直遇到一个奇怪的错误。我有一个中央菜单,可以获得用户输入。功能完成任务后,它会将用户发送回菜单。然而,对于某些函数,我在菜单提示后的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 << "ttProduct: " << (*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的一些怪癖。任何助理都将不胜感激。

编辑:我没有足够的声誉来支持投票或评论具体的答案(我所有的代表都在Math.SE上!!),所以我会在这里发表评论@伊戈尔·坦德特尼克的解决方案非常有效。我把其他的东西都移到了一条边线上,但我想那家伙只是被甩在了后面。我的感谢纷至沓来。

@qwrrty虽然这可能很愚蠢,但我有一个要求(你不只是喜欢低水平的大学课程吗)。我通常不会寻求调试任务的帮助,但这是最后一个错误,我对iostream的了解也不那么深入,但我知道这里的人会知道是什么干扰了我的流状态。

再次感谢,伙计们,干杯!

cin >> inputCLID读取的字符最多不包括第一个空白字符(在您的示例中,是换行符)。那个字符留在了流中。cin.get(actionChoice)稍后检索的就是那个字符。

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

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

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

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

这样,至少您可以了解程序实际为这些变量使用的输入。