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时,空白符将会忽略。
转载于:https://www.cnblogs.com/itree/p/4818018.html