c++ - istream 和 cin.get()

标签 c++ cin istream

我对这两段代码的区别有疑问:

char buffer5[5];
cin.get(buffer5, 5);
cout << buffer5;

cin.get(buffer5, 5);
cout << buffer5;

char buffer4;
while (cin.get(buffer4))
{
    cout << buffer4;
}

在第一段代码中,代码获取了5个字符,放入buffer5中。但是,因为您按下了回车键,所以在调用 get() 时不会将换行符放入流中,因此程序将终止并且不会再要求您输入另一轮 5 个字符。

在第二段代码中,cin.get() 等待输入流的输入,因此循环不会终止(我认为)。假设我在输入流中输入了“Apple”。这会将 5 个字符放入输入流,循环会将所有字符打印到输出。但是,与第一段代码不同的是,它并没有停止,即使在两次输入之后我还可以继续输入。

为什么我在第二段代码中可以连续向终端输入字符序列,而不是第一段代码?

最佳答案

首先,除了在输入序列中输入换行符 (\n) 之外,“按回车键”对 IOStreams 没有特殊意义(注意,当使用文本流时,平台特定的行尾序列被转换为单个换行符)。在控制台上输入数据时,数据通常由控制台进行行缓冲,只有在按下 enter 时才会转发给程序(通常可以将其关闭,但详细信息是特定于平台的,无论如何与这个问题无关)。

让我们把注意力转移到 s.get(buffer, n) 的行为上对于 std::istream s和一个指向至少 n 的数组的指针字符 buffer .对其作用的描述非常简单:它调用 s.get(buffer, n, s.widen('\n')) .由于我们正在谈论 std::istream你可能还没有改变 std::locale我们可以假设 s.widen('\n')只返回 '\n' ,即调用等同于 s.get(buffer, n, '\n')其中 '\n'被称为定界符,问题就变成了这个函数的作用。

嗯,这个函数最多提取 m = 0 < n? n - 1: 0字符,在 m 时停止到达或下一个字符与流中剩余的分隔符相同时(如果您希望提取分隔符,则使用 std::istream::getline())。任何提取的字符都存储在buffer的相应位置。如果0 < n空字符存储到位置 buffer[n - 1] .以防万一,如果没有提取字符std::ios_base::failbit已设置。

好的,有了这个我们就应该准备好谜语的所有成分了:当您输入至少一个字符但少于 5 个字符时,第一次调用 get()成功并将换行符保留为缓冲区中的下一个字符。下次尝试get() more characters 立即找到分隔符,不存储任何字符,并通过设置 std::ios_base::failbit 表示失败.这个理论很容易验证:

#include <iostream>

int main()
{
    char buffer[5];
    for (int count(0); std::cin; ++count) {
        if (std::cin.get(buffer, 5)) {
            std::cout << "get[" << count << "]='" << buffer << "'\n";
        }
        else {
            std::cout << "get[" << count << "] failed\n";
        }
    }
}

如果不输入任何字符,首先调用std::cin.get()失败。如果输入 1 到 4 个字符,第一次调用成功,第二次失败。如果输入超过 4 个字符,第二次调用也会成功,等等。有几种方法可以处理可能卡住的换行符:

  1. 只需使用 std::istream::getline()其行为与 std::istream::get() 相同但如果这就是它停止读取的原因,也会提取定界符。然而,这可能会将一行分成多个读取,这可能是需要的,也可能不需要。
  2. 要避免固定行长度的限制,您可以使用 std::getline()连同 std::string (即 std::getline(std::cin, string) )。
  3. 成功后 get()您可以使用 std::istream::peek() 检查下一个字符是否为换行符和 std::istream::ignore()必要时。

哪种方法能满足您的需求取决于您要实现的目标。

关于c++ - istream 和 cin.get(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12165167/

相关文章:

c++ - 验证 native 的 Active Directory 域信任关系

c++ - cin.clear() 如何清除输入缓冲区?

c++ - getline() 与 ifstream 的意外行为

c++ - 使用 getline 从文本文件创建 2 个并行字符串数组

c++ - 在 OpenSSL 中验证 RSA 公钥?

c++ - 在构造函数初始化列表中使用 placement new 的语法是什么

c++,如何验证数据输入是否具有正确的数据类型

c++ - 协助使用基于 C++ 的基本 GPA 计算器和 cin 用法

c++ - 如何实现自定义 std::streambuf 的 seekoff()?

c++ - 如何在cmake中使用#include保持目录结构?