C++格式化输出(详解版)

前面已经介绍过可用于流对象的 I/O 操作符,特别是 setw(n)、fixed、showpoint、setprecision(n)、left 和 right 操作符。这些操作符都可以在 fstream、ofstream 和 ostringstream 对象上使用。

为了这些操作符的用法,可以假设需要一个函数,该函数釆用一个 double 类型的实参,表示一个项目的价格(以美元为单位),并返回一个以美元符号 $ 开头的字符串,将价格的数值精确到小数点后两位。例如,如果将 12.5 作为金额参数传递给函数,则函数将返回字符串 $12.50。使用 ostringstream 即可轻松编写该函数:
string dollarFormat(double amount)
{
    //创建 ostringstream 对象
    ostringstream outStr;
    //设置信息格式并写入outStr
    outStr << showpoint << fixed << setprecision(2);
    outStr << '$' << amount;
    //提取并返回outStr中的字符串
    return outStr.str ();
}
下面的程序使用 dollarFormat 函数来编写一个整齐格式化的价格表。价格是以二维数组给出的。该程序设置了每个价格的格式并打印了一个包含所有价格的表格,每个价格均右对齐,列宽为 10:
//This program demonstrates the use of an ostringstream object to do sophisticated formatting.
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;

string dollarFormat(double); // Function Prototype

int main()
{
    const int ROWS = 3, COLS = 2;
    double amount[ROWS][COLS] = {184.45, 7, 59.13, 64.32, 7.29, 1289 };
    // Format table of dollar amounts right justfied in columns of width 10
    cout << right;
    for (int row = 0; row< ROWS; row++)
    {
        for (int column = 0; column < COLS; column++)
        {
            cout << setw(10) << dollarFormat(amount[row][column]);
        }
        cout << endl;
    }
    return 0;
}
string dollarFormat(double amount)
{
    // Create ostringstream object
    ostringstream outStr;
    // Set up format information and write to outStr.
    outStr << showpoint << fixed << setprecision(2);
    outStr << '$' << amount;
    // Extract and return the string inside outStr.
    return outStr.str();
}
程序输出结果:
   $184.45     $7.00
    $59.13    $64.32
     $7.29  $1289.00
表 1 列出了可以与 C++ 流对象一起使用的 I/O 操作符列表,并给出了简要含义描述。

表 1 C++流对象
操作符 描 述
Dec 以十进制格式显示后续数字
endl 写入新行并冲刷输出流
fixed 使用固定点表示法表示浮点数
flush 冲刷输出流
hex 以十六进制输入或输出
left 左对齐输出
oct 以八进制输入或输出
right 右对齐输出
scientific 使用科学表示法表示浮点数
setfill(ch) 使用 ch 填充字符
setprecision(n) 将浮点精度设置为n
setw(n) 将输出字段的宽度设置为n
showbase 打印数字时显示基数(进制)
noshowbase 打印数字时不要显示基数(进制)
showpoint 强制显示小数点和尾随零
noshowpoint 如果可能的话,不打印结尾零和小数点
showpos 在非负数前面打印一个加号
noshowpos 在非负数前面不打印加号

前面我们已经介绍过表 1 中的部分操作符。oct、dec 和 hex 操作符可以用于输入和输出流。它们允许使用八进制、十进制或十六进制数字系统读取或写入数字。

下面的程序演示了如何使用 cin 和 cout 读取和写入十进制、十六进制和八进制值。
//This program demonstrates input and output of numbers
//using the octal, decimal, and hexadecimal number systems.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    int a, b;
    //Read two decimals and print hex and octal equivalents
    cout << "Enter two decimal numbers: ";
    cin >> a >> b;
    cout << "The numbers in decimal: " << a << '\t1' << b << endl;
    cout << "The numbers in hexadecimal: " << hex << showbase << a << '\t' << b << endl;
    cout << "The numbers in octal: " << oct << a << '\t' << b << endl;
    // Read some hexadecimals and print their decimal equivalents
    cout << "Enter two hexadecimal numbers:";
    cin >> hex >> a >> b;
    cout << "You entered decimal " << dec << a << '\t' << b << endl;
    // Read some octals and print their decimal equivalents
    cout << "Enter two octal numbers:";
    cin >> oct >> a >> b;
    cout << "You entered decimal " << dec << a << '\t' << b << endl;
    return 0;
}
程序输出结果为:

Enter two decimal numbers: 23 45
The numbers in decimal: 23      45
The numbers in hexadecimal: 0x17        0x2d
The numbers in octal: 027       055
Enter two hexadecimal numbers:17 2d
You entered decimal 23  45
Enter two octal numbers:27 55
You entered decimal 23 45

前面已经介绍过,当一个程序将数据写入一个打开的文件时,数据不会直接进入文件。相反,数据存储在与文件相关的输出缓冲区中,稍后在一个冲刷缓冲区的过程中才会传送到文件。通常情况下,如果缓冲区已满或文件关闭时,缓冲区才会被冲刷。endl 和 flush 操作符允许程序员随时冲刷缓冲区,从而强制将缓冲的数据传输到文件。

例如,以下语句将冲刷输出流的缓冲区:

outFile << flush;

scientific 操作符使得浮点数以科学计数法表示,即形式为 d.dddEdd。填充字符是当打印的数字未填满要打印的整个字段时写入的字符。默认情况下,填充字符为空。程序员可以使用 setfill 操作符来指定不同的填充字符。示例如下:

outFile << setfill ('%');

该语句将使用百分比字符(%)作为填充字符。