cout格式化输出

曾经终败给现在 2022-05-23 05:15 415阅读 0赞

转载于:cout格式化输出

在C语言中,我们一般用printf()函数来进行输出,通过输出字符串中的格式说明符(如%4.2d)可以很容易地格式化输出。而在C++中,为简便起见,往往不指定输出的格式,由系统根据数据的类型采取默认的格式,但有时也需要数据按我们指定的格式输出,比如以十六进制的形式输出一个整数等。有两种方法可以达到格式化输出的目的,一种是使用流对象的有关成员函数,还有一种是使用控制符方法,这两种方法殊途同归,它们的原理和起到的作用都是一样的,只不过使用形式不一样。

cout格式化输出常用函数及标志汇总

表1 用于控输出格式的流成员函数及控制符




































流成员函数 作用相同的控制符 作用
precision(n) setprecision(n) 设置实数的精度为n位
width(n) setw(n) 设置字段宽度为n位
fill(c) setfill(c) 设置填充宇符c
setf(ios::state) setiosflags(ios::state) 设置输出格式状态,括号中应给出格式状态,内容与控制符setiosflags括号中的内容相同,如表2所示
unsetf(ios::state) resetioflags(ios::state) 终止已设置的输出格式状态,在括号中应指定内容

表2 设置格式状态的格式标志






































































格式标志 作用
ios::left 输出数据在本域宽范围内向左对齐
ios::right 输出数据在本域宽范围内向右对齐
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::boolalpha 以“true”/“false”的形式输出布尔值
ios::unitbuf 每次输出之后刷新所有的流
ios::stdio 每次输出之后清除stdout, stderr

用流对象的成员函数控制输出格式

我们可以使用用流对象的成员函数来控制输出格式。比如我们想要以十六进制来输出一个整形,设置字段宽度为8位,并用’*’来填充空白的话,可以使用以下代码:

  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4. int a = 31;
  5. cout.width(8);
  6. cout.fill('*');
  7. cout.unsetf(ios::dec);
  8. cout.setf(ios::hex);
  9. cout << a << endl;
  10. }
  11. 1
  12. 2
  13. 3
  14. 4
  15. 5
  16. 6
  17. 7
  18. 8
  19. 9
  20. 10

输出为:

******1f

使用控制符控制输出格式

我们也可以使用控制符来控制输出格式,这样就无需调用流的成员函数,可以直接在输出输入流中调用相关控制符,我们可以用以下代码实现上文中同样的输出格式:

  1. #include <iostream>
  2. #include <iomanip> //不要忘记包含此头文件
  3. using namespace std;
  4. int main(){
  5. int a = 31;
  6. cout << setw(8) << setfill('*') << resetiosflags(ios::dec) << setiosflags(ios::hex) << a << endl;
  7. }
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

注意:

  • 使用控制符时需要包含头文件<iomanip>。
  • 表2中的格式标志有些是互斥的(比如dec、hex和oct中只能选一),如果想改设置为互斥的另一状态,应当调用成员函数unsetf(对应于成员函数self)或resetiosflags(对应于控制符setiosflags),终止原来设置的状态,然后再设置其他状态。比如之前的例子中终止了默认的十进制(ios::dec),然后再设置了十六进制(ios::hex),如果不终止原来的十进制标志的话,输出仍然会以十进制输出。
  • 各个函数中成员函数width(n)和控制符setw(n)只对其后的第一个输出项有效,而其他函数及各个标志是对输出输入流一直生效的。
  • 表2中的格式标志在ios类中被定义为枚举值,每一个格式标志以一个bit的0或1代表(如下enum _Ios_Fmtflags所示),因此可以用位或运算符“|”组合多个格式标志,在流成员函数setf()/unsetf()以及控制符setioflags()/resetioflags()同时设置。比如:cout.setf(ios::dec | ios::showpos);

    enum _Ios_Fmtflags

    1. {
    2. _S_boolalpha = 1L << 0,
    3. _S_dec = 1L << 1,
    4. _S_fixed = 1L << 2,
    5. _S_hex = 1L << 3,
    6. _S_internal = 1L << 4,
    7. _S_left = 1L << 5,
    8. _S_oct = 1L << 6,
    9. _S_right = 1L << 7,
    10. _S_scientific = 1L << 8,
    11. _S_showbase = 1L << 9,
    12. _S_showpoint = 1L << 10,
    13. _S_showpos = 1L << 11,
    14. _S_skipws = 1L << 12,
    15. _S_unitbuf = 1L << 13,
    16. _S_uppercase = 1L << 14,
    17. _S_adjustfield = _S_left | _S_right | _S_internal,
    18. _S_basefield = _S_dec | _S_oct | _S_hex,
    19. _S_floatfield = _S_scientific | _S_fixed,
    20. _S_ios_fmtflags_end = 1L << 16,
    21. _S_ios_fmtflags_max = __INT_MAX__,
    22. _S_ios_fmtflags_min = ~__INT_MAX__
    23. };
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24

