我对c++输入输出流的理解

 

c++没有内置输入输出功能。原因:脱离系统硬件。这正是c++的优点之一。如果为某操作系统设计了这种功能,那么,c++也就绑死在这系统上了。 通过include     标准输入输出文件,我们可以方便的实现所需要的功能。C-programmer 都很熟悉stdio.h这个文件,以及诸如printf 和scanf这两个函数,c++做了改进,引入了iostream,注意,不是 iostream.h(这是相关标准制定前使用的文件,未包括在std空间中。

自然,iostream是有着其先进性的。一 类型安全,不会像scanf或者printf那样截取浮点数的一部分赋给整型变量,或者犯下其他类似的错误。i.e     float f =12.34;printf("%d",f);二 可扩充性 我们可以重载相关输入输出符来实现编制的类的输入输出,方便了好多啊,比如 string就是这样子的,呵呵。好,下面我们来说一下具体的实现。

对于c++程序来说,输入输出是以内存为标准来衡量的,并且程序将全部设备(磁盘,键盘和显示器)都视为文件,用过linux的兄弟们都知道块设备 以及字符设备这些名词吧?那么,“流”又是什么呢?根据双水的理解呢,程序和流(分为输入和输出)打交道,流和文件捆绑,从而实现了输入输出的功能。想想 虚拟机,流就像逻辑设备一样,在物理设备之上。这样讲,可能会有一些偏差,但大概就是这个样子的,^_^

下面说说标准库里的类吧?说到类,可就多了,其中继承(还有多重继承)比较罗唆。简单讲,ios是基类,就像VC里的CObject一 样,istream和ostream都是从ios派生而来,iostream又是从istream和ostream派生而来,这三个类基本上都是处理硬件 设备的,就这样理解吧。精确的话。实际上,标准库里大部分都是类模版,相对于某个固定的字符类型(如w_chart),才会成为一个实在的类。

对于流的实例,一般需要三个步骤:打开“文件”,操作,关闭“文件”。这里,有几个特例,cin,cout,cerr,clog。c++已经在头文 件里定义了它们,因为它们实在是用的太多了。i.e.        ostream cout (stdout);在这里,对应于每个内置数据类型,都有一个对应的友元函数(返回值是流的地址)来实现<<和>>的重载。好 了,好像讲了1/3了,下面是不是该讲一下文件和c风格字符串的操作了??

NO。上面只是一个大体的框架,我想再讲几个小的问题:一 缓冲存在的必要性     好像输出的缓冲用的多一些,这里也只讲它了。缓冲之所以存在是因为防止数据发送接收不同步引起数据的丢失,这样理解如果不对,要告诉我呦,呵呵。输出时必 须注意及时的刷新,因为有可能还没有输出而是停留在了缓冲区内,这在调试崩溃的程序时是非常重要的。刷新可以用多个manipulator,比如 flush,endl,ends。区别在于:flush只负责刷新,不添加任何字符,endl用的多了,相当 于"<<'/n'<<flush,ends用的少,相当于在缓冲区里加一个NULL字符,然后刷新它。其次,再给大家讲一个不太 会用到的方法(个人意见很好的一个方法),cin.tie(&cout),将输入流和输出流绑在一起,这样,每个读取输入流的尝试都会刷新输出的 缓冲区,这个可以在交互式系统中应用。另外,还有以下的用法:ostream * old_tie=cin.tie(&cout); cin.tie(0);//解除绑定 cin.tie(old_tie);//恢复原来地方式。好了,关于刷新就说这些了。

看到这里的小朋友们,是否觉得我说得有点罗唆呢?双水觉得呢,输入输出是最为基本的,并且在高级应用中还是很有用滴,呵呵。

二 好了,关于标准输入输出再讲最后一点,这一点也是我查资料,自己调程序加上自己的理解得到的结果,中间可能有不对的地方,还希望东东或者其他的达人给俺解 释一二。好了,闲话少说。先说enter键和回车键在键盘上的位置,对于IBM标准的键盘来说,enter键是最右下角那个,旁边是一堆数字,回车键是最 大的那个,在backspace键下面。好像在平时生活中用的时候这点不会十分在意,因为根据我调程序所得,这两个键的ASCII码是一样的,所以平时不 必太区分,但是意义是不同的,同志们,enter键是对对话框的默认选项的键盘default操作,return键呢,是 carriage return 键,即CR键,在c++程序里,它们的ASCII码都是0x0D,即'/r'。注意,这里指得是未进入输入缓冲区且未经系统处理的答案,使用 getch()实现(必须包括conio.h文件)。如果进入了输入流缓冲区的话,那么,注意了,经过了系统的处理,enter键和return键的 ASCII码为0x0A,即'/n',这里用到的函数是getchar()。我想,这里和操作系统是有一定关系的。在很早以前呢,打印机是很重要的输出设 备,所谓carriage return 和line feed都是那时候的产 物,英语稍微好点的人一目了然,至于意义太简单我就不说了,咱们都是高手,呵呵。在打印时,如果要换行至下一行行首,这两个字符都是必须的。后来,在计算 机的早期,存储是珍贵的,所以,有的系统将它俩简化为一个字符,例如,unix(以及linux)操作为line feed,mac os以及apple II将它简化为 carriage return,windows则没有改变。这样带来了一个问题,linux下的文本和windows下的文本交互查阅将导致不正常的显示,呵呵,扯远了。 我想说的是,c++将'/r' 转换为'/n'极有可能和这一点有关,毕竟C和linux的关系非同一般。

下面说说enter键,对于输入流来说,enter键相当于将你输入的数据放在了输入缓冲区里,包括'/n'。那么,cin只是处理相符合的那一部 分,直到格式不相符为止,如果一开始格式就有错误,那么就会产生failbit,哎呀,关于这一点,我竟然还没有提到,罪过。这是输入输出流的条件状态, 非常关键的一块。待会儿再讲它。如果多输入了不相符亦即不能被cin传递给变量的将在缓冲区里呆着直到你能利用它,这里数据是不可能插队的,所以输入时一 定要按要求呀。这里有一个问题,你提交数据时那个'/n'也进入缓冲区了呀?这里我的粗浅的理解是,如果下面是cin>>a,a为某内置类型 或者类(当然>>要重载),那么这个'/n'将会被跳过,如果cin.getline()或者cin.ignore()将不会跳过。看个例子 就好了。

char m='y',n;
char a[100];
//string b;
while(m=='y')
{
cout<<"请输入字符"<<endl;
cin.getline(a,sizeof(a),'/n');
//cin>>b;
cout<<a<<endl;
memset(a,0,sizeof(a));
cout<<"继续输入输入 y"<<endl;
cin>>m;
}

这个循环是失败的,原因,简单,'/n'还在缓冲区里,用一个cin,get(n)或者cin.ignore(),搞定。呵呵,如果用string接收输入,就没这个问题,我已试过,呵呵。下面说说上面提到过的条件状态。

cin有一些标志,当其中错误flag置位时,cin就死掉了,cout还活着(这里,我一开始想错了,如果定义一个chat变量,未初始化,那么 它是没法cout的,和int不同),你就不能再用了。除非你恢复它。这里的恢复就是clear()函数。流共有三种错 误:cin.bad(),cin.fail(),cin.eof()。好了,解释一下,bad标志系统级别的错误,如无法恢复的读写错误,如果这个函数置 一的话,恭喜你,中彩成功,一般通过异常处理然后退出吧。fail标志输入格式错误,可以用clear()函数恢复,eof则表示文件末尾end of file嘛!istream::io_state    old_state=cin.rdstate ();我一般在使用前先来这么一句,然后如果fail了,可以cin.clear(old_state),就好了。《c++经典》里的例子说 cin.clear(istream::failbit)没有实现,应该是错误的,因为我在linux下也试过了,也失败了,呵呵。关于clear()和 setstate()具体用法呢?这样讲,cin.clear(ios::iostate state=goodbit),如果不给它arguement,那么,它会清除所有的错误状态。如果赋了非goodbit以外的值(比如 eofbit,badbit,failbit),那么这个位就将置位,(和它名字不符,别受骗呦)。但是它是覆盖性的。累了,不解释 了,setstate()克服了这点,呵呵。说说这几个位吧,都是enumerator。goodbit是0,eofbit是1,failbit是 2,badbit是3,rdstate()读到的是这四个的和。

最后,我想批评一下微软。啥VC啊,有好几个BUG,例如文件结束符,还有getline(),好了,人家也承认是BUG了,不过最基本的都没有保 证,还在那儿只知道增加新功能还有扩展易用性,这样不好,哈哈,好,到了该结束的时候了,就说这些吧,关于文件流和字符串流下篇文章会讲。累死我了,写这 个,毕竟是我的技术派处女贴,呵呵。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值