c++ getline() 在多次调用时不等待来自控制台的输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7786994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:29:40  来源:igfitidea点击:

c++ getline() isn't waiting for input from console when called multiple times

c++getline

提问by user754852

I'm attempting to get a few user-input parameters from the console, two strings, two ints and a double. The relevant code I'm trying to use is this:

我试图从控制台获取一些用户输入参数、两个字符串、两个整数和一个双精度数。我试图使用的相关代码是这样的:

#include <string>
#include <iostream>
using namespace std;

// ...

string inputString;
unsigned int inputUInt;
double inputDouble;

// ...

cout << "Title: "; 
getline(cin, inputString);
tempDVD.setTitle(inputString);

cout << "Category: "; 
getline(cin, inputString);
tempDVD.setCategory(inputString);

cout << "Duration (minutes): "; 
cin >> inputUInt; 
tempDVD.setDuration(inputUInt);

cout << "Year: "; 
cin >> inputUInt; 
tempDVD.setYear(inputUInt);

cout << "Price: $"; 
cin >> inputDouble; 
tempDVD.setPrice(inputDouble);

However, when running the program, instead of waiting for the first inputString to be entered, the code doesn't stop until the second getline() call. Thus the console output looks like this:

但是,在运行程序时,不是等待输入第一个 inputString,而是直到第二个 getline() 调用代码才停止。因此控制台输出如下所示:

Title: Category:

标题: 类别:

with the cursor appearing after category. If I input now, the program then jumps ahead to the year input, not allowing me to enter more than one string. What's happening here?

光标出现在类别之后。如果我现在输入,程序将跳转到年份输入,不允许我输入多个字符串。这里发生了什么事?

回答by Martin York

The problem is you are mixing calls to getline() with the use of the operator >>.

问题是您正在使用运算符 >> 混合调用 getline()。

Remember that operator >> ignored leading white space so will correctly continue across lines boundaries. But stops reading after the input has successfully been retrieved and thus will not swallow trailing '\n' characters. Thus if you use a getline() after a >> you usually get the wrong thing unless you are careful (to first remove the '\n' character that was not read).

请记住,运算符 >> 忽略了前导空格,因此将正确地跨行边界继续。但在成功检索输入后停止读取,因此不会吞下尾随的 '\n' 字符。因此,如果您在 >> 之后使用 getline() ,除非您小心(首先删除未读取的 '\n' 字符),您通常会得到错误的结果。

The trick is to not use both types of input. Pick the appropriate one and stick to it.

诀窍是不要同时使用这两种类型的输入。选择合适的并坚持下去。

If it is all numbers (or objects that play nice with operator >>) then just use operator >> (Note string is the only fundamental type that is not symmetric with input/output (ie does not play nicely)).

如果它是所有数字(或与运算符 >> 配合良好的对象),则只需使用运算符 >>(注意字符串是唯一与输入/输出不对称的基本类型(即不能很好地配合))。

If the input contains strings or a combination of stuff that will require getline() then only use getline() and parse the number out of the string.

如果输入包含字符串或需要 getline() 的组合,则仅使用 getline() 并解析字符串中的数字。

std::getline(std::cin, line);
std::stringstream  linestream(line);

int  value;
linestream >> value;

// Or if you have boost:
std::getline(std::cin, line);
int  value = boost::lexical_cast<int>(line);

回答by Marc Plano-Lesay

You need to flush the input buffer. It can be done with cin.clear(); cin.sync();.

您需要刷新输入缓冲区。可以用cin.clear(); cin.sync();.

回答by Rika

You can use

您可以使用

cin.ignore();

or as @kernald mentioned use

或正如@kernald 提到的那样使用

cin.clear();
cin.sync();

before using getline()

使用 getline() 之前

回答by sehe

Use cin.clear()as mentioned anduse proper error handling:

使用cin.clear()如前所述使用正确的错误处理:

    cin.clear();
    cin.sync();

    cout << "Title: "; 
    if (!getline(cin, inputString))  exit 255;
    tempDVD.setTitle(inputString);

    cout << "Category: "; 
    if (!getline(cin, inputString))  exit 255;
    tempDVD.setCategory(inputString);

    cout << "Duration (minutes): "; 
    if (!(cin >> inputUInt)) exit 255; 
    tempDVD.setDuration(inputUInt);

    cout << "Year: "; 
    if (!(cin >> inputUInt)) exit 255; 
    tempDVD.setYear(inputUInt);

    cout << "Price: $"; 
    if (!(cin >> inputDouble)) exit 255; 
    tempDVD.setPrice(inputDouble);

回答by Farbod Ahmadian

If user inputs a space before \n in previous cinbefore getline, only ignoreitself wouldn't be enough so you have to use this code instead of ignore()alone. For example 12345 \t \nwill not work anymore. All unprocessed characters must be ignored.

如果用户在getline之前的前一个cin 中的\n 之前输入一个空格,则仅忽略本身是不够的,因此您必须使用此代码而不是单独使用ignore()。例如12345 \t \n将不再起作用。必须忽略所有未处理的字符。

#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');

Use this between cinand getline.

cingetline之间使用它。

回答by Gurudev

cin.sync(); use this instead of cin.ignore( works best.

cin.sync(); 使用它而不是 cin.ignore( 效果最好。

回答by Unix-Ninja

Mixing getline() with input streams in generally a bad thing to do. It's theoretically possible to manually handle the dirty buffers left over by using streams, but it's an unnecessary pain that should definitely be avoided.

将 getline() 与输入流混合通常是一件坏事。理论上可以通过使用流手动处理剩余的脏缓冲区,但这是绝对应该避免的不必要的痛苦。

You are better off using a console library to grab your input, this way the dirty-work can be abstracted for you.

您最好使用控制台库来获取您的输入,这样可以为您抽象出肮脏的工作。

Take a look at TinyCon. You can just use the static method tinyConsole::getLine() in replace of your getline and stream calls, and you can use it as many times as you'd like.

看看 TinyCon。您可以只使用静态方法 tinyConsole::getLine() 代替 getline 和流调用,并且可以根据需要多次使用它。

You can find information here: https://sourceforge.net/projects/tinycon/

您可以在此处找到信息:https: //sourceforge.net/projects/tinycon/

回答by Prabhathiya Herath

cin>> will leave newlines in the buffer when the user presses enter. getline() reads this as the user having pressed enter to "skip" the input.

当用户按下回车键时,cin>> 将在缓冲区中留下换行符。当用户按下 Enter 键“跳过”输入时,getline() 会读取此信息。

You can use cin.ignore() to get rid of those extra characters before using getline().

在使用 getline() 之前,您可以使用 cin.ignore() 去除那些额外的字符。