我编码一个程序,直接从用户输入读取数据,并想知道我(没有循环)怎么会阅读所有的数据,直到EOF从标准输入。我正在考虑使用cin.get(input, '\0')
,但'\0'
不是真正的EOF字符,只是读取到EOF或'\0'
,以先到者为准。如何读取直到EOF可以从cin在C++
或者是使用循环的唯一方法来做到这一点?如果是这样,最好的方法是什么?
我编码一个程序,直接从用户输入读取数据,并想知道我(没有循环)怎么会阅读所有的数据,直到EOF从标准输入。我正在考虑使用cin.get(input, '\0')
,但'\0'
不是真正的EOF字符,只是读取到EOF或'\0'
,以先到者为准。如何读取直到EOF可以从cin在C++
或者是使用循环的唯一方法来做到这一点?如果是这样,最好的方法是什么?
可以使用std::istream::getline()(或优选地version that works on std::string)函数获得一个整行。两者都有允许您指定分隔符(行尾字符)的版本。字符串版本的默认值是'\ n'。
的唯一方法,你可以阅读从标准输入数据的变量量使用循环。我总是发现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;
}
尼斯。至于“我确定它在内部使用某种循环” - 任何解决方案都可以。 – 2008-10-14 17:39:37
这似乎从输入除去换行字符,即使它们发生的正中。 – Multisync 2017-09-07 08:44:47
使用循环:
#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))
{
...
}
while(std::cin) {
// do something
}
这是一个答案的一个可怕的灾难,因为它几乎可以肯定会导致错误的代码。 – 2017-02-19 16:43:37
悲伤侧面说明:我决定使用C++ IO是基于增强的代码是一致的。从这个问题的答案我选择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百万字节/秒。这使得超过10 MB更大的任何输入一个区别...
无需代码重写纯C,只需添加一个'的std :: IOS :: sync_with_stdio(假);`您while循环之前。 `cin.tie(NULL);`如果你交错读写,`也可能有所帮助。 – 2017-11-19 21:52:37
等等,我理解正确吗?您使用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
异常结束。如果需要
#include <iostream>
int main()
{
std::cout << std::cin.rdbuf();
}
:为了解决这些问题,可以储备固定量元素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();
}
可能的最简单的和通常是有效,请使用其他类型的流,如std::ostringstream
作为缓冲区,而不是标准输出流。
使用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;
}
东西要小心这里,当你从已通过标准输入管道在读取文件,是这个和大部分给出的答案都会在输入结尾附加一个额外的换行符。并非所有文件都以换行结束,但循环的每次迭代都会将“std :: endl”附加到流中。这在大多数情况下可能不是问题,但如果文件完整性是一个问题,这可能会反过来咬你。 – Zoccadoum 2016-03-29 00:41:00
这不应该是最有争议的答案。请参阅下面的社区维基答案。此外,也许看到这个问题:https://stackoverflow.com/questions/3203452/how-to-read-entire-stream-into-a-stdstring – loxaxs 2017-08-16 10:21:51