重载的<<操作符
ostream类重新定义了<< 操作符。这时应叫作 插入(insertion)操作符 。
插入操作符被重载,使之能够识别C++中所有的基本类型:
unsigned char signed char
char short
unsigned short int
unsigned int long
unsigned long float
double long double
ostream类还为下面的指针类型定义了插入操作符函数:
const signed char * const unsigned char *
const char * void *
重载的operator<<()函数返回一个指向ostream对象的引用,这使得可以将输出连接起来。
其他ostream方法
put() 方法,用于显示字符。最初原型如下:
ostream & put(char);
当前标准与此相同,但被模板化,以适用于wchar_t 。
用类方法表示法来调用:
cout.put('w'); // display the w character
该方法也返回一个指向调用对象的引用,因此可以用它来拼接输出:
cout.put('i').put('t'); // display "it" with two put()calls
在原型合适的情况下,可以将数值型参数用于put(),让函数原型自动将参数转换为正确的char值。例如:
cout.put(65); // display the A character
cout.put(66.3); // display the B character
第二条语句将double值66.3转换为char值66,并显示ASCII码对应的字符。
write() 方法,用于显示整个字符串,其模板原型如下:
basic_ostream<charT, traits> & write (const char_type * s, streamsize n);
write()的第一个参数提供了要显示的字符串的地址,第二个参数指出要显示多少个字符。
使用cout调用write()时,将调用char具体化,因此返回类型为ostream & 。
该方法并不会在遇到空字符时停止打印字符,而是打印指定数目的字符,即使超出了字符串的边界。
write()方法也可用于数值数据,只需将数字的地址强制转换为char * ,然后传递给它:
long val = 560031841;
cout.write( (char *) &val, sizeof(long));
这不会将数字转换为相应的字符,而是传输内存中存储的位表示。
4字节的long值将作为4个独立的字节被传输。输出设备将把每个字节作为ASCII码进行解释。因此560031841将被显示为4个字符的组合。
刷新输出缓冲区
除了将换行符发送到缓冲区,会刷新缓冲区以外。在输入即将发生时也会刷新缓冲区。例如:
cout << "Enter a number: ";
float num;
cin >> num;
程序期待输入这一事实,将导致它立刻显示cout消息,即使输出字符串中没有换行符。
另外,可以使用控制符flush 刷新缓冲区,或控制符endl 刷新缓冲区,并插入一个换行符:
cout << "Hello, good-looking! " << flush;
cout << "Wait just a moment, please. " << endl;
事实上,控制符也是函数。例如,可以直接调用flush()来刷新cout缓冲区:
flush(cout);
由于ostream类对<< 插入操作符进行了重载,使得表达式:
cout << flush
将被替换为函数调用flush(cout)。
cout格式化
1. 修改显示时使用的计数系统
要控制整数以十进制、十六进制还是八进制显示,可以使用dec、hex、oct 控制符,它们都在std名称空间中。
例如,下面的函数调用:
hex(cout);
将cout对象的计数系统格式状态设置为十六进制,直到将格式状态设置为其他选项为止。
控制符不是成员函数,不必通过对象来调用。通常的使用方式为:
cout << hex;
2. 调整字段宽度
width() 成员函数将长度不同的数字放到宽度相同的字段中,原型为:
int width();
int width(int i);
第一种格式返回字段宽度的当前值。
第二种格式将字段宽度设置为i个空格,并返回以前的字段宽度值。
width()方法只影响将显示的下一个项目,然后字段宽度将恢复为默认值。
例如,下面的语句:
cout << '#';
cout.width(12); // 由于width()是成员函数,因此必须使用对象来调用它
cout << 12 << "#" << 24 << "#/n";
输出如下:
# 12#24#
12被放到宽度为12个字符的字段的最右边,这被称为右对齐 。
C++永远不会截短数据,如果试图在宽度为2的字段中打印一个7位值,C++将增宽字段,以容纳该数据。
3. 填充字符
默认情况下,cout用空格填充字段中未被使用的部分。
可以用fill() 成员函数来改变填充字符。例如:
cout.fill('*');
将填充字符改为星号。
新的填充字符将一直有效,直到更改它为止。
4. 设置浮点数的显示精度
浮点数精度的含义取决于输出模式。
默认模式下,它指的是显示的总位数。
在定点模式和科学模式下,精度指的是小数点后面的位数。
默认精度为6位,不过末尾的0将不显示。
precision() 成员函数能设置其他值。例如:
cout.precision(2);
将cout的精度设置为2。
新的精度设置将一直有效,直到被重新设置。
5. setf()
ios_base类提供了一个setf()函数(用于set标记),能够控制多种格式化特性。
seft()函数有两个原型。第一个为:
fmtflags setf (fmtflags);
fmtflags是bitmask类型的typedef名,用于存储格式标记。
bitmask类型是一种用来存储各个位值的类型。它可以是整形、枚举,也可以是STL bitset容器。其中的每一位都可以单独访问,都有自己的含义。
这个版本的setf()用来设置单个位控制的格式信息。返回值是标记以前的设置。
ios_base类定义了代表位值的常量,下图列出了其中的一些定义。
使用它们时,必须加上作用域解析操作符。例如,ios_base::uppercase 。
修改将一直有效,直到被覆盖为止。
seft()函数第二个原型接受两个参数,并返回以前的设置:
fmtflags setf (fmtflags, fmtflags);
这种重载格式用于设置由多位控制的格式选项。
第一个参数和前面一样,是一个包含了所需设置的fmtflags值。
第二个参数指出要清除第一个参数中的哪些位。
举例说明,将第3位设置为1表示以10为基数,将第4位设置为1表示以8为基数,将第5位设置为1表示以16为基数。假设现在是以10为基数,而要将它设置为以16为基数,则不仅需要将第5位设置为1,还需要将第3位设置为0。这叫作清除位(clearing the bit) 。
ios_base类为此定义了常量。
定点表示法意味着使用格式123.4来表示浮点值,而不管数字的长度如何。
科学表示法则意味着使用格式1.23e04,而不考虑数字的长度。
定点表示法和科学表示法都有下面的两个特征:
精度指的是小数点位数,而不是总位数。
显示末尾的0。
可以声明一个fmtflags类型的值,来保存cout的默认格式,以备以后恢复:
ios_base::fmtflags old = cout.setf(fmtflags);
cout.setf(old);
6. unsetf()
unsetf()成员函数用来消除调用setf()设置的效果。原型如下:
void unsetf(fmtflags mask);
mask是位模式,其中所有的位都设置为1,将使得对应的位被复位。也就是说,setf()将位设置为1,unsetf()将位恢复为0。例如:
cout.setf(ios_base::showpoint); // show trailing decimal point
cout.unsetf(ios_base::boolalpha); // don't show trailing decimal point
cout.setf(ios_base::boolalpha); // display true,false
cout.unsetf(ios_base::boolalpha); // display 1,0
没有专门指示浮点数默认显示模式的标记。仅当只有定点位被设置时使用定点表示法;仅当只有科学位被设置时使用科学表示法;对于其他组合,如没有位被设置或两位都被设置时,将使用默认模式。
启用默认模式的方法之一:
cout.setf(0, ios_base::floatfield); // go to default mode
第二个参数关闭这两位,第一个参数不设置任何位。
启用默认模式的方法之二:
cout.unsetf(ios_base::floatfield);
如果已知cout出于定点状态,则可以使用参数ios_base::fixed调用函数unsetf()来切换到默认模式。但无论cout当前状态如何,使用参数ios_base::floatfield调用函数unsetf()都将切换到默认模式。
7. 标准控制符
C++提供了多个控制符,能够调用setf(),并自动提供正确的参数。这些控制符的工作方式就像前面介绍过的dex、hex和oct一样。
下图列出了这些控制符以及其他一些控制符。
8. iomanip头文件
该头文件中提供了其他一些控制符,它们能够提供前面讨论过的服务,但表示起来更方便。
3个最常用的控制符:
setprecision() 控制符接受一个指定精度的整数参数;
setfill() 控制符接受一个指定填充字符的char参数;
setw() 控制符接受一个指定字段宽度的整数参数。
它们都可以用cout语句连接起来使用。例如:
cout << setw(5) << "Hello" << setw(10) << "World./n";