打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
第一部分 基础语言之七标准IO库
7.1 面向对象的标准库
IO 标准库类型和头文件
Header Type
iostreamistream 从流中读取
ostream 写到流中去iostream 对流进行读写;从 istream 和 ostream 派生而来
fstream ifstream 从文件中读取;由 istream 派生而来ofstream 写到文件中去;由 ostream 派生而来
fstream 读写文件;由 iostream 派生而来
sstream  istringstream 从 string 对象中读取;由 istream 派生而来ostringstream 写到 string 对象中去;由 ostream 派生而来
stringstream 对 string 对象进行读写;由 iostream 派生而来
标准IO类继承关系图和标准IO对象
国际字符支持
标准库还定义了一组相关的类型,支持 wchar_t 类型。每个类都加上“w”前缀,以此与 char 类型的版本区分开来。于是,wostream、wistream 和wiostream 类型从控制窗口读写 wchar_t 数据。相应的文件输入输出类是wifstream、wofstream 和 wfstream。而 wchar_t 版本的 string 输入/输出流则是 wistringstream、wostringstream 和 wstringstream。标准库还定义了从标准输入输出读写宽字符的对象。这些对象加上“w”前缀,以此与 char 类型版本区分:wchar_t 类型的标准输入对象是 wcin;标准输出是 wcout;而标准错误则是 wcerr。
每一个 IO 头文件都定义了 char 和 wchar_t 类型的类和标准输入/输出对象。基于流的 wchar_t 类型的类和对象在 iostream 中定义,宽字符文件流类型在 fstream 中定义,而宽字符 stringstream 则在 sstream 头文件中定义。
IO 对象不可复制或赋值
至于原因我们在后续内容中学习,现在因此产生两个重要含义,一、不能把流对象发在容器中,因为容器必须是可以复制的元素,第二形参和返回类型不能是流对象,也是因为形参需要复制,返回类型需要赋值,所以只能使用流对象引用或指针作为函数形参和返回类型,而且应该设置为非const,因为流对象的读写操作会改变流对象的状态。
7.2 条件状态
1.条件状态
badbit 标志着系统级的故障,如无法恢复的读写错误。如果出现了这类错误,则该流通常就不能再继续使用了。如果出现的是可恢复的错误,如在希望获得数值型数据时输入了字符,此时则设置 failbit 标志,这种导致设置 failbit的问题通常是可以修正的。eofbit 是在遇到文件结束符时设置的,此时同时还设置了 failbit。
流的状态由 bad、fail、eof 和 good 操作提示。如果 bad、fail 或者 eof中的任意一个为 true,则检查流本身将显示该流处于错误状态。类似地,如果这三个条件没有一个为 true,则 good 操作将返回 true。
clear 和 setstate 操作用于改变条件成员的状态。clear 操作将条件重设为有效状态。在流的使用出现了问题并做出补救后,如果我们希望把流重设为有效状态,则可以调用 clear 操作。使用 setstate 操作可打开某个指定的条件,用于表示某个问题的发生。除了添加的标记状态,setstate 将保留其他已存在、的状态变量不变。
2.流状态的查询和控制
可以如下管理输入操作
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
}
3. 条件状态的访问
// 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,cin.clear(falg)是设置,而setstate(flag)是添加
4.多种状态的处理
// sets both the badbit and the failbit
is.setstate(ifstream::badbit | ifstream::failbit);
7.3 输出缓冲区的管理
系统将字符串字面值存储在与流 os 关联的缓冲区中。下面几种情况将导致缓冲区的内容被刷新,即写入到真实的输出设备或者文件:
1. 程序正常结束。作为 main 返回工作的一部分,将清空所有输出缓冲区。
2. 在一些不确定的时候,缓冲区可能已经满了,在这种情况下,缓冲区将会在写下一个值
之前刷新。
3. 用操纵符(第 1.2.2 节)显式地刷新缓冲区,例如行结束符 endl。
4. 在每次输出操作执行完后,用 unitbuf 操作符设置流的内部状态,从而清空缓冲区。
5. 可将输出流与输入流关联(tie)起来。在这种情况下,在读输入流时将刷新其关联
的输出缓冲区。
1.输出缓冲区的刷新
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 thebuffer
2.unitbuf操作符
如果需要刷新所有输出,最好使用unitbuf操作符 。这个操纵符在每次执行完写操作后都刷新流:cout << unitbuf << "first" << " second" << nounitbuf;
等价于:
cout << "first" << flush << " second" << flush;
nounitbuf 操纵符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。
PS: 如果程序崩溃了,则不会刷新缓冲区
3.将输入和输出绑定在一起
当输入流与输出流绑在一起时,任何读输入流的尝试都将首先刷新其输出流关联的缓冲区。
交互式系统通常应确保它们的输入和输出流是绑在一起的。这样做意味着可以保证任何输出,包括给用户的提示,都在试图读之前输出。
tie 函数可用 istream 或 ostream 对象调用,使用一个指向 ostream 对象的指针形参。调用  tie 函数时,将实参流绑在调用该函数的对象上。如果一个流调用 tie 函数将其本身绑在传递给  tie 的 ostream 实参对象上,则该流上的任何 IO 操作都会刷新实参所关联的缓冲区。
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
一个 ostream 对象每次只能与一个 istream 对象绑在一起。如果在调用tie 函数时传递实参 0,则打破该流上已存在的捆绑。
7.4 文件的输入输出
fstream 头文件定义了三种支持文件 IO 的类型:
1. ifstream,由 istream 派生而来,提供读文件的功能。
2. ofstream,由 ostream 派生而来,提供写文件的功能。
3. fstream,由 iostream 派生而来,提供读写同一个文件的功能。
7.4.1. 文件流对象的使用
定义读写文件流,并绑定读写文件
// construct an ifstream and bind it to the file named ifile
ifstream infile(ifile.c_str());
// ofstream output file object to write file named ofile
ofstream outfile(ofile.c_str());  // C-style string;
定义读写文件,不绑定任何文件,使用open函数绑定文件
ifstream infile; // unbound input file stream
ofstream outfile; // unbound output file stream
infile.open("in"); // open file named "in" in the current directory
outfile.open("out"); // open file named "out" in the current directory
检查文件打开是否成功
打开文件后,通常要检验打开是否成功,这是一个好习惯:
// 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
清除文件流的状态
如果程序员需要重用文件流读写多个文件,必须在读另一个文件之前调用 clear 清除该流的状态。
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
}
8.4.2. 文件模式
在打开文件时,无论是调用 open 还是以文件名作为流初始化的一部分,都需指定文件模式(file mode)。每个 fstream 类都定义了一组表示不同模式的值,用于指定流打开的不同模式。与条件状态标志一样,文件模式也是整型常量,在打开指定文件时,可用位操作符设置一个或多个模式。文件流构造函数和 open 函数都提供了默认实参设置文件模式。默认值因流类型的不同而不同。
out、trunc 和 app 模式只能用于指定与 ofstream 或 fstream 对象关联的文件;in 模式只能用于指定与 ifstream 或 fstream 对象关联的文件。所有的文件都可以用 ate 或 binary 模式打开。ate 模式只在打开时有效:文件打开后将定位在文件尾。以 binary 模式打开的流则将文件以字节序列的形式处理,而不解释流中的字符。
默认时,与 ifstream 流对象关联的文件将以 in 模式打开,该模式允许文件做读的操作:与     ofstream 关联的文件则以 out 模式打开,使文件可写。以out 模式打开的文件会被清空:丢弃  该文件存储的所有数据。从效果来看,为 ofstream 对象指定 out 模式等效于同时指定了 out    和 trunc 模式。对于用 ofstream 打开的文件,要保存文件中存在的数据,唯一方法是显式 地指 定   app 模式打开。
对同一个文件作输入和输出运算
fstream 对象以 in 和 out 模式同时打开。当文件同时以 in和 out 打开时不清空。如果打开 fstream 所关联的文件时,只使用 out 模式,而不指定 in 模式,则文件会清空已存在的数据。如果打开文件时指定了 trunc模式,则无论是否同时指定了 in 模式,文件同样会被清空。下面的定义将copyOut 文件同时以输入和输出的模式打开:
// open for input and output
fstream inOut("copyOut", fstream::in | fstream::out);
模式是文件的属性而不是流的属性
ofstream outfile;
// output mode set to out, "scratchpad" truncated
outfile.open("scratchpad", ofstream::out);
outfile.close(); // close outfile so we can rebind it
// appends to file named "precious"
outfile.open("precious", ofstream::app);
outfile.close();
// output mode set by default, "out" truncated
outfile.open("out");
有效的文件读写模式
上述所有的打开模式组合还可以添加 ate 模式。对这些模式添加 ate 只会改变文件打开时的初始化定位,在第一次读或写之前,将文件定位于文件末尾处。
7.4.3 一个打开并检查输入文件的程序
// 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
}
7.5 字符串流
iostream 标准库支持内存中的输入/输出,只要将流与存储在程序内存中的string 对象捆绑起来即可。此时,可使用 iostream 输入和输出操作符读写这个 string 对象。标准库定义了三种类型的字符串流:
· istringstream,由 istream 派生而来,提供读 string 的功能。
· ostringstream,由 ostream 派生而来,提供写 string 的功能。
· stringstream,由 iostream 派生而来,提供读写 string 的功能。
要使用上述类,必须包含 sstream 头文件。
stringstream 对象的和使用
前面已经见过以每次一个单词或每次一行的方式处理输入的程序。第一种程序用 string 输入操作符,而第二种则使用 getline 函数。然而,有些程序需要同时使用这两种方式:有些处理基于每行实现,而其他处理则要操纵每行中每个单词。可用 stringstreams 对象实现:
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 提供的转换和/或格式化
stringstream 对象的一个常见用法是,需要在多种数据类型之间实现自动格式化时使用该类类型。例如,有一个数值型数据集合,要获取它们的 string 表示形式,或反之。sstream 输入和输出操作可自动地把算术类型转化为相应的string 表示形式,反过来也可以。
int val1 = 512, val2 = 1024;
ostringstream format_message;
// ok: converts values to a string representation
format_message << "val1: " << val1 << "\n"
<< "val2: " << val2 << "\n";
format_message 的内容是以下字符:val1: 512\nval2: 1024
相反,用 istringstream 读 string 对象,即可重新将数值型数据找回来。读取 istringstream 对象自动地将数值型数据的字符表示方式转换为相应的算术值。
// 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
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C++基础之IO类
C 文件和IO操作
C++文件操作:打开文件和写入文件
C++ 文件和流 | 菜鸟教程
C++ 文件和流如何从文件读取流和向文件写入流
C++输入输出文件流
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服