getline没有要求输入?

6

这可能是一个非常简单的问题,但请原谅我,因为我是新手。 以下是我的代码:

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

int main ()
{ 
   string name;
   int i;
   string mystr;
   float price = 0;

   cout << "Hello World!" << endl;
   cout << "What is your name? ";
   cin >> name;
   cout << "Hello " << name << endl;
   cout << "How old are you? ";
   cin >> i;
   cout << "Wow " << i << endl;

   cout << "How much is that jacket? ";
   getline (cin,mystr);
   stringstream(mystr) >> price;
   cout << price << endl;
   system("pause");

   return 0;
}

问题在于,当被问到“那件夹克多少钱?”时,getline不会要求用户输入,而只是输入初始值“0”。为什么会这样呢?

1
请注意:这个问题已经被提出了很多次。以下是一些示例链接:
  • http://stackoverflow.com/questions/3731529/program-is-skipping-over-getline-without-taking-user-input
  • https://dev59.com/G3I-5IYBdhLWcg3wpqMK
  • https://dev59.com/01PTa4cB1Zd3GeqPn_Vt
- cpx
3个回答

13
在使用 operator>>getline 混合时必须要小心。问题在于,当你使用 operator>> 时,用户输入数据后按下回车键,这将在输入缓冲区中放置一个换行符。由于 operator>> 是以空格为分隔符的,因此换行符不会被放入变量中,仍然留在输入缓冲区中。然后,当你调用 getline 时,它只寻找一个换行符。由于这是缓冲区中的第一件事情,所以它立即找到了它要找的内容,而且永远不需要提示用户。
修复方法: 如果你在使用 operator>> 后要调用 getline,则需要在两者之间调用 ignore 或执行其他操作以清除换行符,例如对 getline 的虚拟调用。
另一个选项(与 Martin 所说的类似),是根本不使用 operator>>,而只使用 getline,然后将字符串转换为所需的任何数据类型。这样做的副作用是使你的代码更加安全和健壮。我会先编写一个像这样的函数:
int getInt(std::istream & is)
{
    std::string input;
    std::getline(is,input);

    // C++11 version
    return stoi(input); // throws on failure

    // C++98 version
    /*
    std::istringstream iss(input);
    int i;
    if (!(iss >> i)) {
        // handle error somehow
    }
    return i;
    */
}

你可以为浮点数、双精度等其他类型创建一个类似的函数。当你需要一个整数时,不要使用以下方式:

cin >> i;

你需要做这个:

i = getInt(cin);

非常感谢你,本杰明!我完全理解你的意思。 - UzumakiDev
为什么我没早点加入这个网站呢 :-/ - UzumakiDev
"return stoi(input)" 基本上意味着如果返回类型为字符串,则将其转换为整数? - UzumakiDev
@Kyle:不是。这意味着“返回stoi(input)的返回值”。stoi接受一个字符串(这里没有if,它必须是一个字符串,否则它将无法编译),并尝试将其转换为整数。 - Benjamin Lindley

3

这是因为你在之前的调用中留下了一个'\n'在输入流中。

cin >> i;  // This reads the number but the '\n' you hit after the number
           // is still on the input.

实现用户交互输入最简单的方法是确保每行都独立处理(因为用户会在每个提示后按回车键)。

因此,始终先读取一行,然后处理该行(直到您熟悉流的操作方式)。

std::string  line;
std::getline(std::cin, line);

std::stringstream linestream(line);

// Now processes linestream.
std::string garbage;
lienstream >> i >> garbage; // You may want to check for garbage after the number.

if (!garbage.empty())
{
    std::cout << "Error\n";
}

我不明白?那你具体建议我怎么做才能让getline要求输入?抱歉,我是一个完全的n00b。 - UzumakiDev
谢谢你们两位,我会记住这些的。等我对自己在做什么有更清晰的认识后再来看看。谢谢! - UzumakiDev
我发现这个链接非常有用:[link]http://augustcouncil.com/~tgibson/tutorial/iotips.html[link] - UzumakiDev

2

在遇到换行符之前忽略一些字符。

cin.ignore(256, '\n')
getline (cin,mystr);

你能再解释一下吗?为什么我要忽略256个字符,这不是比一个字节多吗,那为什么是256? - UzumakiDev
这是从输入流中提取或忽略的最大字符数。根据您的输入长度,您可以拥有一个大于256的数字。在您的情况下,我假设256是“name”字符串的最大输入字符长度。 - cpx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接