似乎很少有人强调C++的格式化输出的问题,那是因为因为c++的编译器默默地做着许多格式化的动作,以保证C++ Style格式化输出与C-style的格式化的一个根本不同,C++style的格式化输出是类型安全的(type-safe),而C-style不是。当然,我们也可以定制这些格式化的动作,就像C那样,而不全都拜托编译器。
头文件
包含iomanip
头文件,iomanip
顾名思义,io manipulator(操纵器)。本文所用库函数或者变量,只有std::boolalpha
在iostream
头文件中以外,其他都在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;
}
如上图的输出显示,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;
}
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;
}
std::hex
,std::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;