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

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

本文关键字:等待 控制台 输入 getline 调用 C++      更新时间:2023-10-16

我正试图从控制台获取一些用户输入参数,两个字符串、两个int和一个double。我尝试使用的相关代码是:

#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);

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

标题:类别:

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

问题是您将对getline((的调用与运算符>>的使用混合在一起。

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

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

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

如果输入包含字符串或需要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);

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

您可以使用

cin.ignore();

或如@kernald所述,使用

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

使用getline((之前

如上所述使用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);

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

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

cingetline之间使用此选项。

也适用于ws。您可以使用getline(cin >> ws, inputString)(在使用cin命令读取数据后吃掉空白或换行符。

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

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

看看TinyCon。您可以使用静态方法tinyConsole::getLine((来代替您的getLine和流调用,并且您可以随心所欲地使用它。

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

cin.sync((;用这个代替cin.ignore(效果最好。

函数_______将返回最后读取的字符,并将内部指针移动一个带-1字符的字符。

  1. Getline((
  2. Peek((3.flush((4.putback((