一  流状态
   C++中的输入输出系统负责记录每一个输入输出操作的结果信息,这些当前的状态信息被包含在io_state类型的对象中。io_state是一个枚举类型(就像open_mode一样),以下便是它包含的值。  
eofbit 已到达文件尾 
failbit 非致命的输入/输出错误,可挽回 
badbit 致命的输入/输出错误,无法挽回

这三个标志位均用一位二进制位来表示,0表示清除,1表示设置。

对于eofbit,failbit,badbit。0表示正常,1表示被设置。

这三个整体构成了流的状态。若三个均为0,表示流状态正常,反之,若有一个为1,流状态非正常。包括达到了文件尾,出现可恢复性错误,出现了不可恢复性的错误。

另外还有一个标志位goodbit用来测试流状态是否正常。如果流状态正常返回true,输出1.否则输出0。
相对应与这四个标志位有四个函数分别用来测试相应的标志位的状态。他们分别为:

bool bad();

bool eof();

bool fail();

bool good();

看上去这四个函数的返回值是bool类型,返回值应该是true和false,也就是在我们C++里,0代表false,非0代表true,但是,在我们输出他们的结果时,得到的是0和1.不是true和false,也不是0和非0值。

二 测试流状态。

对于流状态的测试我们有三种方法。

1 rdstate()函数

我们可以用这个函数来返回当前的流状态。若我们用该函数输出当前流的状态信息,他输出的并不是一个二进制数。他输出的是一个十进制。是将二进制转换为对应的十进制后输出的。我们可以写个小程序进行一下测试,我们可以测试输入流的状态,也可以测试输出流的状态。

如:

#include <iostream>
using namespace std;
int main()
{
    cout << "hello" << endl;
    cout << cout.rdstate() << endl;//输出当前的流状态
    if(cout.rdstate() == ios::goodbit) 
    { 
     cout<<"输出数据的类型正确,无错误!"<<endl; 
    } 
    if(cout.rdstate() == ios_base::failbit) 
    { 
     cout<<"输出数据类型错误,非致命错误,可清除输入缓冲区挽回!"<<endl;
    } 
    system("pause"); 
    return 0;
}

输出的当前的流状态为0.    表示当前流状态正常,那么他就和我们的if条件判断语句中的    第一个相匹配了。由此可知,rdstate() 返回的是eofbit,failbit,badbit三个标志的值,即返回的是一个strm::iostate类型。

2 我们可以用三个标志位对应的函数来测试当前的流状态。

如:

#include <iostream>
using namespace std;
int main()
{
 cout << "你好吗?" << endl;
    cout <<  cout.eof() << cout.fail() << cout.bad() << endl; 
    cout << cout.good() << endl;
    return 0;
}

输出结果为:

你好吗?

000

1

前面的000表示三个标志位对应的值,均为0,由此可知此时流状态正常,故goodbit标志位被设置。所以good()函数输出结果为1.

3 用流本身来测试

如:

if (cin)

while (cin >> word)

if语句直接检查流的状态,while语句则检测表达式的返回值,即间接的检查流状态。

我们可以用如下的函数进行测试:

#include <iostream>
using namespace std;
int main()
{
 int i;
 cin >> i;
 if (cin)
 {
  cout << "流状态正常" << i << endl;
 }
 else
 {
  cout << "流状态不正常" << i << endl;
 }
    return 0;
}

当我们输入的值为整型值或是能隐式转换成整型值时,当前输入流状态有效,若我们输入了字符串类型值,则会使当前输入流状态无效。

同样我们也可以对while语句进行测试。

#include <iostream>
using namespace std;
int main()
{
 int i;
 
 while(cin >> i)
 {
  cout << "当前输入流状态有效" << endl;
 }
 cout << "输入流状态无效" << endl;
 
    return 0;
}

当我们输入的值为整型值或是能隐式转换成整型值时,当前输入流状态有效,若我们输入了字符串类型值,则会使当前输入流状态无效。

三 表示流状态的四个常量

标记位常量

常量

含义

failbit标记位的值

eofbit标记位的值

badbit标记位的值

转化为10进制

ios::failbit

输入(输出)流出现非致命错误,可挽回

1

0

0

4

ios::badbit

输入(输出)流出现致命错误,不可挽回

0

0

1

2

ios::eofbit

已经到达文件尾

0

1

0

1

ios::goodbit

流状态完全正常

0

0

0

0

下面来解释这张表格:
ios::failbit    ios::badbit    ios::eofbit    ios::goodbit均为常量,它们任何一个都代表了一种流状态,因此称为“输入状态标记位常量”。
比如,ios::failbit表示的是流状态为:
 流的failbit标记位值为1,eofbit标记位值为0,badbit标记位的值为0。
         
始终牢记:failbit,badbit,eofbit组成了流状态
        
注意:它们不是failbit、badbit、eofbit、goodbit这四个标记位的存贮变量。
这四个常量我认为是strm::iostate类型的常量值。
分别对应于:
ios::failbit 010  ---2
ios::badbit  100  ---4
ios::eofbit  001  ---1
ios::goodbit 000  ---0
我们可以用函数来测试这三个常量的值:
#include <iostream>
using namespace std;
int main()
{
    cout << ios:: failbit << endl;
    cout << ios:: badbit << endl; 
    cout << ios:: eofbit << endl;
    cout << ios:: goodbit << endl;
    return 0;
}
由此我们也可以得出表示流状态的三个标志位的顺序为:
badbit,failbit,eofbit
注意: ios::failbit ,ios::badbit,ios::eofbit,ios::goodbit均为常量值,它与当前的流状态无关。

四 设置流状态

1 设置流状态函数我们可以用setstate(flag)函数.参数为一个strm::iostate类型的值。

如: cin.setstate(ios::eofbit);

注意,它的目的并不是将流状态ios::eofbit替换(或覆盖)当前的输入流状态。而是仅仅的将标志位eofbit置1,其他位保持不变。

好的,既然设置好了。我们可以来查看一下我们的流状态是否设置成功了:

#include <iostream>
using namespace std;
int main()
{
 cout << "输入流设置前的状态: " << endl;
 cout << cin.bad() << cin.fail() << cin.eof() << endl;
 cin.setstate(ios::failbit);
 cout << "输入流设置后的状态: " << endl;
 cout << cin.bad() << cin.fail() << cin.eof() << endl;
    return 0;
}

然后我们再进行一下测试,看一下函数setstate是否覆盖我们原来的状态:

我们还用上一个函数,加点语句。

#include <iostream>
using namespace std;
int main()
{
 cout << "输入流设置前的状态: " << endl;
 cout << cin.bad() << cin.fail() << cin.eof() << endl;
 cin.setstate(ios::failbit);
 cout << "输入流设置第一次后的状态: " << endl;
 cout << cin.bad() << cin.fail() << cin.eof() << endl;
 cin.setstate(ios::badbit);
 cout << "输入流设置第二次后的状态: " << endl;
 cout << cin.bad() << cin.fail() << cin.eof() << endl;
    return 0;
}

输出结果为:

000

010

110

由此可知,函数setstate函数并没有覆盖我们原来的流状态,而是仅仅的设置了对应位。

2 当我们设置了ios::failbit,ios::eofbit,ios::badbit流状态后,由于该三种状态为非正常状态,故设置后,对应的输入流或是输出流就处于无效状态,我们此后对于该流的任何使用均为无效,不起作用。

不妨我们来测试一下:

#include <iostream>
using namespace std;
int main()
{
 cin.setstate(ios::failbit);
 int i;
 cin >> i;
 cout << "hello!" << endl;
    return 0;
}

上面这个程序不等待我们输入直接就输出了结果hello!由此可知,cin状态在设置后已处于无效状态,所有对此的操作均为视为透明的,或是无效的,直接跳过。那我们如何将流状态重置为有效呢,我认为有三种方法:

①:我们可以用函数clear();将流的所有状态重设为有效状态。

②:我们可以用函数clear(flag);

flag 可选值有ios::badbit ios::failbit ios::eofbit,这里参数的意思是重设对应的标志位有效。

③:我们可以用函数setstate(ios::goodbit);重设流有效状态

但经我在VC++ 6.0,VC++ 2008上测试后两种方法虽能成功运行,但并没起到作用。第一种方法可以。

#include <iostream>
using namespace std;
int main()
{
 cin.setstate(ios::failbit);

cin.clear();
 int i;
 cin >> i;
 cout << "hello!" << endl;
    return 0;
}

输入流重为有效状态

此题的while循环的判断调件是,只要没有遇到文件结束符,不管输入流是否有效均执行循环体。

。下面我们再来整体看一个函数:

#include <iostream>
using namespace std;
int main()
{
 int i;
 while (cin >> i,!cin.eof())
 {
   try
   {
  if (cin.bad())  //出现系统故障
  {
   throw runtime_error("输入输出流出现故障");  //抛出异常
  }
   }
   catch(runtime_error err) //处理异常
   {
    cout << err.what() << endl; //输出异常原因
    cout << "try again?y/n" << endl;
    char c;
    cin >> c;
    if ('y' == c)
    {
     continue;
    }
    else
    {
     break;
    }
    
   }
  if (cin.fail()) //出现了可恢复错误
  {
   cerr << "bad data, try again";
   cin.clear(); //重置输入流有效
   cin.ignore(20,' '); //忽略20个输入字符。若不写此语句将陷入死循环。
   continue;
  }
  cout << i << " ";
 }
    return 0;
}

此题的while循环的判断调件是,只要没有遇到文件结束符,不管输入流是否有效均执行循环体。

初识io流条件状态的更多相关文章

  1. 初识IO流之小型资源管理器

    初次接触到IO流,根据书本上的知识,加上自己的摸索,发现了一些好玩的事情.(书本上的知识或多或少,有时候不足以解决我们的问题!这时候我们就应该自己去求解!!! 所以我们学习的时候要抱有探索的精神,求知 ...

  2. Java学习 · 初识 IO流

    IO流   1. 原理与概念 a)     流 i.           流动,流向 ii.           从一端移动到另一端 源头到目的地 iii.           抽象.动态概念,是一连 ...

  3. 初识IO流

    输入输出流,用来进行设备之间的数据传输. 是我们IO传输的数据是以文件的形式体现的,所以Java给我们提供了一个类,Flie用来描文件和目录 File(File parent, String chil ...

  4. ca73a_c++_流的条件状态

    /*ca73a_c++_流的条件状态strm::iostate strm::badbit //流的状态strm::failbit //输入的状态,应该输入数字,结果输入为字符,strm::eofbit ...

  5. 从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态

    一.文件流 ofstream,由ostream派生而来,用于写文件 ifstream,由istream派生而来, 用于读文件 fstream,由iostream派生而来,用于读写文件 二.打开文件 说 ...

  6. 关于Java中面向对象章节、IO 流中的重点基础知识。

    一.面向对象的三大特征,以及作用. 答:面向对象的三大特征即,封装性.继承性.多态性. 其分别的作用为 : 封装作用:将数据封装起来,提高数据的安全性, 继承作用:提高代码的复用性,减少冗余代码. 多 ...

  7. java IO流 对文件操作的代码集合

    Io流 按照分类 有两种分类 流向方向: 有输入流和输出流 按照操作类型有:字节流和字符流 按照流向方向 字节流的一些操作 //读文件 FileInputStream fis = new FileIn ...

  8. C++ IO流小结

    撒花庆祝下,终于看完了(C++Primer)第一部分,即将进入第二部分! IO部分,最基本的是iostream(istream.ostream),子类有fstream(ifstream.ofstrea ...

  9. IO流C++

    1.iostream处理控制台IO #include<iostream> #include<string> using namespace std; istream& ...

随机推荐

  1. winform 清空界面所有控件已输入的值

    rivate void btnClear_Click(object sender, EventArgs e){ ClearCntrValue(this.pnlContent);}   复制代码/// ...

  2. mongodb的常用操作(二)

    继续mongodb的学习: 9.mongodb条件查询 假设有user集合,里面结构如下:{ "_id" : ObjectId("52ab35d281181f853264 ...

  3. CentOS 7 yum nginx MySQL PHP 简易环境搭建

    用centos自带的yum源来安装nginx,mysql和php,超级方便,省去编译的麻烦,省去自己配置的麻烦,还能节省非常多的时间. 我们先把yum源换成国内的阿里云镜像源(当然不换也可以),先备份 ...

  4. jdbc连接数据库使用sid和service_name的区别

    问题描述: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor The Connect ...

  5. sqlalchemy - day1

    一.Create engine Database url规则: dialect+driver://username:password@host:port/database echo: True表示cm ...

  6. 把数组排成最小的数/1038. Recover the Smallest Number

    题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323.   Give ...

  7. 部署keepalived

    下载 keepalived-1.1.20.tar.gz tar  -xvf  keepalived-1.1.20.tar.gz [root@yoon export]# cd keepalived-1. ...

  8. ASP.NET MVC +EasyUI 权限设计(四)角色动作

    请注明转载地址:http://www.cnblogs.com/arhat 由于最近的事情比较多,一直忙于工作和照顾老婆,所以老魏更新的速度慢了,本来写文章就要占据工作和生活很多的时间,这也就是院子中很 ...

  9. iOS开发网络篇—大文件的多线程断点下载(转)

    http://www.cnblogs.com/wendingding/p/3947550.html   iOS开发网络篇—多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了 ...

  10. 【UIScrollView】基本方法+基本描述

    scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(, , , )]; scrollView.backgroundColor = [ ...