为什么 std::getline() 在格式化提取后跳过输入? [英] Why does std::getline() skip input after a formatted extraction?

查看:38
本文介绍了为什么 std::getline() 在格式化提取后跳过输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码提示用户输入他们猫的年龄和名字:

#include #include <字符串>int main(){年龄;std::string 名称;std::cin >>年龄;std::getline(std::cin, 名称);如果(标准::: cin){std::cout <<我的猫是"<<年龄<<"岁,他们的名字是"<<姓名<

我发现已经成功读取了年龄,但没有读取名称.这是输入和输出:

<块引用>

输入:10""先生胡须"输出:我的猫 10 岁了,它们的名字是"

为什么输出中省略了名称?我已经给出了正确的输入,但代码以某种方式忽略了它.为什么会发生这种情况?

解决方案

为什么会这样?

这与您自己提供的输入无关,而是与 std::getline() 的默认行为有关.当您提供年龄的输入 (std::cin >>age) 时,您不仅提交了以下字符,而且在您键入 输入:

<块引用>

10
"

当您从终端提交时选择 EnterReturn 时,总是会在您的输入后附加换行符.它也用于文件中以移动到下一行.在提取到 age 之后,换行符留在缓冲区中,直到下一个 I/O 操作被丢弃或读取.当控制流到达std::getline()时,会看到" Mr.Whiskers" 和开头的换行符会被丢弃,但输入操作会立即停止.发生这种情况的原因是 std::getline() 的工作是尝试读取字符并在找到换行符时停止.因此,您的其余输入将留在缓冲区中未读.

解决方案

cin.ignore()

要解决此问题,一种选择是在执行 std::getline() 之前跳过换行符.您可以通过在第一次输入操作后调用 std::cin.ignore() 来完成此操作.它将丢弃下一个字符(换行符),使其不再碍事.

std::cin >>年龄;std::cin.ignore();std::getline(std::cin, 名称);

匹配操作

当您遇到这样的问题时,通常是因为您将格式化输入操作与未格式化输入操作结合使用.格式化输入操作是当您接受输入并将其格式化为某种类型时.这就是 operator>>() 的用途.无格式输入操作是除此之外的任何操作,例如 std::getline()std::cin.read()std::cin.get() 等,这些函数不关心输入的格式,只处理原始文本.

如果你坚持使用单一类型的格式,那么你可以避免这个烦人的问题:

//未格式化的 I/Ostd::string 年龄,姓名;std::getline(std::cin, 年龄);std::getline(std::cin, 名称);

//格式化的 I/O年龄;std::string first_name, last_name;std::cin >>年龄 >>名字 >>姓;

如果您选择使用无格式操作将所有内容作为字符串读取,您可以在之后将它们转换为适当的类型.

I have the following piece of code that prompts the user for their cat's age and name:

#include <iostream>
#include <string>

int main()
{
    int age;
    std::string name;

    std::cin >> age;
    std::getline(std::cin, name);
    
    if (std::cin)
    {
        std::cout << "My cat is " << age << " years old and their name is " << name << std::endl;
    }
}

What I find is that the age has been successfully read, but not the name. Here is the input and output:

Input:

"10"
"Mr. Whiskers"

Output:

"My cat is 10 years old and their name is "

Why has the name been omitted from the output? I've given the proper input, but the code somehow ignores it. Why does this happen?

解决方案

Why does this happen?

This has little to do with the input you provided yourself but rather with the default behavior std::getline() has. When you provided your input for the age (std::cin >> age), you not only submitted the following characters, but also an implicit newline was appended to the stream when you typed Enter:

"10
"

A newline is always appended to your input when you select Enter or Return when submitting from a terminal. It is also used in files for moving toward the next line. The newline is left in the buffer after the extraction into age until the next I/O operation where it is either discarded or read. When the flow of control reaches std::getline(), it will see " Mr. Whiskers" and the newline at the beginning will be discarded, but the input operation will stop immediately. The reason this happens is because the job of std::getline() is to attempt to read characters and stop when it finds a newline. So the rest of your input is left in the buffer unread.

Solution

cin.ignore()

To fix this, one option is to skip over the newline before doing std::getline(). You can do this by calling std::cin.ignore() after the first input operation. It will discard the next character (the newline character) so that it is no longer in the way.

std::cin >> age;
std::cin.ignore();
std::getline(std::cin, name);

Match the operations

When you run into an issue like this it's usually because you're combining formatted input operations with unformatted input operations. A formatted input operation is when you take input and format it for a certain type. That's what operator>>() is for. Unformatted input operations are anything other than that, like std::getline(), std::cin.read(), std::cin.get(), etc. Those functions don't care about the format of the input and only process raw text.

If you stick to using a single type of formatting then you can avoid this annoying issue:

// Unformatted I/O
std::string age, name;
std::getline(std::cin, age);
std::getline(std::cin, name);

or

// Formatted I/O
int age;
std::string first_name, last_name;
std::cin >> age >> first_name >> last_name;

If you choose to read everything as strings using the unformatted operations you can convert them into the appropriate types afterwards.

这篇关于为什么 std::getline() 在格式化提取后跳过输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