8.1 IO类
1.
标准库定义了一族类型,支持对文件和控制窗口等设备的读写,还使得string对象能够像文件一样操作。采用继承来实现。
流:是以字节方式对数据从源到目标进行传递的一种描述。
输入流:指从输入设备到内存中字节的传递;
输出流:指从内存到输出设备中字节的传递;
iostream类库的接口对应的头文件:
头文件iostream包含所有i/o流所需的基本信息,并定义有四个标准i/o流对象:
cin:标准输入流对象(与标准输入设备连接)
cout :标准输出流(与标准输出设备连接)
cerr :非缓冲的标准错误流(默认设备为显示器)
clog :经缓冲的标准错误流(默认设备为打印机)
istream(输入流)类型,提供输入操作
ostream(输出流)类型,提供输出操作
cin,一个istream对象,从标准输入读取数据
cout,一个ostream对象,向标准输出写入数据
cerr,一个ostream对象,通常用于输出程序错误信息,写入到标准错误
>>运算符,用来从一个istream对象读取输入数据
<<运算符,用来向一个ostream对象写入输出数据
getline函数,从一个给定的istream读取一行数据,存入一个给定的string对象中
2.
IO 类型在三个独立的头文件中定义:
iostream 定义读写控制窗口的类型,
fstream 定义读写已命名文件的类型,
sstream 所定义的类型则用于读写存储在内存中的 string 对象。
在 fstream 和 sstream 里定义的每种类型都是从iostream 头文件中定义的相关类型派生而来。
以上类型前缀+’w’表示wchar_t版本 ,类似地,我们有wcin
,wcout
,wcerr
准库类型不允许做复制或者赋值操作。这个要求说明:
首先,在流对象不能在容器类型(如vector)中储存,因为容器类型中只能储存支持复制的元素类型。
其次,形参或者返回类型不能为流类型。如果非要传递或者返回IO对象,那么必须传递或返回指向该对象的指针或者引用。
IO对象无法进行拷贝,赋值,且读写IO对象会改变状态,因此IO对象不能设置为形式参数,返回类型,不能用const
3.IO库类型和头文件
4.IO库条件状态
IO标准库管理一系列的条件状态,用来标记给定的IO对象是否处于可用状态。
流必须处于无错误状态,才可以用于输入或者输出。检查流是否可用的最简单方法是检查它的真值:
<span style="font-size:18px;">if(cin)
while(cin>>word)</span>
IO库条件状态:
strm::iostate // 机器相关的整型名,由各个iostream类定义,用于定义条件状态
strm::badbit // strm::iostate类型的值,用于指出被破坏的流
strm::failbit // strm::iostate类型的值,用于指出失败的IO操作
strm::eofbit // strm::iostate类型的值,用于指出流已经到达文件结束符
s.eof() // 如果设置了流s的eofbit值,则该函数返回true
s.fail() // 如果设置了流s的failbit值,则该函数返回true
s.bad() // 如果设置了流s的badbit值,则该函数返回true
s.good() // 如果流s处于有效状态,则该函数返回true
s.clear() // 将流s中的所有状态值都重设为有效状态
s.clear(flag) // 将流s中的某个指定条件状态设置为有效。flag的类型是strm::iostate
s.setstate(flag) // 给流s添加指定条件。flag的类型是strm::iostate
s.rdstate() // 返回流s的当前条件,返回值类型为strm::iostate
5.流状态的查询和控制:
<span style="font-size:14px;">int ival;
while(cin>>ival,!cin.eof())//逗号操作符,首先计算它的每一个操作数,然后返回最右边的操作数作为整个操作的结果。
{
if(cin.bad())
/*do something*/
if(cin.fail())
{
cerr<<”bad data”;
cin.clear(istrea::failbit);
continue;
}
}</span>
6.每个IO对象管理一个缓冲区,用于存储程序读写的数据。
os<<”please”;
系统将字符串字面值存储在与流os相关的缓冲区中。下面几种情况将导致缓冲区的内容被刷新,即写入到真实的输出设备或者文件。
导致缓冲刷新的原因有很多:
1. 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
2. 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
3.我们可以使用操纵符如endl来显式刷新缓冲区。
4. 在每次输出操作完后,我们可以用操作符unitbuf设置流的内部状态,从而清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
5. 一个输出流可能被关联到另一个流。在这种情况下,当肚泻被关联的流时,关联到的流的缓冲区会被刷新。
7.刷新输出缓冲区
endl 操纵符,用于输出一个换行符并刷新缓冲区。
flush操纵符,用于刷新流,但不在输出中添加任何字符。
ends操作符,这个操纵符在缓冲区中插入空字符 null,然后刷新它。
8.unitbuf操纵符,这个操纵符在每次执行完写操作后都刷新流。
nounitbuf操纵符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。
8.2 文件输入输出
1.程序如果要读写控制窗口,那么采用标准库定义的对象cin,cout,cerr。
程序如果要读写文件,需要自行定义对象,然后将它们绑定到问价上。
注意小心,如果需要重用文件流读写多个文件,那么必须在读另一个文件之前调用clear()清除该流的状态,然后再close()。否则,可能上个对象的错误状态仍然残留在新的对象那个那里。
1.C++ 通过以下几个类支持文件的输入输出:
ofstream: 写操作(输出)的文件类 (由ostream引申而来)
ifstream: 读操作(输入)的文件类(由istream引申而来)
fstream: 可同时读写操作的文件类 (由iostream引申而来)
2.文件模式
in 打开文件做读操作
out 打开文件做写操作
app 在每次写之前找到文件尾
ate 打开文件后立即将文件定位在文件尾
trunc 打开文件时清空已存在的文件流
binary 以二进制模式进行 IO 操作
阻止一个ofstream清空给定文件内容的方法是同时指定app模式: ofstream::app
8.3 string流
1.标准库定义了三种类型的字符串流:
istringstream,由 istream 派生而来,提供读 string 的功能。
ostringstream,由 ostream 派生而来,提供写 string 的功能。
stringstream,由 iostream 派生而来,提供读写 string 的功能。
<span style="font-size:14px;">while(getline(cin,line))
{
istringstream stream(line);
<span style="white-space:pre"> </span> while(stream>>word)
{...}
}</span>
2.文件流概述
使用:文件流对象>>变量1>>变量2>>…;完成读操作;
使用:文件流对象<<表达式1>>表达式2>>…;完成写操作;
<span style="font-size:14px;"> #include <fstream> //包含文件流类头文件
int main()
{
ofstream out; //定义输出流对象
out.open(“AAA”); //打开文件
if(!out) //文件打开失败,out值为假
{
cout << "Cannot open AAA file./n";
return 1;
}
out << "C++ " << 89.5 << endl;
out << "English " << 93.5 << endl;
out << "Maths " << 87 << endl;
out.close(); //关闭文件
}</span>
3.stringstream 特定的操作
sstream strm; strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型
sstream strm(s); strm是一个sstream对象,保存string s的一个拷贝。此构造函数是explict的。
strm.str() 返回strm所保存的string的拷贝
strm.str(s) 将string s拷贝到strm中。返回void