C++流与标准IO库

1. 流

数据在计算机设备和内存之间移动,其基本单位为字符,故将其形象地称为流。C++中把输入输出流定义为类,这里的输入、输出是针对内存而言的。流类的对象称为流对象。每个流对象在内存中有自己的缓冲区用于暂存数据。流对象不能复制或赋值,但可以将其引用或指向流对象的指针作为函数的参数或者返回值。

C++ primer(第四版)中主要讲了三类流:标准输入输出流、文件流和字符串流。顾名思义,与流的交互对象分别为标准设备、外设和字符串。

2.标准输入/输出流

头文件:iostream/istream/ostream。后两者是iostream的子类,分别对应标准输入流和标准输出流。iostream对象既可用于输入又可以用于输出。

2.1 标准输出流

常用流对象:cout、cerr和clog。其中cerr负责向标准输出(屏幕)输出错误信息(字符串形式)。与clog的区别的前者不会经过缓冲区而直接输出至屏幕。

缓冲区:暂存数据。内存中的数据首先存在输出缓存区中,然后再输出至标准输出(屏幕)。

以下情况下会刷新输出缓冲区:

a) 程序正常结束。若程序非正常退出且未作其它措施,则流缓冲区不会刷新。

b) 缓冲区已满。

c) 显式调用函数来刷新。可以通过endl、ends和flush操作符来显示刷新。endl会插入换行符,ends会插入一个空字符(NULL),flush不会添加任何字符。

d) unitbuf设置流状态:cout << unutbuf << ... << nounitbuf; 则...中的每一次输出都会刷新一次缓冲区,直到nounitbuf操作符取消强制每次刷新。

e) 输入流与输出流相关联(tie),读输入流时将会刷新输出缓冲区。cin.tie(&cout); ostream *pos = cin.tie(); cin.tie(0).表示了cin与cout之间的绑定与解绑定操作。一 个ostreram对象一次只能被一个istream对象所绑定。

输出对象:可以为C++内置对象,或者重定义了输出操作符的自定义对象。

输出格式控制:可以通过使用控制符(需要include<iomanip>)或者流对象的内置函数:

a) 数值进制:cout << hex << a << dec << b << oct << c << setbase(int) <<d; 或者 cout.setf(ios::hex)/cout.setf(ios::dec)/cout.setf(ios::oct);其中setbase(int)的参数 取值为8,10或16。若通过调用输出流对象的内置函数输出,则会带有前缀(0x/0)。设置进制之后的整数输出一直按此进制,直到显式改变进制(cout内置函数方 式需要调用cout.unsetf(...))。

b) 宽度设置:cout << setw(int) << obj; 或者cout.width(int);用于设置输出对象的最小宽度。

c) 默认填充: cout << setfill(char) << obj; 或者cout.fill(char); 用于不够指定宽度时空白字符的填充。

d) 小数输出格式:cout << setiosflags(ios::scientific) << a ; 或者cout.setf(ios::scientific);ios::scientific:科学计数法;ios::fixed:普通小数。

e) 小数精度: cout << setprecision(int) << a; 或者cout.precision(int)。科学计数法中参数表示小数点后有效数字位数,小数表示中参数表示总共的有效位数。

f) bool值输出字符串:cout << boolalpha << b;

注:b和c设置之后仅对下一次输入有效;cout.setf的参数可以为用“|”隔开的设置组合。例如进制和表示法、精度的组合。

其他方法:可以用put方法实现字符的输出:cout.put(ch) 或者 putchar(ch);其中前者需要include<stdio.h>。

2.2标准输入流

常用对象:cin。

缓冲区:同标准输出流,标准设备的输入线暂存于内存中的输入缓冲区,然后再输入值内存中的相应位置。

缓冲区的刷新:fflush(cin);

流成员函数:

a) cin.get() :在标准输入中读取一个字符并且返回该字符。

b) cin.get(ch) :在标准输入中读取一个字符并且赋值给ch。

c) cin.get(char *p, int n, char del); 用于在标准输入中读取n-1个字符至p指向的内存中。若前n-1个字符中出现了字符del,则停止读入。

d) getchar函数:主要作用是将cin后移一位,越过无用的字符(比如空格)。

字符串的输入:遇到空格、制表或换行时停止。或者可以调用getline()函数来实现整行的读取:cin.getline(str); 或者getline(cin, str);

其他成员:eof()表示文件尾; ignore(int n, char del) 表示忽略前n个字符或者del及其之前的m(m<n)个字符; cin.peek() 返回当前字符,但是流指向的位置不变;

2.3 流状态

状态常量:strm::badbit; strm::failbit; strm::eofbit;

常量类型:strm::iostate

状态函数:strm.bad(); strm.fail(); strm.eof(); strm.good(); 只有前三个均为false的时候strm.good()才是true。

状态设置:strm.clear(); 将状态设置为good()状态。

    strm.clear(flag); 将flag位设为true,其他位设为false。(可以同时设置多个状态,用“|”隔开)

    strm.setstate(flag);将flag设为true。(可以同时设置多个状态,用“|”隔开)

    strm.rdstate(); 读取状态。

说明:当遇到文件尾的时候,会为eof()或bad(),若输入错误,则会为fail()。

3.文件流

3.1 头文件:fstream; 流类型:fstream/ifstream/ofstream

3.2 使用:构造函数中传递函数名(C风格字符串)或者调用open函数(参数亦为C风格字符串)。检查文件是否打开成功,可以直接用if来判断。读取或者写入完毕后应当        close(),close()之后应该clear()以恢复流状态为正确状态。

3.3 文件模式:

in/out 通用: ate(定位至文件尾), binary(二进制读写方法)

in : in(读取)

out: out(写入),app(追加), trunc(清除其他文件流)

模式设置中同时包含in和out时表示既可以读又可以写,但是若再加上(“|”隔开)trunc,则等同于仅有out模式。

4. 字符串流

4.1 头文件 sstream. 类型:stringstream/istringstream/ostringstream

4.2 stringstream 的使用:

a) 构造函数:stringstream strm; stringstream strm(str);

b) 返回string对象: strm.str();

c) 改变string对象:strm.str(str);

4.3 类型转换:

步骤:由stringstream对象读入string对象,然后再输出为不同类型的对象赋值即可。类型必须对应:

stringstream strm;

string str("this a1 234 b 45");

string s1, s2, s3;

int i1, i2;

strm.str(str);

strm >> s1 >> s2 >> i1 >> s3 >> i2;如此才能实现一一对应。空格或者制表符或者换行符是必要的间隔。

5. 输入输出操作符:

>> 和 << 的箭头方向即表示了数据流的流动方向:

对于标准输入输出来说,cin >> a;  cout << b; 分别表示数据出输入缓冲区和进入输出缓冲区;

对于文件的输入输出:if  >> s; 和 of << s; 分别表示在文件中读数据(经文件输入缓冲区)到s和将s(经文件输出缓冲区)输入至文件。

对于stringstream:strm >> s; 和 strm << s 则分别表示为s赋值和读取s。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章