c++primer plus第十七章-输入和输出概述
1)通过使用缓冲区可以更高效地处理输入和输出。缓冲区是用作中介的内存块,它是将信息从设备输到程序或从程序输给设备的临时存储工具。通常,像磁盘驱动器这样的设备以512字节(或更多)的块为单位来传输信息,而程序通常每次只能处理一个字节的信息。缓冲区帮助匹配这两种不同的信息传输速率。
因为从内存中读取单个字节的速度比从硬盘上读取快很多,所以这种方法更快。
2)输出时,程序首先填满缓冲区,然后把整块数据传输给硬盘,并清空缓冲区,以备下一批输出使用。这被称为刷新缓冲区。
键盘输入每次提供一个字符,因此在这种情况下,程序无需缓冲区来帮助匹配不同的数据传输速率。然而,对键盘输入进行缓冲可以让用户在将输入传输给程序之前返回并更正。c++程序通常在用户按下回车键时刷新输入缓冲区。
3)管理流和缓冲区的工作有点复杂,但iostream文件中包含一些专门设计用来实现、管理流和缓冲区的类。
第一:streambuf类为缓冲区提供了内存,并提供了用于填充缓冲区、访问缓冲区内容、刷新缓冲区和管理缓冲区内存的类方法;
第二:ios_base类表示流的一般特征,如是否可读取、是二进制还是文本流等;
第三:ios类基于ios_base,其中包括了一个指向streambuf对象的指针成员;
第四:ostream类是从ios类派生而来的,提供了输出方法;
第五:istream类也是从ios类派生出来的,提供了输入方法;
第六:iostream类是基于istream和ostream类的,因此继承了输入方法和输出方法。
4)c++的iostream类库管理了很多细节。
第一:cin对象对应于标准输入流。在默认情况下,这个流被关联到标准输入设备(通常为键盘)。wcin对象与此类似,但处理的是wchar_t类型。
第二:cout对象与标准输出流相对应。在默认情况下,这个流关联到标准输出设备(通常为显示器)。wcout对象与此类似,但处理的是wchar_t类型。
第三:cerr对象与标准错误流相对应,可用于显示错误信息。在默认情况下,这个流被关联到标准输出设备(显示器)。这个流没有被缓冲,这意味着信息将被直接发送到屏幕,而不会等到缓冲区填满或新的换行符。
第四:clog对象也对应于标准错误流。在默认情况下,这个流关联到标准输出设备(显示器)。这个流被缓冲。
第五:对象代表流。?
5)重载的<<运算符
<<默认为按位左移运算符,但ostream类重载为输出。使之能够识别c++所有的基本类型:
unsigned char; long;
signed char; unsigned long;
char; long long(c++)
short; unsigned long long(c++)
unsigned short; float;
int; double;
unsigned int; long double;
6)函数原型:ostream &operator<<(int);
cout<<88;
该原型表明,operator()函数接受一个int参数,这与上述语句的88匹配。该原型还表明,函数返回一个指向ostream对象的引用,这使得可以将输出连接起来。
cout<<"i am feeling sedimental over"<<boundary<<"\n";
7)ostream类还为下面的指针类型定义了插入运算符函数:
const signed char*;
const unsigned char*;
const char*;
void*;
c++用指向字符串存储位置的指针来表示字符串。指针的形式可以是char数组名、显式的char指针或用引号括起的字符串。
char name[20]="dudly diddlemore";
char *pn="violet dmore";
cout<<"hello!";
cout<<name;
cout<<pn;
方法使用字符串中的终止空字符来确定何时停止显示字符。对于其他类型的指针,c++将其对应于void*,并打印地址的数值表示。如果要获得字符串的地址,则必须将其强制转换为其他类型。
char *amount="dozen";
cout<<(void*) amount; //prints the address of the "dozen" string
8)put()方法和write()方法
put()用于显示字符,write()用于显示字符串。
ostream &put(char);
和<<运算符函数一样,该函数也返回一个指向调用对象的引用,因此也可以用它将拼接输出:
cout.put('I').put('am');
write()方法是显示整个字符串。
basic_ostream<char T,traits> &write(const char_type* s,streamsize n);
第一个参数提供了要显示的字符串的地址,第二个参数指出了要显示多少个字符。
const char *state ="kanroe";
cout.write(state,4);
9)刷新输出缓冲区
由于ostream类对cout对象处理的输出进行缓冲,所以输出不会立即发送到目标地址,而是被存储在缓冲区中,直到缓冲区填满。然后,程序将刷新缓冲区,把内容发送出去,并清空缓冲区,以存储新的数据。通常,缓冲区为512字节或其整数倍。当标准输出连接的是硬盘上的文件时,缓冲可以节省大量的时间。毕竟,不希望程序为发送512个字节,而存取磁盘512次。将512个字节收集到缓冲区中,然后一次性将它们写入硬盘的效率要高得多。
如果实现不能在所希望时刷新输出,可以使用两个控制符中的一个来强行进行刷新。控制符flush刷新缓冲区,而控制符endl刷新缓冲区,并插入一个换行符。这两个控制符的使用方式与变量名相同。
cout<<"hello,i am a boy"<<flush;
cout<<"hey, who are you"<<endl;
实际上,控制符也是函数,也可以直接调用flush()来刷新cout缓冲区。
flush(cout);
10)十进制、十六进制和八进制输出
hex(cout);或
cout<<hex;
dec十进制;hex十六进制;oct八进制
完成上述设置后,程序将以十六进制形式打印整数值,直到将格式状态设置为其他选项为止。注意,控制符不是成员函数,不能通过对象来调用。
11)调整字段宽度
int width();
int width(int i);
第一种格式返回字段宽度的当前设置;第二种格式将字段宽度设置为i个空格,并返回以前的字段宽度值。这使得能够保持以前的值,以便以后恢复宽度值时使用。width()方法只影响将显示的下一个项目,然后字段宽度将恢复为默认值。
cout<<'#';
cout.width(5);
cout<<12<<'#';
# 12#
12)填充字符
在默认情况下,cout用空格填充字段中未被使用的部分,可以用fill()成员函数来改变填充字符。
cout.fill('*');
13)设置浮点数的显示精度
浮点数精度的含义取决于输出模式。在默认情况下,它指的是显示的总位数。在定点模式和科学模式下,精度指的是小数点后面的位数。c++默认精度为6位(但末尾的0将不显示)。precision()成员函数使得能够选择其他值。
cout.precision(2);//精度设置为2
和width()的情况不同而与fill()类似,新的精度设置将一直有效,直到新的精度被设置为止。
14)setf()
第一种原型:fmtflags setf(fmtflags);
fmtflags是bitmask类型的typedef别名,用于存储格式标记。该名称是在ios_base类中定义的。这个版本的setf()用来设置单个位控制的格式信息。参数是一个fmtflags值,指出要设置哪一位。返回值是类型为fmtflags的数字,指出所有标记以前的设置。
格式常量
常量 含义
ios_base::boolalpha 输入和输出bool值,可以为true或false
ios_base::showbase 对于输出,使用c++基数前缀(0,0x)
ios_base::showpoint 显示末尾的小数点
ios_base::uppercase 对于16进制输出,使用大写字母,E表示法
ios_base::showpos 在正数前面加上+
注意:bitmask类型是一种用来存储各个位值的类型。它可以是整形、枚举,也可以是STL bitset容器。这里的主要思想是,每一位都是可以单独访问的,都有自己的含义。
15)第二种原型:fmtflags setf(fmtflags,fmtflags);
setf(long,long)的参数
第二个参数 第一个参数 含义
ios_base::basefield ios_base::dec 使用基数10
ios_base::basefield ios_base::oct 使用基数8
ios_base::basefield ios_base::hex 使用基数16
ios_base::floatfield ios_base::fixed 使用定点计数法
ios_base::floatfield ios_base::scientific 使用科学计数法
ios_base::adjustfield ios_base::left 使用左对齐
ios_base::adjustfield ios_base::right 使用右对齐
ios_base::adjustfield ios_base::internal 符号或基数前缀左对齐,值右对齐
16)头文件iomanip
3个最常用的控制符分别是setprecision()、setfill()和setw()。它们分别是设置精度、填充字符和字段宽度。
setprecision()控制符接受一个指定精度的整数参数;
setfill()控制符接受一个指定填充字符的char参数;
setw()控制符接受一个指定字段宽度的整数参数。
cout<<setw(6)<<"N"<<setw(14)<<"square root"
<<setw(15)<<"fourth root\n";