输入输出流
(1)
基类是ios_base,直接继承这个类的是basic_ios<charT>,另外两个派生类分别继承了 basic_ios<charT>
这两个类分别是 basic_istream<charT> 和 basic_ostream<charT>,然后 basic_iostream继承上面两个类
(2)
ios_base定义了所有流共有的内容,不依赖于流所处理的字符类型。其他类都是以字符类型为参数的模板,比如istream:
typedef basic_istream<char> istream
basic_istream定义了一般的输入函数,
basic_ostream定义了一般的输出函数
在平常的使用中我们经常会用到插入符号<<和提取符号>>,类中定义了各种 operator<<()函数,以识别不同的类型,有了以上的知识,我们就可以定义自己的
输入输出流了。
(3).重载流的输入输出,需要两个参数,一个是非const的输入/出流,一个是自定义类,返回值为流的引用。比如:
ostream& operator<<(ostream& out, Data d);
(4)流的失败标志位:
设置标志位的函数是setstate,一旦设置,在标志位恢复之前一切的流操作都会被忽略
主要有四种标志:
a):badbit --机器上发生了致命性的错误
b):eofbit--输入结束了
c):failbitIO操作失败,主要原因是非法数据
d):goodbit--IO流正常
可以调用对应的IO流标志位函数来看结果。比如good()函数,如果标志位goodbit正常,则返回true,eofbit正常,则eof()返回true
一旦流状态中的任何一个标志位被设置,则它会一直保持下去,如果想要修改,则需要手动设置
使用clear()函数,则可以清空标志位,默认设置goodbit
可以选择设置需要清空的标志位,比如设置eofbit和badbit标志位 clear(eofbit | badbit)
(5).文件输入输出流
文件输入流: ios_ifsream<charT> 继承自 ios_istream<charT>
文件输出流: ios_ofstream<charT> 继承自 ios_ofstream<charT>
文件输入输出流 ios_iofstream<charT> 继承自 ios_ifstream<charT>
(5)流缓冲
streambuf类,可以通过这个类对输入和输出流进行通信,我们可以通过直接访问这个类,来对读取的数据进行格式化,
也就是我们可以通过这个指针,得到读取或者输入到流中的全部数据。也许每次读取数据,数据都被读取到了缓冲区。
每个流对象都包含一个指向这个类的指针。可以通过rdbuf()方法来访问
(6)在输入输出流中进行定位
streampos可以用来进行定位。
也可以采用C语言类似的方法来定位
a) istream 的定位方法是 tellg(), 移动流指针的方法是 seekg()
b)ostream的定位方法是tellp(), 移动方法是seekp()
(7)字符串输入输出流
字符串输入输出流对象模仿文件流对象,分别是istringstream, ostringstream 对象,
所有字符串流类的声名都在sstream里面
继承方式和文件流类似
base_ios<charT>
|
-------------------------------
||
basic_istream<charT> basic_ostream<charT>
|||
|basic_iostream<charT>|
|||
|||
basic_istringstream<charT>|basic_ostringstream<charT>
|
basic_iostringstream<charT>
使用流操作读取字符串,或者用字符串流给对象赋值,会十分的便利
使用字符串流操作的方式和文件流其实基本一样
比如创建一个istringstream对象 ,对它进行操作
istringstream in("123abc456");
int a = 0, b = 0;
string str;
in >> a >> str >> b;
则会得到 a = 123 str = abc456 b =0;
它会检查字符串类型和空格来给对象赋值
对于字符串的输出流操作,可以对各种类型的数据进行转化,使之成为string类,然后获取string对象。
ostringstream out;
double p = 3,14;
out << p;//浮点型转为位string
string str = out.str();//得到string
cout << str;
(8).格式化
1.格式化标志
输出的时候,需要对输出的数据格式化,比如宽度,精度,填充的字符等等
我们可以通过各种函数来设置
也可以通过格式化标志符来设置。
获取当前设置的格式化标志函数是flags()
用于改变格式化标志的函数如下,这些函数会返回原本的格式:
fmtflags flags(fmtflags newflags) 这个函数可以把格式设置为新的格式,可以使用或取多个标志位,但是这个函数一般用不上
fmtflags setf(fmtflags ored_flags) 设置指定的标志
fmtflags unsetf(fmtflags clear_flag) 关闭指定的标志
fmtflags setf(fmtflags bits, fmtflags fields); 关闭fields的设置,启用bits的设置
开关标志说明:
ios::skipws 跳过空格,这是输入流的默认格式
ios::showbase 打印整数的时候,指出数字的基数
ios::showpoint 显示小数点,但是不会输出末尾的零
ios::uppercase 16位的时候显示大写字母,科学计数法显示E
ios::showpos 正数前显示+
ios::unitbuf 每次插入数据后,刷新单元缓冲区 类似于C语言fflush
2.格式化域
每一种标志都有自己的类别,比如ios::basefields有ios::hex(16进制), ios::dec(十进制), ios::oct(八进制)
ios::floatfileds 有 ios::scientific(科学计数法) ios::fixed(以固定格式显示浮点数,精度是指小数点后面的位数
iosadjustfield 有 ios::left(左对齐) ios::right(右对齐), ios::internal(数值放在符号之后对其)
3.宽度,填充, 精度设置
int ios::width() 返回当前的宽度
int ios::width(int n) 设置宽度,返回先前的宽度
int ios::fill() 返回之前的填充字符
int ios::fill(int n) 设定填充字符,并且返回先前的填充字符
int ios::precision() 返回当前的精度,默认情况下是6位
int ios::precision(int n) 设定浮点书的精度,返回先前的精度
width(int n)每次设定之后,都会被重写设置为原本的默认值
(9).操纵算子
前面介绍的都是调用相关函数,也有不用调用函数,直接插入到流中,改变流的输出状态。
操作算子有带参数,也有不带参数,实际上是与函数名同样的
不带参数的有
showbase 显示基数
noshowbase
showpos 显示正负号
noshowpos
uppercase 输出16进制使用大写字母A~F 科学计数法显示大写E
nouppercase
showpoint 显示小数点后面的位数,包含0
noshowpoint
skipws 跳过输入中的空格
noskipws
left
right
internal
fixed
带有参数的操作算子如下
setiosflag(fmtflags n) ;设置之后会一直起作用,直到下次修改
resetiosflag(fmtflags n);清除n代表的格式化标志,一直有效,直到下次修改
setbase(base n) n 取10, 8 ,16代表各种进制
setfill(char n) 设置填充字符n
setprecision(int n) 设置精度n
setw(int n) 设置宽度为n
操作算子也可以对输入字符串进行操作
(10).创捷操作算子
编译器会寻找和算子函数同名的函数,然后调用它,比如endl的实现
ostream& endl(ostream& out)
{
return out << '\n';
}
(11).效用算子
创建一个操作算子很简单,但是创建一个带参数的操作算子很难。我们一般使用效用算子实现带参数的操作算子
使用方法是创建一个类,这个实际上没什么好说的
比如输出一个数字的二进制