-->

istream和cin.get()(istream and cin.get())

2019-06-27 11:28发布

我有一个关于这两段代码之间的区别问题:

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()等待输入到输入流,所以该环不只是终止(我想)。 可以说,我输入“苹果”到输入流。 这将会把5个字符到输入流,并循环将打印所有字符输出。 然而,与第一段代码,它不会停止,即使在两个输入端,我可以继续保持输入。

为什么我能连续输入的字符序列到第二代码段的终端而不是所述第一?

Answer 1:

首先,“按压输入”具有超过进入换行符(无特殊意义的输入输出流\n )到输入序列(注意,使用文本时流线的序列的平台特定的最终被变换成单个换行字符)。 当在控制台上输入数据时,数据被正常线由控制台缓冲,并且只按压时输入转发到程序(通常这可以被关闭,但这样做的细节是特定于平台的和不相关的这个问题反正)。

有了这个出路可以让我们把目光转向行为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 = 0 < n? n - 1: 0字符,当任一停止m达到或当的下一个字符是相同的,其在流中留下的定界符(你所使用std::istream::getline()如果你想要的定界符将被提取)。 任何提取的字符被存储在相应的位置buffer ,并且如果0 < n空字符被存储到位置buffer[n - 1] 在情况下,如果没有提取字符std::ios_base::failbit设置。

OK,这个我们应该有所有成分到位谜:当你输入的至少一个字符,但少于5个字符第一次调用get()成功离开了换行符作为缓冲下一个字符。 下一次尝试get()更多的字符后,立即找到了分隔符,没有存储特性,并通过设置指示故障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()它在必要时。

哪些方法满足您的需求取决于你想要达到的目的。



文章来源: istream and cin.get()
标签: c++ cin istream