1、除了条件状态之外,每个iostream对象还维持一个控制IO格式化细节的状态。如整形值的基数,浮点值的精度,输出元素的宽度等。标准库还定义了一组操纵符来修改对象的格式状态。操纵符(manipulator)是可用作输入或输出运算符的操作数,它是一个函数或对象(a manipulator is a function or object that can be used as an operand([计]操作数;运算对象) to an input or output operator(运算符).)。操纵符返回其应用于的流对象,所以可以在一个语句中输出多个操纵符和数据。
2、操纵符罗列
表1 iostream 中定义的操纵符
|
||
|
boolalpha
|
将真和假显示为字符串
|
x
|
noboolalpha
|
将真和假显示为1,0
|
|
showbase
|
产生指出数的基数的前缀
|
x
|
noshowbase
|
不产生记数基数前缀
|
|
showpoint
|
总是显示小数点
|
x
|
noshowpoint
|
有小数部分才显示小数点
|
|
showpos
|
显示非负数中的+
|
x
|
noshowpos
|
不显示非负数中的+
|
|
uppercase
|
在十六进制中打印0X,科学记数法中打印E
|
x
|
nouppercase
|
在十六进制中打印0x,科学记数法中打印e
|
x
|
dec
|
用十进制显示(整形值,符点数不受影响)
|
|
hex
|
用十六进制显示(整形值,符点数不受影响)
|
|
oct
|
用八进制显示(同上)
|
|
left
|
在值的右边增加填充字符
|
|
right
|
在值的左边增加填充字符
|
|
internal
|
在符号和值之间增加填充字符
|
|
fixed
|
用小数形式显示浮点数
|
|
scientific
|
用科学记数法显示浮点数
|
|
boolalpha
|
将真和假显示为字符串
|
|
flush
|
刷新ostream缓冲区
|
|
ends
|
插入空字符,然后刷新ostream缓冲区
|
|
endl
|
插入换行符,然后刷新ostream缓冲区
|
|
unitbuf
|
在每个输出操作之后刷新缓冲区
|
x
|
nounitbuf
|
恢复常规缓冲区刷新
|
x
|
skipws
|
为输入操作符跳过空白
|
|
noskipws
|
不为输入操作符跳过空白
|
|
ws
|
“吃掉”空白
|
注:带 x 的是默认流状态。
|
||
表2 iomanip 中定义的操纵符
|
||
setfill(ch)
|
用 ch 填充空白
|
|
setprecision(n)
|
将浮点精度置为 n
|
|
setw(w)
|
读写 w 个字符的值
|
|
setbase(b)
|
按基数 b 输出整数
|
3、读写操纵符的时候,不读写数据,相反,会采取某种行动。改变流格式状态的操纵符通常为后续IO保留改变后的格式状态。取消操纵符的任何状态改变通常是最好的。一般而言,流应该在每个IO操作之后处于通常的默认状态。大多数改变格式状态的操纵符提供设置/复原对,一个操纵符将格式状态置为新值而另一个进行复原,恢复常规默认格式。
4、用flags操作恢复格式状态
flags 操作类似于管理流的条件状态的rdstate和setstate操作。这种情况下,标准库定义了一对flags函数:
• 不带实参的 flags() 返回流的当前格式状态。返回值是名为 fmtflags的标准库定义类型。
• flags(arg) 接受一个实参并将流格式置为实参所指定的格式。
示例代码
void display(ostream& os) { //remember the current format state ostream::fmtflags curr_fmt = os.flags(); //do output that uses manipulators that change the format state of os os.flags(curr_fmt); //restore the original format state of os }
5、控制输出格式
有两大类的输出控制:控制数值的表示,以及控制填充符的数据和布局。
示例代码
int main() { bool bool_val; cout << boolalpha << bool_val << noboolalpha; return 1; }
6、控制浮点值的格式
1)对于浮点值的格式化,可以控制下面三个方面:
• 精度:显示多少位数字(总位数)。
• 记数法:用小数还是科学记法法显示。
• 对是整数的浮点值的小数点的处理。
示例代码
int main() { cout << "Precision: " << cout.precision() << ", value: " << sqrt(2.0) << endl; int prev_precision = cout.precision(12); cout << ", value: " << sqrt(2.0) << endl; cout << setprecision(prev_precision); cout << ", value: " << sqrt(2.0) << endl; return 1; }
2)恢复浮点值的默认记数法
与其他操纵符不同,我们必须调用unsetf成员来取消scientific或fixed所做的改变。
示例代码
#include <iostream> #include "string" #include "cmath" using namespace std; int main() { cout << sqrt(2.0) << '\n' << endl; cout << scientific << sqrt(2.0) << endl; cout << fixed << sqrt(2.0) << endl; //reset to default handling for notation cout.unsetf(ostream::floatfield); cout << sqrt(2.0) << endl; return 1; }
7、填充输出
• setw,指定下一个数值或字符串的最小间隔。
• left,左对齐输出。
• right,右对齐输出。输出默认为右对齐。
• internal,控制负值的符号位置。internal 左对齐符号且右对齐值,用空格填充介于其间的空间。
• setfill,使我们能够指定填充输出时使用的另一个字符。默认情况下,值是空格。
像 endl 一样,setw 不改变输出流的内部状态,它只决定下一个输出的长度。
示例代码
#include <iostream> #include "string" #include "cmath" #include "iomanip" using namespace std; int main() { int i = -16; double d = 3.14159; cout << setfill('#') << "i: " << setw(12) << i << endl << "d: " << setw(12) << d << endl << setfill(' '); //restore normal pad character return 1; }
8、默认情况下,输入操作符忽略空白(空格,制表符,换行符,进纸和回车)。noskipws则强制要求不跳过空白。