这是我的测试代码:
#include<iostream>
using namespace std;
istream& func(istream &);
int main()
{
if(func(cin))
cout<<"good"<<endl;
return 0;
}
istream& func(istream &is)
{
int num;
is.clear();
auto old_state = is.rdstate();
while(is>>num)
cout<<num<<endl;
is.setstate(old_state);
return is;
}
问题是:如果我输入一个字符或EOF标记(我的系统中的ctr_z)来打破while循环,那么程序会直接终止 . 我期望cin流可以重置为正常状态并返回:
if(func(cin))
cout<<"good"<<endl;
但是当程序结束时我无法获得输出 . 那么我的理解有什么不对?
3 回答
您需要忽略该错误然后清除它 . 举个例子,你只需要将while循环更改为:
这是因为setstate并没有真正清除旧标志(阅读链接引用以了解原因)
如果要完全重置标志,则需要使用clear函数 . 不是我真的推荐它,因为它给你一个虚假的流状态 . 相反,你应该明确检查状态 .
在无效输入后可以恢复状态:未能根据预期类型解析输入,只需设置
std:: ios_base::failbit
,这可以是clear()
. 由于不会删除导致问题的字符,因此您可能需要摆脱它(例如使用ignore()
)或以不同方式对数据进行parae .虽然EOF也只是一个标志(
std::ios_base::eofbit
)清除它一般不会从已经到达流的末尾恢复 . 特定流可以具有继续读取的方式,但是在流指示符结束之后控制台很可能被断开(例如,Ctrl-D或Ctrl-Z) . 根据系统,可以创建到控制台的新连接,例如,通过打开文件流到/dev/tty
.如果您确实想使用控制字符来指示特殊处理,请使用
tcgetattr()
和tcsetattr()
将流设置为非规范模式 . 完成此操作后,可以看到输入的所有字符,并且可以在自定义流缓冲区中进行处理 . 我不知道如何在其他系统上做类似的事情 .