从流中读取格式化输入后,std :: getline()读取错误的数据

时间:2013-08-29 22:20:41

标签: c++ getline

我查看了其他一些问题,而且我对C ++过于陌生,知道它们是否适用于我的问题。

基本上,当显示“name”的输出时,如果我输入我的全名,它只显示第二个单词。之前,它甚至没有任何东西,它只是跳过它。我现在很困惑,看起来很简单。感谢。

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

int main()
{
double money;
string name;
int age;

// Prompt for age and receive
cout<<"How old are you? ";
cin >> age;

// Prompt for money and receive
cout<<"How much money do you have?";
cin >> money >> endl;

// Prompt for name and receive
cout<<"What's your name?\n\n"<< endl;
getline(cin, name);

// Display all information to user
cout<<"Hello, "<< name <<".";
cout << "You are " << age << " years old";
cout<< " and have $" << money << ".\n";

system("PAUSE");
return 0;
}

2 个答案:

答案 0 :(得分:4)

问题是使用>>的格式化输入读取值并在完全解析值后停止。例如,一旦出现与格式不匹配的内容,就会完成一个数字。也就是说,读数会在空格或换行符(以及其他一些字符)前面停止。通常这些额外的字符不会导致问题,因为格式化的输入在尝试读取实际值之前跳过前导空格(空格,制表符,换行符等)开始。

但是,未格式化的输入(例如getline())会立即开始读取其值并在遇到换行符时停止(或者如果使用三个参数版本,则指定为换行符的字符)。也就是说,getline()会在读取换行符后立即停止,如果它留在流中。

摆脱换行符(以及任何其他前导空格)的最简单方法是使用std::ws,例如:

if (std::getline(std::cin >> std::ws, name)) {
    ...
}

......而且,顺便说一句,每当你尝试阅读某些内容时,你应该始终检查之后,读取该值的尝试是否成功!

另一种方法是根本不使用std::getline(),而只是使用name的格式化输入。但是,假设名称中没有空格。

答案 1 :(得分:0)

那是因为“你有多少钱?”newline。回复仍然在输入缓冲区中。一般来说,混合项目输入和基于行的输入(无论是使用C和scanf / fgets还是C ++ >>getline)并不是一个好主意,因为你得到这些问题。

您可以在char dummy = cin.get();之前的某个地方之前使用getline来修复此特定情况,但是,每次从“项目输入”切换到“行输入”时都必须这样做,如果您稍后更改顺序,您必须记住移动cin.get()

更好的解决方案是始终使用基于行的输入,然后使用stringstream从字符串中获取数据,如下所示:

string ageString;
getline(cin, ageString);
stringstream ageSs(ageString);
if (!ageSs >> age)
{
    cout << "Bad input" << endl;
    exit(1);    // You may of course want to repeat rather than exit... 
}

这样,无论输入是什么,你都在阅读整行。