此代码大部分都可以正常工作,即提示用户输入单个字符,执行相关操作,提示用户按返回,然后重复。但是,当我在提示符处输入^ D(EOF)时,会发生无限循环。我通过std :: cin.clear()清除错误状态并调用std :: cin.ignore(...)来清除缓冲区。什么可能导致无限循环?
#include <iostream>
#include <limits>
void wait()
{
std::cout << std::endl << "press enter to continue.";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
std::cin.get();
}
int main()
{
char response;
while (true)
{
std::cout << "enter a character at the prompt." << std::endl << "> ";
std::cin >> response;
switch (response)
{
case 'q':
exit(0);
break;
}
wait();
}
}
如果重要的话,我在Mac OS X终端上运行它。
更新:我在这里真正要求的是,当用户在提示符下输入EOF(^ D)时,我如何(a)检测到它和( b)重置流,以便用户可以继续输入数据。
以下示例与上面的代码不同 ,但说明了在检测到^ D并继续从该流中读取后清除流的相同原理
> a you entered: a > b you entered: b > ^D you entered EOF > c you entered: c ...
答案 0 :(得分:3)
在调用格式化提取操作之后,您应该始终检查是否设置了任何流的失败标志,在您的示例中,您正在检查response
而不检查是否正确提取了response
。
此外,您在提示输出中使用std::endl
,这是没有意义的。 std::endl
打印\n
然后刷新缓冲区,然后立即打印更多字符,以便刷新多余。由于cin
和cout
(通常)绑定,调用std::cin
的输入函数会导致std::cout
在任何情况下都被刷新,所以你也可以将\n
放入提示字符串中,并保存在详细的额外<<
运算符上。
为什么不创建一个打印提示的提示函数,检索输入并返回对流的引用,以便您可以使用通常的流到布尔类型转换来测试它是否成功。
通过这种方式,您可以摆脱真实而明确的突破。
std::istream& prompt_for_input( std::istream& in, std::ostream& out, char& response )
{
out << "enter a character at the prompt.\n> ";
in >> response;
return in;
}
int main()
{
char response;
while ( prompt_for_input( std::cin, std::cout, response ) && response != 'q' )
{
wait();
}
}
答案 1 :(得分:2)
这个问题对标准输入没有意义。在流结束后很难从标准输入中读取内容 - 你必须以某种方式重新打开它,但是没有办法重新打开标准输入。它可能连接到管道,文件或终端 - 并且没有适合所有这些的行为。
因此,我假设您将从终端明确阅读。在UN * X系统上,这意味着读取/ dev / tty,并在需要时重新打开它。这是一个简单的例子;大多数错误检查都被忽略了。
// Warning: UN*X-specific
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
for(unsigned i=0; ; i++) {
ifstream tty("/dev/tty");
if (! tty) {
cerr << "Failed to open TTY" << endl;
return 2;
}
string s;
while (getline(tty,s))
cout << i << ": " << s << endl;
}
return 0; // (unreached)
}
答案 2 :(得分:0)
您需要清除标记,以便在遇到EOF后让流做很多事情。
答案 3 :(得分:0)
呃,我可能会遗漏一些东西,但我从未见过break
循环中的while (true)
。
// ...
while (true) {
if (std::cin.eof()) {
break;
}
// ...
}
答案 4 :(得分:0)
在读取EOF时,您只需忽略它并循环回来,而不退出循环,因此您将不断读取EOF并继续循环。如果你想在看到EOF时做一些事情,你需要在开关中或之前处理它。
也许你想在用户用^ D关闭stdin之后从某处读取输入?在这种情况下,您必须关闭cin并重新打开它以从您想要读取输入的其他位置读取。
答案 5 :(得分:0)
如上所述,您需要确保流未处于错误状态。我会改变条件使用good()。不要只检查EOF,因为除了EOF之外,流有几种方式变得“坏”。
while (std::cin.good()) {...
答案 6 :(得分:0)
while ((std::cout << "Enter a character at the prompt ")
&& (!(std::cin >> response) || response =='q')) {
std::cout << "Not a valid input";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}