只记录常用的,为的就是少翻砖头书·········
IO类:
IO类顾名思义就是用来做IO的,包括普通流(iostream处理控制台IO)、文件流(fstream处理文件IO)、string流(sstream完成内存中string的IO)。平时用到的 cin 和 cout 分别是 istream 和 ostream 的一个对象。文件流和string流都是继承于普通流,所以适用于普通流的操作同样适用于文件流和string流。另外要注意的是,流对象不能被赋值和拷贝,所以我们会发现有关流的函数中其参数或者返回值都是对流的引用。
类与所在的头文件:
iostream istream、wistream 从流读取数据
ostream、wostream 向流写入数据
iostream、wiostream 读写流
fstream ifstream、wifstream 从文件读取数据
ofstream、wofstream 向文件读取数据
fstream、wfstream 读写文件
sstream istringstream、wistringstream 从string读取数据
ostringstream、wostringstream 向string写入数据
stringstream、wstringstream 读写string
上面有些类前面加了w,这是对应类的宽字符版本,照常使用就行了。
条件状态:
IO操作可能会发生错误,一些错误可以恢复,另一些错误是由于系统原因造成的,无法恢复。通常,读取到的数据的类型与期望读取的类型不一致时,流会进入错误状态,流遇到文件结束符时也会进入错误状态,还有其他未知的操作也可能导致流进入错误状态。一个流如果在读取某个数据时发生了错误,其上后续的IO操作都将会失败。所以,我们在使用一个流之前,或者在流读取一部分数据之后接着要继续读取数据之前,应该检查流是否处于正常状态。检查流是否正常的最简单做法就是把流当做一个条件来使用:
while( cin ) {.........} //或者
if( cin ) {.............}
花括号内代表流处于正常状态时要进行的操作。另外IO类还提供了许多状态位和函数来帮助我们查询流的状态:
strm::iostate //strm是一种上面列出的IO类型,iostate是一种机器相关的类型,提供了表达条件状态的完整功能
strm::badbit //用来指出流已崩溃
strm::failbit //用来指出一个IO操作失败了
strm::eofbit //用来指出流已到达了文件结束
strm::goodbit //用来指出流未处于错误状态,此值保证为零
s.eof() //若流 s 的eofbit置位,则返回true
s.fail() //若流 s 的 failbit 或 badbit 置位,则返回true
s.bad() //若流 s 的 badbit 置位,则返回true
s.good() //若流 s 处于有效状态,则返回true
s.clear() //将流 s 中所有条件状态位复位,将流的状态设置为有效,返回void
s.clear(flags) //根据给定的 flags 标志位,将流 s 中对应条件状态位复位。flags的类型为strm::iostate。返回void
s.setstate(flags) //根据给定的 flags 标志位,将流 s 中对应的条件状态位置位。flags的类型同上。返回void
s.rdstate() //返回流 s 的当前条件状态,返回值类型为 strm::iostate
记录《C++Primer第五版》中280页的话:badbit表示系统级错误,如不可恢复的读写。通常情况下,一但badbit被置位,流就无法再使用了。在发生可恢复错误后,failbit被置位,如期望读取数值却读取出一个字符等错误。这种问题是可以修正的,流还可以继续被使用。如果到达文件结束位置,eofbit和failbit都会被置位。goodbit的值为0,表示流为发生错误。如果badbit、failbit和eofbit任一个被置位,则检测流状态的条件会失败。
good()在所有错误位均未置位的情况下返回true,而bad()、fail()和eof()则在对应错误位被置位时返回true。在badbit被置位是,fail()也会返回true。使用good()和fail()是确定流的总体状态的正确方法。
格式化输入输出:
boolalpha //用输出true和false来代替布尔值1和0
no boolalpha //反上
oct //以八进制输出整数
dec //以十进制输出整数
hex //以十六进制输出整数
showbase //输出数制的前导符,如八进制是0,十六进制是0x
noshowbase //反上
uppercase //输出十六进制时涉及到的字母全部变大写
nouppercase //反上
cout.precision() //获取当前输出浮点数的精度
cout.precision(p) //设置浮点数输出的精度为p
文件输入输出:
前面适用于普通IO流的操作也适用于文件流,包括<<、>>、getline()等。除此之外还提供了以下操作,可以对fstream、ifstream、ofstream调用这些操作:
fstream fstrm; //创建一个未绑定的文件流。fstream是头文件fstream中定义的一个类型
fstream fstrm(s); //创建一个fstream,并打开名为 s 的文件。s 可以是string类型,或者是一个指向C风格字符串的指针。这些构造
//函数都是explicit的。默认的文件模式mode依赖于fstream的类型。
fstream fstrm(s,mode); //按指定的mode打开文件名为 s 的文件。
fstrm.open(s); //打开名为 s 的文件,并将文件与fstrm绑定。 s 可以是string类型,或者是指向C风格字符串的指针。
//默认的文件mode依赖于fstream的类型。返回void
fstrm.close(); //关闭与fstrm绑定的文件。返回void
fstrm.is_open(); //返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭。
fstrm.read(start,length); //从当前文件指针处开始读入length个字节的数据放到start所指的缓冲区
fstrm.write(start,length); //将start所指的缓冲区往后length个字节写入到文件中。
所以,要使用文件流打开文件有两种做法:
fstream file("filename"); //直接用文件名构造流对象
fstream file;
file.open("filename"); //先声明一个流对象,再用open来关联
文件流对象同样可以作为条件,用来判断文件打开是否成功以及文件流对象的状态是否有效。如果一个文件已经被打开但未关闭,当再次使用open()来打开另一个文件时,文件流对象将会进入错误状态,并且failbit被置位,导致之后的IO操作都失效。必须先调用close()来关闭文件才可以打开另一个文件。一个文件流对象在析构时会自动调用close()函数解除与文件的关联。
文件模式:
in //以读方式打开
out //以写方式打开
app //每次写操作前均定位到文件末尾
ate //打开文件后立即定位到文件末尾
trunc //截断文件
binary //以二进制方式进行IO
ifstream不能被指定out模式,ofstream不能被指定in模式。ofstream默认以out模式打开文件,并且隐含有trunc模式,即以写模式打开文件,文件内存会被截断,即被覆盖。若不想打开的文件被覆盖,可以以app模式构建ofstream对象来打开文件,这样数据只会写到文件末尾而不会覆盖文件。trunc模式不能与app同时使用。
文件随机访问:
tellg(); //返回一个输入流中标记的当前位置
tellp(); // 类上,改为输出
seekg(pos); //在一个输入流中将标记重定位到pos给定的绝对地址
seekp(pos); // 类上,改为输出
seekp(off,form); //在一个输出流中将标记定位到from之前或之后off个字符的位置,from可以是beg(文件开始)、cur(当前)、
//end(文件末尾)之一。
seekg(off,form); //类上,改为输入
巧用 seek(0,end) 与 tellg() 的组合可以很方便地得到文件的长度。
string流:
这个东西跟string有什么区别?string流可以向cin和cout那样用>>和<<来读写,而string却不能。string流对象内部也有一个string对象,只是增加了<<和>>而已。没什么好神秘的。使用与普通IO流的操作也适用于string流。
相关操作:
sstream strm; //strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型。
sstream strm(s); //strm是一个sstream对象,保存string s 的一个拷贝。次构造函数是explicit的。
strm.str(); //返回strm所保存的string的拷贝
strm.str(s); //将string s 拷贝到strm 中。返回void
顺便记记string。
string对象:
初始化string对象的方式:
string s1; //默认初始化,是s1是一个空串
string s2(s1); //s2是s1的副本
string s2 = s1; //同上
string s3("value"); //s3是字面值"value"的副本,除了字面值最后的那个空字符外
string s3 = "value"; //同上
string s4(n,'c'); //把s4初始化为由连续n个字符c组成的串
string的操作:
os<<s; //将s写到输出流os当中,并返回os
is>>s; //从is输入流中读取字符串赋给s,并返回 is。在执行读取操作时,string对象会自动忽略开头的空白,包括空格符、换行符、
//制表符等,并从第一个真正的字符开始读起,直到遇见下一处空白为止。
getline(is,s); //从 is 输入流中读取一行赋给s,返回 is。遇到空格不断流,可以读入空格,但一遇到换行符,读取结束。
//注意换行符虽然被读进来了,但没有保存到string中
s.empty(); //s为空串则返回true,否则返回false
s.size(); //返回s中字符的个数
s[n]; //返回s中第n个字符的引用,位置n从0算起
s1+s2; //返回s1和s2连接后的结果、string对象也能与字面值连接,但是两个字面值字符串不能直接用'+'连接
s1=s2; //用s2的副本代替s1中原来的字符
s1==s2; //如果s1和s2中所含的字符完全一样,则它们相等;string对象的相等性判断对字母的大小写敏感
s1 != s2;
<,<=,>,>= //利用字母在字典中的顺序进行比较,且对字母的大小写敏感
读取未知长度的流:
string word;
while( cin>>word ) //每次读入一个单词,并在循环体内输出。直到遇到文件结束符或非法输入就结束。
cout<< word << endl;
string line;
while( getline(cin, line) ) //与上面类似,换成一次读入一行
cout<< line << endl;
流对象之所以能作为条件,是因为编译在背后做了隐式类型转换,调用了流对象中的bool运算符重载函数,返回的bool值代表流对象是否正常。一般来说,非法输入、文件结束符等因素都会导致其返回false。