首页 文章

C:进入EOF后可以恢复cin流的状态

提问于
浏览
1

这是我的测试代码:

#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 回答

  • 0

    您需要忽略该错误然后清除它 . 举个例子,你只需要将while循环更改为:

    while(true)
        {
            if(is>>num)
                cout<<num<<endl; //if cin is numeric
            else // we have an error
            {
                is.ignore(); // ignore the last error (else your program will run crazy)
                is.clear(); // clear the state
                break; // terminate console reading
            }
        }
    
  • 1

    这是因为setstate并没有真正清除旧标志(阅读链接引用以了解原因)

    如果要完全重置标志,则需要使用clear函数 . 不是我真的推荐它,因为它给你一个虚假的流状态 . 相反,你应该明确检查状态 .

  • 0

    在无效输入后可以恢复状态:未能根据预期类型解析输入,只需设置 std:: ios_base::failbit ,这可以是 clear() . 由于不会删除导致问题的字符,因此您可能需要摆脱它(例如使用 ignore() )或以不同方式对数据进行parae .

    虽然EOF也只是一个标志( std::ios_base::eofbit )清除它一般不会从已经到达流的末尾恢复 . 特定流可以具有继续读取的方式,但是在流指示符结束之后控制台很可能被断开(例如,Ctrl-D或Ctrl-Z) . 根据系统,可以创建到控制台的新连接,例如,通过打开文件流到 /dev/tty .

    如果您确实想使用控制字符来指示特殊处理,请使用 tcgetattr()tcsetattr() 将流设置为非规范模式 . 完成此操作后,可以看到输入的所有字符,并且可以在自定义流缓冲区中进行处理 . 我不知道如何在其他系统上做类似的事情 .

相关问题