为什么 cin 在使用 getline 后没有获取缓冲区数据?

Kin*_* Oe 2 c++ cin getline

对于此代码:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>

using namespace std;

#define p(a) cout << "|" << a << "|" << endl
int main() {
    
    char a[100];
    char b[100];

    cin.getline(a, 4, '\n');

    cin >> b;

    p(a);
    p(b);
    
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我的输入是“1234”

1234
Run Code Online (Sandbox Code Playgroud)

我有下一个输出:

|123|
||
Run Code Online (Sandbox Code Playgroud)

但我知道使用 getline,我得到三个元素:"123"它发送到a变量添加到\0字符的末尾。以同样的方式,剩余的字符"4\n"留在缓冲区中。那么为什么在接下来"cin>>"它没有被复制到b变量中?,为什么bnull

use*_*301 6

如果std::istream::getline不能将整行(并终止空值)放入给定的缓冲区,它会设置一个错误标志并且在错误被清除之前变得不可读。

std::istream::get的第四个重载是此用例的更好选择,因为如果整行未被消耗,它不会引发标志。

代替

cin.getline(a, 4, '\n');
Run Code Online (Sandbox Code Playgroud)

cin.get(a, 4, '\n');
Run Code Online (Sandbox Code Playgroud)

无关推荐:

在任何 IO 事务之后,在继续之前测试流的状态,以便您知道是否值得按计划进行,或者事务是否失败并且您必须执行其他操作(例如clear错误并重试)。例如,您可以

if (cin)
{
    // safe to act upon the values read
}
Run Code Online (Sandbox Code Playgroud)

或者,因为几乎所有流函数都返回流以便于 IO 链接,

if (cin.get(a, 4, '\n'))
{
    // safe to act upon the values read
}
Run Code Online (Sandbox Code Playgroud)

自从我提到它,链接是允许代码的魔法

std::cin >> a >> b >> c;
Run Code Online (Sandbox Code Playgroud)

并且与成功的读取测试abc

if (std::cin >> a >> b >> c)
{
    // safe to do stuff with a, b, and c
}
Run Code Online (Sandbox Code Playgroud)