首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >又一个C++ cin循环问题

又一个C++ cin循环问题
EN

Stack Overflow用户
提问于 2012-10-30 23:06:27
回答 1查看 2K关注 0票数 5

更新

我找到了问题的原因。我一直在试验外壳。我看到有人在Mac上成功地运行了我的代码,并决定在标准bash中尝试。效果很好。所以,我想没有鱼壳了。:)

我仍然希望知道cin是如何工作的,以及为什么cin是这样工作的。这是我问题的主要部分。

我遇到了一个很流行的问题:在循环中使用cin。代码很简单,但我找不到解决方案。谷歌给我的答案五花八门,但通常涉及cin.clear()cin.ignore()cin.get()的一些组合。不幸的是,我还没有找到解决问题的组合或排序。而且,我对cin的功能没有完全的理解,这让我感到很沮丧。我不想用试错来解决这个问题。我想确切地了解到底发生了什么。

应该发生什么

当我运行我的代码时,我应该看到一个带有选项列表的提示符。我应该能够键入一个字符,它将运行其中一个选项。然后,它应该再次显示提示符,并重复这个过程,直到我选择退出选项。

实际发生了什么

一旦我运行了代码,它就会将提示符打印到屏幕上任意次数,并最终在提示符的一半时间停止。那我除了用^C杀死它什么也做不了。

代码语言:javascript
复制
$ ./run

Choose an option:
[A]dd a score
[R]emove a player
[E]xit

    : That is not a valid input.

[repeated a bunch of times]

Choose an option:
[A]dd a score
[R]emove a player
[E]xit

    : That is not a valid input.


Choose ^C
$ 

我的问题

是什么导致cin这么做的?作为一名经验丰富的Java (但是是一个初学者C++开发人员),我熟悉缓冲区和流之类的概念,但我不知道cin是如何工作的。我知道cin.clear()清除了错误状态,而cin.ignore()忽略了流中的许多字符。到目前为止,我的Google-fu还没有找到一个简明的参考。

为什么cin的行为是这样的?当在循环中使用cin时,人们应该如何可视化引擎盖下发生的事情?在C++中实现这种无限菜单思想的最优雅的方法是什么?

我的代码

下面是我的代码的一个简化版本,它产生了与完整版本完全相同的问题:

代码语言:javascript
复制
#include <iostream>

using namespace std;

int main () {

    //infinite menu 
    char input;
    while(true) {

        //prompt
        cout << "\n\nChoose an option:\n";
        cout << "[A]dd a score\n";
        cout << "[R]emove a player\n";
        cout << "[E]xit\n";
        cout << "\n\t: ";

        //input
        cin >> input;

        //decide what the input means
        switch(input) {
            case 'a':
            case 'A':
                cout << "Add a score.\n";
                break;
            case 'r':
            case 'R':
                cout << "Remove a player.\n";
                break;
            case 'e':
            case 'E':
                cout << "Program Complete.\n";
                return 0;
                break;
            default:
                cout << "That is not a valid input.\n";
        }
    }
    return 0;
}

我编译并运行:

代码语言:javascript
复制
$ g++ Test.cpp -o run
$ ./run

我正在MacOSX10.8.2上运行gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-30 23:34:24

帮自己一个忙,不要直接从std::cin中提取令牌。相反,用getline逐行读取,然后解释每一行。此外,必须始终在布尔上下文中计算输入操作的结果,否则将无法正确处理任意输入。

为了进行测试,如果调用echo "abc" | ./run,您的程序必须存活。这应该永远是你的第一批测试之一。

现在,关于代码:

代码语言:javascript
复制
#include <string>
#include <iostream>

int main()
{
    for (std::string line; std::getline(std::cin, line); )
    {
        if (line.empty()) { continue; }


        if (line == "A" || line == "a") { /* ... */ continue; }

        if (line == "R" || line == "r") { /* ... */ continue; }

        if (line == "E" || line == "e") { break; }

        std::cout << "Sorry, I did not understand.\n";
    }

    std::cout << "Goodbye!\n";
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13148887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档