格式标志简化控制输出格式

在上述两种方法中,要设置格式标志位都需要调用函数(setf和setiosflags),比较麻烦,所幸C++还有一组关于格式标志的函数,可以直接在输入输出流中使用,比如要实现之前的输出格式我们可以这么写:

  1. #include <iostream>
  2. #include <iomanip>
  3. using namespace std;
  4. int main(){
  5. int a = 31;
  6. cout << setw(8) << setfill('*') << hex << a << endl;
  7. }
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7

上面的hex就是这样的一个函数,除了hex,表2中的所有格式标志都通过这种方法设置,如果要终止只需标志名前加个“no”就可以,比如showpos和noshowpos(表2中前六项没有no版本)。
另外可以注意到,这里用hex设置十六进制的时候并不用像之前一样先终止十进制,这是为什么呢?先来看看hex的函数定义:

  1. inline ios_base&
  2. hex(ios_base& __base)
  3. {
  4. __base.setf(ios_base::hex, ios_base::basefield);
  5. return __base;
  6. }
  7. 1
  8. 2
  9. 3
  10. 4
  11. 5
  12. 6

可以看到hex其实是调用了setf函数,但这里的setf跟我们上面用到的setf函数不同,这是重载之后有两个形参的setf函数,其定义如下:

  1. fmtflags
  2. setf(fmtflags __fmtfl, fmtflags __mask)
  3. {
  4. fmtflags __old = _M_flags;
  5. _M_flags &= ~__mask;
  6. _M_flags |= (__fmtfl & __mask);
  7. return __old;
  8. }
  9. 1
  10. 2
  11. 3
  12. 4
  13. 5
  14. 6
  15. 7
  16. 8

可以看到这里setf先将mask所对应的位都置0,再将要设置的位置1。具体到hex函数,它是将_S_basefield(_S_dec | _S_oct | _S_hex)都先置0,再将_S_hex位置1。有了这个setf函数,我们在使用hex的时候就不需要先终止dec了,可以直接使用hex。

  1. <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css">
  2. </div>

发表评论

表情:
评论列表 (有 0 条评论,415人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++ cout格式化输出

    希望按照一定的格式进行输出,如按十六进制输出整数,输出浮点数时保留小数点后面两位,输出整数时按 6 个数字的宽度输出,宽度不足时左边补 0,等等。C++ 中的 cout 对象则

    相关 cout格式化输出

    在C语言中,我们一般用printf()函数来进行输出,通过输出字符串中的格式说明符(如%4.2d)可以很容易地格式化输出。而在C++中,为简便起见,往往不指定输出的格式,由系统

    相关 cout格式化输出

    转载于:[cout格式化输出][cout] 在C语言中,我们一般用printf()函数来进行输出,通过输出字符串中的格式说明符(如%4.2d)可以很容易地格式化输出。而在C+