如何在C++中从cin读取EOF

How to read until EOF from cin in C++

本文关键字:cin 读取 EOF 中从 C++      更新时间:2023-10-16

我正在编写一个直接从用户输入读取数据的程序,我想知道如何(没有循环)从标准输入读取所有数据,直到EOF。我曾考虑使用cin.get( input, '' ),但''并不是真正的EOF字符,它只读取到EOF或'',以先到者为准。

还是使用循环是唯一的方法?如果是,最好的方法是什么?

stdin读取可变数据量的唯一方法是使用循环。我一直发现std::getline()功能运行得很好:

std::string line;
while (std::getline(std::cin, line))
{
    std::cout << line << std::endl;
}

默认情况下,getline()读取到换行符。您可以指定另一个终止字符,但EOF本身不是一个字符,因此您不能简单地调用getline()

使用循环:

#include <iostream>
using namespace std;
...
// numbers
int n;
while (cin >> n)
{
   ...
}
// lines
string line;
while (getline(cin, line))
{
   ...
}
// characters
char c;
while (cin.get(c))
{
   ...
}

资源

您可以使用流迭代器在没有显式循环的情况下完成此操作。我确信它在内部使用了某种循环。

#include <string>
#include <iostream>
#include <istream>
#include <ostream>
#include <iterator>
int main()
{
// don't skip the whitespace while reading
  std::cin >> std::noskipws;
// use stream iterators to copy the stream to a string
  std::istream_iterator<char> it(std::cin);
  std::istream_iterator<char> end;
  std::string results(it, end);
  std::cout << results;
}

在使用std::istream_iterator研究KeithB的解决方案后,我发现了std:istreambuf_iterator

测试程序,将所有管道输入读取为字符串,然后再次写出:

#include <iostream>
#include <iterator>
#include <string>
int main()
{
  std::istreambuf_iterator<char> begin(std::cin), end;
  std::string s(begin, end);
  std::cout << s;
}

可能最简单且普遍有效:

#include <iostream>
int main()
{
    std::cout << std::cin.rdbuf();
}

如果需要,可以使用std::ostringstream等其他类型的流作为缓冲区,而不是这里的标准输出流。

不幸的是:我决定使用C++IO来与基于boost的代码保持一致。从这个问题的答案中,我选择了while (std::getline(std::cin, line))。在cygwin(mintty)中使用g++版本4.5.3(-O3),我获得了2 MB/s的吞吐量。对于相同的代码,Microsoft Visual C++2010(/O2)使其达到40 MB/s。

在将IO重写为纯C while (fgets(buf, 100, stdin))之后,两个测试编译器的吞吐量都跃升至90MB/s。这对任何大于10MB的输入都有影响。。。

您可以使用std::istream::getline()函数(最好是处理std::string的版本)来获取整行。两者都有允许您指定分隔符(行尾字符)的版本。字符串版本的默认值为"\n"。

while(std::cin) {
 // do something
}

等等,我能正确理解你吗?您正在使用cin进行键盘输入,并且希望在用户输入EOF字符时停止读取输入?为什么用户会输入EOF字符?或者你是说你想在EOF停止读取文件?

如果您实际上试图使用cin读取EOF字符,那么为什么不将EOF指定为分隔符呢?

// Needed headers: iostream
char buffer[256];
cin.get( buffer, 'x1A' );

如果您想在EOF处停止读取文件,那么只需使用getline并再次指定EOF作为分隔符。

// Needed headers: iostream, string, and fstream
string buffer;
    ifstream fin;
    fin.open("test.txt");
    if(fin.is_open()) {
        getline(fin,buffer,'x1A');
        fin.close();
    }

一个选项是使用容器,例如

std::vector<char> data;

重定向所有输入到此集合,直到收到EOF,即

std::copy(std::istream_iterator<char>(std::cin),
    std::istream_iterator<char>(),
    std::back_inserter(data));

但是,使用过的容器可能需要过于频繁地重新分配内存,或者当系统内存不足时,您将以std::bad_alloc异常结束。为了解决这些问题,您可以保留固定数量的N元素,并单独处理这些数量的元素,即

data.reserve(N);    
while (/*some condition is met*/)
{
    std::copy_n(std::istream_iterator<char>(std::cin),
        N,
        std::back_inserter(data));
    /* process data */
    data.clear();
}