94

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

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

4

10 回答 10

90

您可以从中读取可变数量数据的唯一方法stdin是使用循环。我一直发现这个std::getline()功能很好用:

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

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

于 2008-10-14T17:16:38.327 回答
67

Using loops:

#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))
{
   ...
}

resource

于 2008-10-14T17:43:34.543 回答
53

You can do it without explicit loops by using stream iterators. I'm sure that it uses some kind of loop internally.

#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;
}
于 2008-10-14T17:35:00.130 回答
36

在使用 研究 KeithB 的解决方案后std::istream_iterator,我发现了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;
}
于 2016-05-02T09:10:20.150 回答
6

可能最简单且通常有效的:

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

如果需要,在此处使用其他类型的流(std::ostringstream如缓冲区)而不是标准输出流。

于 2015-05-18T15:04:07.333 回答
3

悲伤的旁注:我决定使用 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)),两个测试编译器的吞吐量都跃升至 90 MB/s。这对于任何大于 10 MB 的输入都会有所不同......

于 2012-08-03T10:10:23.833 回答
2

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

于 2008-10-14T17:14:14.183 回答
0
while(std::cin) {
 // do something
}
于 2011-05-25T23:38:17.063 回答
0

一种选择是使用容器,例如

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();
}
于 2014-12-18T23:13:53.357 回答
0

等等,我理解正确吗?您正在使用 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();
    }
于 2012-08-10T17:00:59.430 回答