天天看点

S08IO库S08IO库

S08IO库

一、IO类

1、IO库类型和头文件

iostream    //istream/ostream/iostream,读写流,若前缀w如wistream表示对宽字符的支持
fstream     //ifstream/ofstream/fstream,读写文件,若前缀w表示对宽字符的支持
sstream     //istringstream/ostringstream,读写string,若前缀w表示对宽字符的支持
           

(1)由于fstream和sstream定义的文件流类型和string流类型都是继承自iostream定义的流类型,因此可以像使用cin/cout等对象一样来使用文件和string流类型的对象(例如函数形参是ostream&,实参可以是ofstream)

(2)IO对象没有拷贝或赋值

(3)基本操作

ofstream out1, out2;
out1 = out2;                   //错误,不能赋值流对象
ofstream print(ofstream);      //错误,不能初始化ofstream参数
out2 = print(out2);            //错误,不能拷贝流对象
           

2、进行IO操作的函数通常以引用的形式传递和返回流,并且不能是const的

3、IO库的条件状态

strm::iostate   //strm是一种IO类型,具体参考1中的内容,iostate提供了表达条件状态的完整功能
strm::badbit    //badbit置1表示流已崩溃,系统级错误,无法恢复,该流无法再使用,检测流状态的条件会失败
strm::failbit   //failbit置1表示一个IO操作失败,可恢复,检测流状态的条件会失败
strm::eofbit    //eofbit置1表示流到达了文件结束,检测流状态的条件会失败
strm::goodbit   //goodbit置0表示流未发生错误,只有在goodbit置0时流对象作为条件判断才会为真
s.eof()         //若eofbit置1,则返回true
s.fail()        //若failbit或badbit置1,则返回true
s.bad()         //若badbit置1,则返回true
s.good()        //若流有效,则返回true
s.clear(flags)  //flags参数可选,类型是strm::iostate,若有则所有状态位置成flags,若无则复位,返回void
s.setstate(flags)   //将flags提供的位设置为flags,与clear不同
                    //clear对每个状态都复位或设置,setstate相当于clear(原状态 | 新状态),返回void
s.rdstate()     //返回流的当前条件状态,返回类型为strm::iostate

clear(rdstate() | state) = setstate(state)  //clear()与setstate()的关系
           

4、一旦流出现错误后,后续IO操作都会失败,只有当流不处于错误状态时才能进行正常操作,故使用一个流之前应该检查它的状态

while(cin >> word) {...}         //流状态正常时作为条件会返回为真,故可以正常操作
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);    //将fallbit和badbit复位,保持eofbit不变
           

5、管理输出缓冲,导致缓冲区立即刷新的原因

(1)程序正常结束,main函数return时刷新缓冲区

(2)缓冲区满

(3)

cout << endl

来显式刷新缓冲区并输出换行,

cout << ends

显式刷新缓冲区并输出空格,

cout << flush

显式刷新缓冲区并不附加任何字符

(4)

cout << unitbuf

设置所有输出都立即刷新,无缓冲;

cout << nounitbuf

取消立即刷新

(5)当一个输出流被关联到另一个流时,读写被关联的流时,关联流的缓冲区被刷新

注意:如果程序崩溃,输出缓冲区不会被刷新,可能在缓冲区中会存有已经被程序执行完毕但还未输出的数据

6、tie函数关联输入和输出流,此时参考5(5),缓冲区将会刷新

ostream* tie() const;          //返回指向绑定的输出流的指针,若未绑定返回空指针
ostream* tie(ostream* tiestr); //将tiestr指向的输出流绑定的该对象上,并返回上一个绑定的输出流指针

cin.tie(&cout);                        //将cin关联到cout
ostream *old_tie = cin.tie(nullptr);   //cin不再与其他流关联,并使old_tie指向cin上一个绑定的输出流
cin.tie(&cerr);                        //将cin再关联到cerr上,此时读取cin会刷新cerr
           

二、文件输入输出

1、fstream特有的操作

fstream fstrm;            //创建未绑定的文件流fstrm,fstream是头文件fstream中定义的类型
fstream fstrm(s, mode);   //创建一个fstream并打开名为s的文件,s可以是string或C风格的字符串,可选打开模式mode
fstrm.open(s);            //打开名为s的文件并与fstrm绑定,返回void
fstrm.close();            //关闭fstrm绑定的文件,返回会void
fstrm.is_open();          //判断fstrm绑定的文件是否成功打开且尚未关闭,返回bool
           

注意:继承机制保证在要求使用基类型对象的地方(如要求是istream&),可以用继承类型的对象替代(传入ifstream)

2、成员函数

open

close

当定义空文件流对象时可以用

open

将它与特定文件关联起来,若在定义时提供了文件名则会自动调用

open

,若

open

调用失败则会将流的

failbit

置1,若要关联另一个文件则首先要调用

close

关闭当前关联的文件,不

close

直接

open

新文件会出错

注意:当一个fstream对象被销毁时,close会被自动调用

3、文件模式,部分限制情况参考《C++primer 5th》p.286

in      //读
out     //写
app     //附加,即写操作前先定位到文件末尾
ate     //打开文件立即定位到文件末尾
trunc   //截断文件,即清空原有内容
binary  //二进制方式IO

ofstream out("file1");                                    //默认写、截断
ofstream out2("file1", ofstream::out);                    //默认截断
ofstream out3("file1", ofstream::out | ofstream::trunc);  //写,截断,与前两者等价
           

三、string流

1、sstream特有的操作

sstream strm;             //创建未绑定的stringstream对象strm,sstream是头文件sstream中定义的类型
sstream strm(s);          //创建一个sstream并保存string s的拷贝
strm.str();               //返回strm保存的s的拷贝
strm.str(s);              //将string s保存到strm中,返回void

ostringstream msg;
msg << "C++ Primer the fifth edition" << endl;    
istringstream in(msg.str());
           

四、其他

1、一些课本上的习题或一些参考代码

练习:
//略去头文件等一些细节
istream &func(istream &is) 
{
    int s1;
    while (is >> s1, !is.eof())
    {
        if (is.bad())
        {
            throw runtime_error("IOStream Error");
        }
        else if (is.fail())
        {
            cerr << "Failed, please try again" << endl;
            is.clear();
            is.ignore(buffer, '\n');   //buffer = 100
            continue;
        }
        cout << s1 << endl;
    }
    return is;
}

int main()
{
    func(cin);
    return ;
}

练习:
//略去头文件等一些细节
int main(int argc, char *argv[])
{
    ifstream file;
    vector<string> lines;
    string line;
    if (argc != )
    {
        cerr << "Wrong argument(s)" << endl;
    }
    file.open(argv[]);
    if (!file)
    {
        cerr << "Can't open file " << argv[] << endl;
    }
    while (getline(file, line))
    {
        lines.push_back(line);
    }
    file.close();
    auto beg = lines.begin(), end = lines.end();
    while (beg != end)
    {
        istringstream words(*beg);
        string word;
        while (words >> word)
        {
            cout << word << " ";
        }
        cout << endl;
        ++beg;
    }

    return ;
}
           

2、iostream类型的设计与scanf/printf的设计有诸多不同,可以参考陈硕的《C++ 工程实践(7):iostream 的用途与局限》来进一步了解iostream

继续阅读