我正在编写一个程序,该程序直接从用户输入中读取数据,并且想知道如何(无循环)从标准输入中读取所有数据直到EOF。我正在考虑使用cin.get( input, '\0' )
但'\0'
不是真正的EOF字符,它会一直读取到EOF或EOF '\0'
,以先到者为准。
还是使用循环是唯一的方法?如果是这样,最好的方法是什么?
Answers:
读取变量数据的唯一方法stdin
是使用循环。我一直发现该std::getline()
功能运行良好:
std::string line;
while (std::getline(std::cin, line))
{
std::cout << line << std::endl;
}
默认情况下getline()
读取直到换行符。您可以指定其他终止符,但EOF本身不是字符,因此您不能简单地对进行调用getline()
。
通过使用流迭代器,可以在没有显式循环的情况下进行操作。我确定它在内部使用了某种循环。
#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;
}
研究了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;
}
std::istreambuf_iterator
而不是std::istream_iterator
,但是用什么呢?
您可以使用std :: istream :: getline()(或者最好是对std :: string起作用的版本)函数来获取整行。两者都有允许您指定定界符(行尾字符)的版本。字符串版本的默认值为“ \ n”。
遗憾的是,我决定使用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的输入,这都会有所不同...
std::ios::sync_with_stdio(false);
在while循环之前添加一个。cin.tie(NULL);
如果您交错阅读和写作,也可能会有所帮助。
while(std::cin) {
// do something
}
// do something
不包含I / O操作返回值的其他检查,并且它所包含的检查是没有意义的。
等一下,我理解正确吗?您正在使用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();
}