1. 程式人生 > >C++基礎——格式化輸出

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; }

這裡寫圖片描述

如上圖的輸出顯示,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;
}

五、 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