简体   繁体   English

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

[英]Need help fixing strange cin behavior

I'm building a product checkout piece of software and I keep hitting a strange bug. 我正在构建一个产品结帐软件,并且不断遇到奇怪的错误。 I have a central menu that gets user input. 我有一个中央菜单,可以获取用户输入。 After a function is finished with its task, it sends the user back to the menu. 功能完成其任务后,它将使用户返回菜单。 For certain functions, however, the cin.get() I have after the menu prompt bugs out and won't accept the first command given. 但是,对于某些功能,我在菜单提示后输入的cin.get()会出错,并且不接受给出的第一个命令。 Here are the relevant code fragments: 以下是相关的代码片段:

The main menu loop: 主菜单循环:

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;
    }
}

A problem-child function, studentDisplay: 问题子函数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";
}
}

Some of the indention was mangled moving over to SE, I apologize. 抱歉,有些缩进已转移到SE。 Here an example of the issue I'm having: 这是我遇到的问题的一个示例:

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

I tried putting a std::cin.flush() at the beginning of the menu-loop, but that didn't work. 我尝试将std :: cin.flush()放在菜单循环的开始,但这没有用。 I tried doing std::cin.ignore(std::INT_MAX) at the beginning of the menu-loop, but that makes it to where the menu never even shows up. 我尝试在菜单循环的开始处执行std :: cin.ignore(std :: INT_MAX),但这使菜单甚至无法显示。 I also tried a std::cin.sync(), but that just makes an infinite cycle of this: 我还尝试了一个std :: cin.sync(),但这只是一个无限循环:

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

I have no idea where to go from here. 我不知道从这里去哪里。 I know it is probably just some quirk of the iostream that I'm not picking up on. 我知道这可能只是我不了解的iostream的一些怪癖。 Any assistant would be appreciated. 任何助手将不胜感激。

EDIT: I do not have enough reputation to upvote or comment on specific answers (all of my rep is on Math.SE!!!), so I'll comment here. 编辑:我没有足够的声誉来赞扬或评论特定的答案(我的所有代表都在Math.SE上!!!),所以我将在这里发表评论。 @Igor-tandetnik 's solution worked perfectly. @ Igor-tandetnik的解决方案运行完美。 I had moved everything else over to a getline, but I suppose that guy just got left in the shuffle. 我已经将其他所有内容移到了一条Getline,但我想那家伙只是被拖进了洗牌场。 My thanks come in droves. 我的谢意成群结队。

@qwrrty While it may be folly, I had a specification to meet (don't you just love low level University courses). @qwrrty虽然很愚蠢,但我有一个要满足的规范(您不只是喜欢低级的大学课程)。 I don't typically ask for help debugging assignments, but this was the last bug and my knowledge of iostream isn't that deep, but I knew someone on here would know what was bugging out my stream state. 我通常不需要寻求调试任务的帮助,但这是最后一个错误,我对iostream的了解并不深,但是我知道这里的人会知道是什么使我的流状态出错。

Thanks again guys, cheers! 再次感谢你们,加油!

cin >> inputCLID reads characters up to, but not including, the first whitespace character (in your example, a line feed). cin >> inputCLID读取的字符最多但不包括第一个空格字符(在您的示例中为换行符)。 That character is left in the stream. 该角色留在信息流中。 It is that character that cin.get(actionChoice) later retrieves. cin.get(actionChoice)之后检索的是该字符。

I tend to think that for interactive input, trying to use stdin and/or cin for reading anything other than a full line of input is folly. 我倾向于认为对于交互式输入,尝试使用stdin和/或cin读取全行输入以外的任何内容都是愚蠢的。 There are just too many ways for your program to get confused about what's still on the input stream, and end up in an unrecoverable state. 对于您的程序,有太多的方法会混淆输入流中仍然存在的内容,并最终导致无法恢复的状态。

At the very least I'd modify the program to say what command it thinks is invalid, or product that doesn't exist: 至少,我会修改程序说它认为是无效的,或不存在的产品是什么命令:

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

and

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

That way at least you can get an idea of what input the program is actually using for these variables. 这样,至少您可以了解程序实际上为这些变量使用的输入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM