C++IO流:你不知道的事(一)

来源:互联网 发布:mindmap for mac破解 编辑:程序博客网 时间:2024/05/22 13:41

C++IO流:你不知道的事(一)

(2011-05-14 14:01:30)
转载
标签:

c

cin.fail()

cin

分类:Cpp
 
  最近帮某胖(此胖是个懒胖)的同学写了个DOS下的简易通讯录,只有一个要求:要对输入进行围追堵截式的检测。之前写东西因为老师已经给了一堆的测试数据,倒是对这种健壮性的问题考虑的很少,不得以再次一头扎进了C++primer里。。
   要实现的功能如下:
    C++IO流:你不知道的事(一)
下面用switch语句的8个case对应这八个命令,default语句提示用户重新输入命令:
    C++IO流:你不知道的事(一)
如此保证只要不输入0,就不退出DOS窗口,在循环底部加上system("pause")和system("cls"),算是我用惯了的手段。但第一个问题也随之而来:当输入非数字时,将执行上一次执行的命令。例子如下:
    C++IO流:你不知道的事(一)
输入非数字命令"test",由于demand初始时为1,故执行操作1:读取联系人列表。
   这个输入数据类型验证一度搞得我很抓狂,后来想了想,仍然执行上一个操作,说明本次输入没有成功,于是果断在cin的函数里找到了cin.fail(),木哈哈~~
   修改后的代码如下:
    C++IO流:你不知道的事(一)
   将此段代码添加在cin>>demand后,一旦输入的是非数字类型,则输入fail,即令demand=8,使程序执行switch块里的default语句。其中的cinCacheClear()函数是遇到第二个问题后才加上去的,若没有这个语句,程序将进入死循环:输入一个非数字类型,提示错误信息,回车清屏后再次提示错误信息。。。
    C++IO流:你不知道的事(一)C++IO流:你不知道的事(一)
显然第一次执行之后便跳过了所有输入,而直接demand=8->default了。。。
   查了网上的一些帖子,才发现原来简单的cin>>x是分两步的:第一步输入数据,将数据保存到缓冲区;第二步输入回车,将缓冲区的数据放入变量中,缓冲区大致上是队列形式的,即先输入先处理。
   明白了原理就明白了:之前输入的test已经存入了输入缓冲区中,但由于与demand类型不匹配,所以在赋值的时候fail,就没有执行出队列操作,一直呆在缓冲区的“队首”,参与了接下来的每一次if(cin.fail()),自然都是fail了。。。
   于是增加了两个cin的函数:
C++IO流:你不知道的事(一)
将它们打包起来,一是便于读代码者理解(--b连通讯录都要人帮忙写对她期待不能太高),二是之后还有需要使用这两个函数的地方。
   注释里提到了cin流的错误状态,以下引用C++ primer248页的解释(有书的童鞋可以自己看看去):
   “所有流对象都包含一个条件状态成员,该成员由setstate和clear操作管理。这个状态成员为iostate类型,这是由各个iostream类分别定义的机器相关的整型。该状态成员以二进制位的形式使用。
    每个IO类还定义了三个iostate类型的常量值,分别表示特定的位模式。这些常量值用于指出特定类型的IO条件,可与位操作符一起使用,以便在一次操作中检查或设置多个标志。badbit标志着系统级的故障,如无法恢复的读写错误;若出现的是可恢复的错误,如在希望获得数值型数据时输入了字符,此时则设置failbit标志。eofbit是在遇到文件结束符时设置的,此时同时还设置了failbit。
   流的状态由bad、fail、eof和good操作揭示。若good操作返回true,则说明之前的三个条件都是false。
   clear和setstate操作用于改变条件成员的状态。clear操作将条件重设为有效状态。在流的使用出现了问题并作出补救后,如果我们希望把流重设为有效状态,则可与调用clear操作。使用setstate操作可打开某个指定的条件,用于表示某个问题的发生。除了添加的标记状态,setstate将保留其他已存在的状态变量不变。”
   
   加入cinCacheClear()之后程序即正常运行,至此UI方面(DOS下的UI。。。)的输入检测基本完善,开始对通讯录的具体实现进行改善。(未完待续)
0 0
原创粉丝点击