C++基础——格式化输出

似乎很少有人强调C++的格式化输出的问题,那是因为因为c++的编译器默默地做着许多格式化的动作,以保证C++ Style格式化输出与C-style的格式化的一个根本不同,C++style的格式化输出是类型安全的(type-safe),而C-style不是。当然,我们也可以定制这些格式化的动作,就像C那样,而不全都拜托编译器。

准备

  • 头文件

    包含iomanip头文件,iomanip顾名思义,io manipulator(操纵器)。本文所用库函数或者变量,只有std::boolalphaiostream头文件中以外,其他都在iomanip

  • 每使用iomanip头文件的std命名空间中的函数对输出的格式做任何形式的设置,影响的都是其后的输出格式,而对之前的输出毫无影响。

零、 输出布尔类型

bool b = bool();            // 显式地调用其构造函数实现对基本类型的初始化
std::cout << std::boolalpha << b << std::endl;      // 输出为'false',而不是将bool类型转化为‘0’

一、 域宽的设置

setw(n)

#include <iostream>
#include <iomanip>

int main(int, char**)
{
    const int max = 10;
    const int width = 6;
    for (int row = 1; row < max; ++row)
    {
        for (int col = 1; col < max; ++col)
        {
            std::cout << std::setw(width) << row * col;
        }
        std::cout << std::endl;
    }
    return 0;
}


C++基础——格式化输出_第1张图片

如上图的输出显示,setw()默认是右对齐。

二、 对齐方式的设置

共有两种对齐方式的设置:std::ios::left, std::ios::right,所用到的api是std::setiosflags,以及std::resetiosflags

for (int row = 1; row < max; ++row)
{
    if (row%2)      // 奇数行
        std::cout << std::setiosflags(std::ios::left);  // 设置对齐方式为左对齐
    else
        std::cout << std::resetiosflags(std::ios::left);    
    for(int col = 1; col < max; ++col)
    {
        std::cout << row * col;     
    }
    std::cout << std::endl;
}


C++基础——格式化输出_第2张图片

三、 精度的控制

std::setprecision(n)

double x = 800000./81;
std::cout << std::setprecision(2) << x << endl;     // 9.9e+003
std::cout << std::setiosflags(std::ios::fixed) 
                    << std::setprecision(2) 
                    << x << std::endl;              // 9876.54
                    // std::setiosflags(std::ios::fixed)
                    // 避免使用科学计数法?

使用setprecision()设置的精度位数,最后的输出结果是一种四舍五入的版本;

std::cout << std::setiosflags(std::ios::fixed) 
            << std::setprecision(4) << 2./3 << std::endl;   // 0.6667

不使用 <iomanip>头文件中的相关 api,使用 std::cout 输出流的成员函数也可实现精度的设置:

std::cout.precision(20);

四、 设置填充字符

std::setfill('')

void showDate(int m, int d, int y)      // 月 日 年
{
    std::cout << std::setfill('0'); 
    std::cout << std::setw(2) << m << '/'
            << std::setw(2) << d << '/'
            << std::setw(4) << y << std::endl;
}

五、 10进制、8进制、16进制

std::hexstd::oct

unsigned long x = 64206;
std::cout << x
        << " in base 8 is \"" << std::oct << x << "\""
        << " in base 16 is \"" << std::hex << x << "\"" << std::endl;

C++库函数并没有提供一个任意进制的转换,如下是一个转换版本:

std::string convBase(unsigned long val, long base)
{
    std::string digits = "0123456789ABCDEF";
    std::string ret;
    if (base < 2 || base > 16)
        ret = "base out of range";
    else
    {
        do
        {
            ret = digits[val%base] + ret;       
                        // != (ret != digits[val%base]), 否则顺序将会是逆序
            ret /= base;
        }while(val);
    }
    return ret;
}

六、补充

禁止科学计数法

std::cout << std::fixed << someNumber<< std::endl;

references

  1. <Output Formatting>

你可能感兴趣的:(C++,格式化输出,iomanip)