c++ 格式化输出总结

可使用的格式

原始格式的备份与恢复

1
2
3
4
5
// 备份
std::ostream::fmtflags flags = std::cout.flags();

// 恢复
std::cout.flags(flags);

存在的格式

flags: 新的格式设置, 可以通过下面的进行组合得到.

Constant Explanation
dec 10进制表示整数, std::dec
oct 8进制表示整数, std::oct
hex 16进制表示整数, std::hex
basefield 用于dec,oct,hex or 0. 是个关于进制的掩码, 用于记录当前是哪个进制
left 左对齐, 用填充字符填充右边, std::left
right 右对齐, 用填充字符填充右边, std::right
internal 内部对齐,用填充字符填充内部指定的点, std::internal
adjustfield 用于left,right和internal. 同basefield
scientific 使用科学计数法表示小数, 或进制计数法(如果与fixed联合使用), std::scientific
fixed 使用普通定点格式表示小数, std::fixed
floatfield 用于scientific, fixed, (scientific,fixed)和0. 同basefield
boolalpha 将bool类型以true或false输出,而不是0或1, std::boolalpha
showbase 为整数添加一个表示其进制的前缀, std::showbase
showpoint 在浮点数中强制插入小数点, std::showpoint
showpos 在正数前面加入+, 只对十进制有效, std::showpos
skipws 忽略前导空格, 主要用于输入流, std::skipws
unitbuf 在每次插入后清空输出缓存, std::unitbuf
uppercase 对于十六进制和科学计数法里的字符, 以大写输出, std::uppercase

格式的使用

bool 变量的输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
// 输出true or false
std::cout << std::boolalpha
<< "boolalpha true: " << true << '\n'
<< "boolalpha false: " << false << '\n';
// 输出0 or 1
std::cout << std::noboolalpha
<< "noboolalpha true: " << true << '\n'
<< "noboolalpha false: " << false << '\n';
// booalpha parse
bool b1, b2;
std::istringstream is("true false");
is >> std::boolalpha >> b1 >> b2;
std::cout << '\"' << is.str() << "\" parsed as " << b1 << ' ' << b2 << '\n';

输出为:

1
2
3
4
5
boolalpha true: true
boolalpha false: false
noboolalpha true: 1
noboolalpha false: 0
"true false" parsed as 1 0

进制的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 输出指定进制的整数
std::cout<<"无前导: "<<'\n'<<std::noshowbase
<< "The number 42 in octal: " << std::oct << 42 << '\n'
<< "The number 42 in decimal: " << std::dec << 42 << '\n'
<< "The number 42 in hex: " << std::hex << 42 << '\n';

// 添加进制的前导
std::cout << "有前导" <<'\n'<<std::showbase
<< "The number 42 in octal: " << std::oct << 42 << '\n'
<< "The number 42 in decimal: " << std::dec << 42 << '\n'
<< "The number 42 in hex: " << std::hex << 42 << '\n';

// 通过掩码设置进制
std::cout << "掩码操作进制显示" << std::endl;
int num = 150;
std::cout.setf(std::cout.oct, std::cout.basefield);
std::cout.setf(std::cout.showbase);
std::cout << num << '\n';

std::cout.setf (std::cout.dec , std::cout.basefield);
std::cout.setf (std::cout.showbase);
std::cout << num << '\n';

std::cout.setf(std::cout.hex, std::cout.basefield);
std::cout.setf(std::cout.showbase);
std::cout << num << '\n';

输出为:

1
2
3
4
5
6
7
8
9
10
11
12
无前导:
The number 42 in octal: 52
The number 42 in decimal: 42
The number 42 in hex: 2a
有前导
The number 42 in octal: 052
The number 42 in decimal: 42
The number 42 in hex: 0x2a
掩码操作进制显示
0226
150
0x96

对齐操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 对齐
std::cout << "===============对齐与填充操作=======================" << std::endl;
std::cout << "Left fill:\n" << std::left << std::setfill('*')
<< std::setw(12) << -1.23 << '\n'
<< std::setw(12) << std::showpos << 1.23 << '\n'
<< std::setw(12) << std::dec << std::noshowpos <<std::showbase << 42 << '\n'
<< std::setw(12) << std::dec << std::showpos << std::showbase << 42 << '\n'
<< std::setw(12) << std::hex << std::showbase << 42 << '\n' <<'\n';

