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

时间:2011-10-16 20:13:12

标签: c++ getline

我正在尝试从控制台获取一些用户输入参数,两个字符串,两个整数和一个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()调用之前不会停止。因此控制台输出如下所示:

  

标题:类别:

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

8 个答案:

答案 0 :(得分:20)

问题是你使用运算符&gt;&gt;混合调用getline()。

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

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

如果它是所有数字(或与运算符&gt;&gt;匹配的对象),那么只需使用运算符&gt;&gt; (注意字符串是唯一与输入/输出不对称的基本类型(即不能很好地播放)。)

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

答案 1 :(得分:12)

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

答案 2 :(得分:8)

您可以使用

cin.ignore();

或@kernald提到使用

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

使用getline()之前

答案 3 :(得分:3)

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

答案 4 :(得分:1)

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

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

cin getline 之间使用它。

答案 5 :(得分:0)

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

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

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

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

答案 6 :(得分:0)

cin.sync(); 用它代替cin.ignore( 效果最好。

答案 7 :(得分:0)

还可以与ws一起使用。使用getline(cin >> ws, inputString)命令读取数据后,您可以使用cin)来吃空格或换行符。