[c++primer][08]标准IO库

C++的输入/输出由标准库提供,支持对文件、控制窗口和string对象的读写。

8.1 面向对象的程序库

IO类型在三个独立的头文件中定义,iostream定义读写控制窗口的类型,fstream定义读写已命名文件的类型,sstream所定义的类型用于读写存储在内存中string对象。

 

如果函数有基类类型的引用形参时,可以给函数传递其派生类型的对象。即对istream&进行操作的函数,也可以使用ifstream或者istringstream对象来调用。

标准库定义了一组相关类型,支持wchar_t类型,每个类都加上“w”前缀,与char类型的版本区分。如wiostream、wfstream、wstringstream等。

IO对象不可复制或赋值

1)流对象不能复制,故不能存储在vector等容器中;

2)形参或返回类型不能为流类型。如要传递或返回IO对象,必须指定为该对象的指针或引用。

8.2 条件状态

条件状态

badbit标志着系统级的故障,无法恢复;failbit是IO错误,通常可以修正;eofbit是在遇到文件结束符时设置的,此时同时设置了failbit

bad、fail、eof中任意一个为true,则流处于错误状态;若三者都不为true,则good操作返回true。

clear操作将条件重设为有效状态。

setstate操作打开某个指定的条件,表示某个问题发生。

流状态的查询和控制

int ival;
// read cin and test only for EOF; loop is executed even if there are other IO failures
while (cin >> ival, !cin.eof()) {
    if (cin.bad()) // input stream is corrupted; bail out
        throw runtime_error("IO stream corrupted");
    if (cin.fail()) { // bad input
        cerr<< "bad data, try again"; // warn the user
        cin.clear(istream::failbit); // reset the stream
        continue; // get next input
    }
// ok to process ival
}    

条件状态的访问

rdstate成员函数返回一个iostate类型的值,表示流当前的整个条件状态。

// remember current state of cin
istream::iostate old_state = cin.rdstate();
cin.clear();
process_input(); // use cin
cin.clear(old_state); // now reset cin to old state

多种状态的处理

使用按位或在一次调用中生成“传递两个或更多状态位”的值

// sets both the badbit and the failbit
is.setstate(ifstream::badbit | ifstream::failbit);

生成一个值,对应于badbit和failbit的位都打开了,将这两个位都设置为1,该值的其他位都为0

8.3 输出缓冲区的管理

每个IO对象都管理一个缓冲区,用于存储程序读写的数据。下面几种情况会导致缓冲区的内容被刷新

1)程序正常结束

2)在一些不确定的时候,缓冲区已满,写入新数据前被刷新

3)用操纵符显式地刷新缓冲区

cout << "hi!" << flush; // flushes the buffer; adds no data
cout << "hi!" << ends; // inserts a null, then flushes the buffer
cout << "hi!" << endl; // inserts a newline, then flushes the buffer

4)每次操作执行完后,用unitbuf操纵符设置流的内部状态,从而清空缓冲区

cout << unitbuf << "first" << " second" << nounitbuf;
//is equivalent to writing
cout << "first" << flush << " second" << flush;

unitbuf在每次执行完写操作后都刷新流,nonunitbuf操作符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。

5)将输出流与输入流关联,在读输入流时将刷新其关联的输出缓冲区

标准库默认将cout与cin绑定在一起

tie函数可用istream或ostream调用,使用一个指向ostream对象的指针形参。如果在调用tie函数时传递实参0,则打破该流上已存在的捆绑。

cin.tie(&cout); // illustration only: the library ties cin and cout for us
ostream *old_tie = cin.tie();
cin.tie(0); // break tie to cout, cout no longer flushed when cin is read
cin.tie(&cerr); // ties cin and cerr, not necessarily a good idea!
// ...
cin.tie(0); // break tie between cin and cerr
cin.tie(old_tie); // restablish normal tie between cin and cout

8.4 文件的输入和输出

fstream除了继承下来的行为外,还定义了两个自己的新操作,open,close

流对象的两种初始化形式

// construct an ifstream and bind it to the file named ifile
ifstream infile(ifile.c_str());

ifstream infile; // unbound input file stream
infile.open("in"); // open file named "in" in the current directory

由于历史原因,IO标准库使用C风格字符串而不是C++ string类型的字符串作为文件名。

检查文件打开是否成功

// check that the open succeeded
if (!infile) {
    cerr << "error: unable to open input file: "
        << ifile << endl;
    return -1;
}

将文件流与新文件重新捆绑(文件流改变关联文件时,需先关闭当前的文件流)

ifstream infile("in"); // opens file named "in" for reading
infile.close(); // closes "in"
infile.open("next"); // opens file named "next" for reading

清除文件流的状态

重用已存在的流对象,while循环必须在每次循环时记得关闭和清空文件流,因成功打开文件并读取直到文件结束或出现其他错误为止,流对象处于错误状态,任何读取流对象的尝试都会失败。

ifstream input;
vector<string>::const_iterator it = files.begin();
// for each file in the vector
while (it != files.end()) {
    input.open(it->c_str()); // open the file
    // if the file is ok, read and "process" the input
    if (!input)
        break; // error: bail out!
    while(input >> s) // do the work on this file
        process(s);
    input.close(); // close file when we're done with it
    input.clear(); // reset state to ok
    ++it; // increment iterator to get next file
}    

文件模式

in 读打开,ifstream默认方式

out 写打开,ofstream默认方式,文件会被清空

app  末尾写打开

ate 打开定位到末尾

trunc 清空打开

binary 二进制形式打开

一个打开并检查输入文件的程序

// opens in binding it to the given file
ifstream& open_file(ifstream &in, const string &file)
{
    in.close(); // close in case it was already open
    in.clear(); // clear any existing errors
    // if the open fails, the stream will be in an invalid state
    in.open(file.c_str()); // open the file we were given
    return in; // condition state is good if open succeeded
}

8.5 字符串流

stringstream对象的使用

string line, word; // will hold a line and word from input, respectively
while (getline(cin, line)) { // read a line from the input into line
    // do per-line processing
    istringstream stream(line); // bind to stream to the line we read
    while (stream >> word){ // read a word from line
        // do per-word processing
    }
}

stringstream提供的转换

int val1 = 512, val2 = 1024;
ostringstream format_message;
// ok: converts values to a string representation
format_message << "val1: " << val1 << "\n"
                          << "val2: " << val2 << "\n";

 

// str member obtains the string associated with a stringstream
istringstream input_istring(format_message.str());
string dump; // place to dump the labels from the formatted message
// extracts the stored ascii values, converting back to arithmetic types
input_istring >> dump >> val1 >> dump >> val2;
cout << val1 << " " << val2 << endl; // prints 512 1024  

使用输入操作符读string时,空白符将会忽略。

posted @ 2015-09-17 23:58  treeland  阅读(180)  评论(0编辑  收藏  举报