std::cout << "Internal fill:\n" << std::internal
<< std::setw(12) << -1.23 << '\n'
<< std::setw(12) << std::showpos << 1.23 << '\n'
<< std::setw(12) << std::dec << std::noshowpos << std::showbase << 42 << '\n'
<< std::setw(12) << std::dec << std::showpos << std::showbase << 42 << '\n'
<< std::setw(12) << std::hex << std::showbase<< 42 << '\n'<< '\n';

std::cout << "Right fill:\n" << std::right
<< std::setw(12) << -1.23 << '\n'
<< std::setw(12) << std::showpos << 1.23 << '\n'
<< std::setw(12) << std::dec << std::noshowpos << std::showbase << 42 << '\n'
<< std::setw(12) << std::dec << std::showpos << std::showbase << 42 << '\n'
<< std::setw(12) << std::hex << std::showbase << 42 << '\n'<< '\n';

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
===============对齐与填充操作=======================
Left fill:
-1.23*******
+1.23*******
42**********
+42*********
0x2a********

Internal fill:
-*******1.23
+*******1.23
**********42
+*********42
0x********2a

Right fill:
*******-1.23
*******+1.23
**********42
*********+42
********0x2a

浮点型的控制输出

  • 用浮点表示的输出中,setprecision(n)表示有效位数.
  • 用定点表示的输出中,setprecision(n)表示小数位数, 与fixed配合.
  • 用指数形式输出时,setprecision(n)表示小数位数, 与scientific配合.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int originPrecision = std::cout.precision();
std::cout << "===========================================================" << std::endl;
std::cout << "精度使用, 初始精度: "<<originPrecision << std::endl;
std::cout <<std::setprecision(4) <<12.345678 <<std::endl ; // 12.35 rounded!
std::cout <<std::setprecision(10) <<12.345678 <<std::endl ; // 12.345678 其实内部发生了 rounded, 而结果正好进位, 与原值相同

std::cout << "===========================================================" << std::endl;
std::cout << "小数的表示形式的使用" << std::endl;
std::cout << "当前精度: "<<std::cout.precision() << std::endl;
double f = 101 / 6.0 ;
std::cout << "小数的表现形式:" << std::endl;
std::cout <<"定点小数:"<<std::fixed << f <<std::endl ;
std::cout <<"科学计数法:"<<std::scientific <<f <<std::endl ;
std::cout <<"上一次设置的形式:"<<f*10 << std::endl;

std::cout << "===========================================================" << std::endl;
std::cout << "表现形式恢复为默认值, 这时候精度就表示小数的有效位数" << std::endl;
std::cout.unsetf(std::ostream::floatfield);
std::cout << "当前有效位数: "<<std::cout.precision() << std::endl;
std::cout << f <<std::endl ;

std::cout << "===========================================================" << std::endl;
std::cout << "恢复为初始精度:"<<std::setprecision(originPrecision) << std::endl;
std::cout << "当前精度: "<<std::cout.precision() << std::endl;

std::cout << "===========================================================" << std::endl;
std::cout << "显示十进制浮点" << std::endl;
std::cout << "不显示浮点:"<<12.0 << std::endl;
std::cout << "显示浮点:"<< std::showpoint<<10.0 << std::endl;
std::cout << "不显示浮点:"<< std::noshowpoint<<10.0 << std::endl;

输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
===========================================================
精度使用, 初始精度: 6
12.35
12.345678
===========================================================
小数的表示形式的使用
当前精度: 10
小数的表现形式:
定点小数:16.8333333333
科学计数法:1.6833333333e+001
上一次设置的形式:1.6833333333e+002
===========================================================
表现形式恢复为默认值, 这时候精度就表示小数的有效位数
当前有效位数: 10
16.83333333
===========================================================
恢复为初始精度:
当前精度: 6
===========================================================
显示十进制浮点
不显示浮点:12
显示浮点:10.0000
不显示浮点:10

输出指针地址

1
2
3
4
5
6
7
8
9
int a = 10;
std::cout << "基本数据类型地址:" << static_cast<void*>(&a) << std::endl;

std::string str = "hello!";
std::cout << "string类型首地址:"<< static_cast<void*>(&str) << std::endl;

char* strc = const_cast<char*>(str.c_str());
std::cout << "string里面存放内容的地址:"<< static_cast<void*>(strc) << std::endl;
std::cout << "string里面存放内容的地址:"<< static_cast<void*>(const_cast<char*>(str.c_str())) << std::endl;

输出为:

1
2
3
4
基本数据类型地址:0x62fe00
string类型首地址:0x62fde0
string里面存放内容的地址:0x62fdf0
string里面存放内容的地址:0x62fdf0

其他

后续完善