[Turn] C++ cout formatted output
Transfer from here
Sometimes you want to output according to a certain format, such as outputting integers in hexadecimal, leaving two digits after the decimal point when outputting floating-point numbers, outputting integers in the width of 6 digits, and padded 0 on the left when the width is insufficient, and so on. The printf() function in C language uses %
format control symbols that begin with, such as %X, %.2f, %6d, etc.; the cout object in C++ uses stream operators (you can also call format control symbols) or members Function to control.
Use stream operators
Commonly used output stream manipulation operators in C++ are shown in Table 1. They are all defined in the header file iomanip; to use these stream manipulation operators, the header file must be included.
Note: The asterisk in the "Flow Manipulation Operator" column is
*
not a part of the operator. The asterisk means that if no operator is used, it is equivalent to using the operator. For example, by default, integers are output in decimal form, which is equivalent to using the dec operator.
Flow operator | Use | |
---|---|---|
*dec | Output integer in decimal form | Commonly used |
hex | Output integers in hexadecimal form | |
oct | Output integer in octal form | |
fixed | Output floating point numbers as ordinary decimals | |
scientific | Output floating point numbers in scientific notation | |
left | Left-justified, that is, fill characters are added to the right when the width is insufficient | |
*right | Right-aligned, that is, when the width is insufficient, fill characters are added to the left | |
setbase(b) | Set the base when outputting integers, b=8, 10 or 16 | |
setw(w) | Specify the output width as w characters, or read w characters when inputting a character string | |
setfill © | When the output width is specified, when the output width is insufficient, the character c is used to fill (the default is to fill with spaces) | |
setprecision(n) | Set the precision of the output floating point number to n. In the case of non-fixed and non-scientific output, n is the number of significant digits. If the number of significant digits exceeds n, the fractional part will be rounded off, or it will be automatically converted to scientific notation for output and kept in total n significant digits. In the case of fixed and scientific output, n is the number of digits that should be kept after the decimal point. | |
setiosflags(flag) | Set a certain output format flag to 1 | |
resetiosflags(flag) | Set an output format flag to 0 | |
boolapha | Output true and false as strings | uncommonly used |
* noboolalpha | Output true and false as 0, 1 | |
showbase | Output the prefix of the base of the value | |
*noshowbase | Do not output the prefix of the base. | |
showpoint | Always output decimal point | |
*noshowpoint | Display the decimal point only when the decimal part exists | |
showpos | Show in non-negative values + | |
*noshowpos | Do not display in non-negative values + | |
* skipws | Skip blank characters when typing | |
noskipws | Do not skip blank characters when typing | |
uppercase | Use A~E in hexadecimal number. If the prefix is output, the prefix outputs 0X, and the output E in scientific notation | |
*nouppercase | Use a~e in hexadecimal numbers. If the prefix is output, the prefix outputs 0x, and in scientific notation, it outputs e. | |
internal | The sign (plus or minus) of the value is left aligned within the specified width, the value is aligned right, and the middle is filled with padding characters. |
How to use stream operators
The way to use these operators is to use << and cout together. E.g:
cout << hex << 12 << "," << 24;
The function of this statement is to specify the following two numbers to be output in hexadecimal form, so the output result is:
c, 18
setiosflags () operator
The setiosflags() operator is actually a library function. It takes some flags as parameters. These flags can be the following values defined in the iostream header file. Their meaning is the same as the operator of the same name.
Sign | Use |
---|---|
ios::left | The output data is aligned to the left within the wide range of this field |
ios::right | The output data is aligned to the right within the wide range of this field |
ios::internal | 数值的符号位在域宽内左对齐,数值右对齐,中间由填充字符填充 |
ios::dec | 设置整数的基数为 10 |
ios::oct | 设置整数的基数为 8 |
ios::hex | 设置整数的基数为 16 |
ios::showbase | 强制输出整数的基数(八进制数以 0 开头,十六进制数以 0x 打头) |
ios::showpoint | 强制输出浮点数的小点和尾数 0 |
ios::uppercase | 在以科学记数法格式 E 和以十六进制输出字母时以大写表示 |
ios::showpos | 对正数显示“+”号 |
ios::scientific | 浮点数以科学记数法格式输出 |
ios::fixed | 浮点数以定点格式(小数形式)输出 |
ios::unitbuf | 每次输出之后刷新所有的流 |
ios::stdio | 每次输出之后清除 stdout, stderr |
这些标志实际上都是仅有某比特位为 1,而其他比特位都为 0 的整数。
多个标志可以用|
运算符连接,表示同时设置。例如:
cout << setiosflags(ios::scientific|ios::showpos) << 12.34;
输出结果是:
+1.234000e+001
如果两个相互矛盾的标志同时被设置,如先设置 setiosflags(ios::fixed),然后又设置 setiosflags(ios::scientific),那么结果可能就是两个标志都不起作用。因此,在设置了某标志,又要设置其他与之矛盾的标志时,就应该用 resetiosflags 清除原先的标志。例如下面三条语句:
cout << setiosflags(ios::fixed) << 12.34 << endl;
cout << resetiosflags(ios::fixed) << setiosflags(ios::scientific | ios::showpos) << 12.34 << endl;
cout << resetiosflags(ios::showpos) << 12.34 << endl; //清除要输出正号的标志
输出结果是:
12.340000
+1.234000e+001
1.234000e+001
综合示例
关于流操纵算子的使用,来看下面的程序。
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int n = 141;
//1) 分别以十六进制、十进制、八进制先后输出 n
cout << "1)" << hex << n << " " << dec << n << " " << oct << n << endl;
double x = 1234567.89, y = 12.34567;
//2)保留5位有效数字
cout << "2)" << setprecision(5) << x << " " << y << " " << endl;
//3)保留小数点后面5位
cout << "3)" << fixed << setprecision(5) << x << " " << y << endl;
//4)科学计数法输出,且保留小数点后面5位
cout << "4)" << scientific << setprecision(5) << x << " " << y << endl;
//5)非负数显示正号,输出宽度为12字符,宽度不足则用 * 填补
cout << "5)" << showpos << fixed << setw(12) << setfill('*') << 12.1 << endl;
//6)非负数不显示正号,输出宽度为12字符,宽度不足则右边用填充字符填充
cout << "6)" << noshowpos << setw(12) << left << 12.1 << endl;
//7)输出宽度为 12 字符,宽度不足则左边用填充字符填充
cout << "7)" << setw(12) << right << 12.1 << endl;
//8)宽度不足时,负号和数值分列左右,中间用填充字符填充
cout << "8)" << setw(12) << internal << -12.1 << endl;
cout << "9)" << 12.1 << endl;
return 0;
}
程序的输出结果是:
1)8d 141 215
2)1.2346e+06 12.346
3)1234567.89000 12.34567
4)1.23457e+06 1.23457e+01
5)***+12.10000
6)12.10000****
7)****12.10000
8)-***12.10000
9)12.10000
需要注意的是,setw() 算子所起的作用是一次性的,即只影响下一次输出。每次需要指定输出宽度时都要使用 setw()。因此可以看到,第 9) 行的输出因为没有使用 setw(),输出的宽度就不再是前面指定的 12 个字符。
在读入字符串时,setw() 还能影响 cin 的行为。例如下面的程序:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
string s1, s2;
cin >> setw(4) >> s1 >> setw(3) >> s2;
cout << s1 << "," << s2 << endl;
return 0;
}
输入:
1234567890↙
程序的输出结果是:
1234,567
说明setw(4)
使得读入 s1 时,只读入 4 个字符,其后的setw(3)
使得读入 s2 时只读入 3 个字符。
setw() 用于 cin 时,同样只影响下一次的输入。
思考题:setw() 究竟是如何实现的,以至于能和 cout 连用来指定输出宽度?自行查看编译器所带的 iomanip 头文件,然后写一个功能和 setw() 完全相同的 mysetw()。
调用cout的成员函数
ostream 类有一些成员函数,通过 cout 调用它们也能用于控制输出的格式,其作用和流操纵算子相同,如表 3 所示。
成员函数 | 作用相同的流操纵算子 | 说明 |
---|---|---|
precision(n) | setprecision(n) | 设置输出浮点数的精度为 n。 |
width(w) | setw(w) | 指定输出宽度为 w 个字符。 |
fill© | setfill © | 在指定输出宽度的情况下,输出的宽度不足时用字符 c 填充(默认情况是用空格填充)。 |
setf(flag) | setiosflags(flag) | 将某个输出格式标志置为 1。 |
unsetf(flag) | resetiosflags(flag) | 将某个输出格式标志置为 0。 |
setf 和 unsetf 函数用到的flag
,与 setiosflags 和 resetiosflags 用到的完全相同。
这些成员函数的用法十分简单。例如下面的三行程序:
cout.setf(ios::scientific);
cout.precision(8);
cout << 12.23 << endl;
输出结果是:
1.22300000e+001