I/O操作 – 流基础

1)          C语言 I/O<cstdio>函数的比较

l       printf (%s%f%d”,…)

即使使用它一个,所有关于I/O的操作库函数都要包含进来,使得程序变大。

 

l       另外,它是运行时才解析输出格式,效率比较低。

 

l       C I/O缺乏编译时刻检查,比如,里面是%s,传入的参数却是整数。运行时刻才抛出异常。

 

l       C I/O不具备可扩展性,只能输出基本类型的数据,不能重载输出自定义类型的数据。

 

2)          C++ I/O流结构

为了方便,C++定义了<iosfwd>头文件,一般只需include它就行;不行的话再include<iostream>

 

l       ios_base基类 public ios

定义了所有流共有的内容,不依赖于流所处理的字符类型。

 

l       basic_ios<charT> public ios_base

定义跟字符相关的输入输出共有的类,一般很少使用。

 

l       basic_istream<charT> : public basic_ios<charT>

 typedef basic_istream<char> istream;

 typedef basic_istream<wchar_t> wistream;

 

istream cin;

 

l       basic_ostream<charT> : public basic_ios<charT>

 typedef basic_ostream<char> ostream;

 typedef basic_ostream<wchar_t> wostream;

 

 ostream cout;

 ostream cerr;

 

cerrcout的不同是cerr不带缓冲区(将unitbuf打开),比较快。

 

l       basic_iostream<charT>

: public basic_istream<charT>, 

  basic_ostream<charT>

                        typedef basic_iostream<char> iostream;

  typedef basic_iostream<wchar_t> wiostream;

 

3)          重载I/O

l       ostream& operator << (ostream& os, const Data& data)

ostream参数不能是const,因为输出会改变流的状态。

 

l       istream& operator >> (istream& is, const Data& data)

istream参数不能是const,因为输入会改变流的状态。

 

4)          按行输入

l       get(缓冲区指针,缓冲区大小,结束符 = ‘/n’) – istream 成员函数

其遇到结束符时,不从流中提取它,然后方法返回。怎么办呢,只能想办法把结束符去掉,然后再进行读取。

怎么去呢?可以换一个结束符,读取一个字符,就去掉了,或者参考下面做法。

 

所以,一般不用它。

while(cin.get(buf, 1024))

{

             cin.get(); //去掉/n

             或者

             cin.ignore(跳过的字符数 = 1, 遇到字符退出 = EOF(-1)

}

 

l       getline(缓冲区指针,缓冲区大小,结束符 = ‘/n’) – istream成员函数

get的区别是,其会从流中把结束符去掉,同时,不把它放进缓冲区。

 

l       <string>中的全局getline(istream, string)

比上述getline好的地方在于,string的内存是可扩充的,不用担心缓冲区大小。

 

l       吸收空格

cin>>ws; //可用于吸收所有空格,ws是内置方法

 

5)          流状态分类

l       ios::badbit ios_base::badbit (以下类似) – bad()

致命性错误,流不能继续使用。

 

只有设置了badbitbad()才返回true

 

l       ios::eofbit – eof()

输入结束。

 

只有当输入结束时,eof()才返回true

 

l       ios::failbit – fail()

非法数据等IO失败,流可以继续使用,但是,在流恢复到正常状态前,流的所有操作会被忽略。

 

当输入结束eof()true或者设置了failbitbadbit fail()才返回true

 

l       ios::goodbit  - good()

一切正常。

 

仅当其他为true时,这个才能为true

 

l       设置标志 – setstate()

比如,setstate(ios::failbit)

l       清除错误标志 – clear()

-        clear()还原所有标志位

-        clear(ios::failbit | ios::badbit) 选择性的清除

 

6)          流错误处理

l       手动检查流状态 一般不用了

istream& operator >> (istream& is, Date& date)

{

    is >> date.year;

 

    char dash;

    is >> dash;

    if( dash != '-' )

    {

        is.setstate(ios::failbit);

    }

    //出错了以后就不会处理输入了。

    is >> date.month;

 

    is >> dash;

    if( dash != '-' )

    {

        is.setstate(ios::failbit);

    }

 

    is >> date.day;

 

    return is;

}

 

Date myday;

memset(&myday, 0,sizeof(myday));

cin >> myday;

cout<<endl<<myday.year<<" "<<myday.month<<" "<<myday.day<<endl;

 

cin.clear(); //流恢复

int age = 0;

cin >> age;

 

如果输入 1981 02 21

则输出是 1981 0 0,因为流出错了,会忽略所有其他流操作。

 

l       异常处理 推荐的处理方式

在任何状态标志设置了都可以抛出异常,一般只在错误状态设置了才抛出异常。

如,cin.exceptions(ios::badbit);

 

cin.exceptions(ios::failbit);

   try

   {

      Date myday;

      cout<<myday.year<<myday.month<<myday.day<<endl;

      memset(&myday, 0,sizeof(myday));

      cout<<myday.year<<myday.month<<myday.day<<endl;

      cin >> myday;

      cout<<endl<<myday.year<<" "<<myday.month<<" "<<myday.day<<endl;

   }

   catch(std::ios_base::failure e)

   {

      cout<<"输入错误"<<endl;

}

 

关于异常,请参考

http://blog.csdn.net/yeming81/archive/2010/06/16/5673070.aspx

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值