【STL】iostream 编程:字符串和 I/O 格式化


本文介绍一下 iostream 编程中的字符串和 I/O 格式化,并给出两个示例便于理解。


目录

  • [1 概述](#1 概述)
  • [2 示例](#2 示例)
  • [3 其他格式化方案](#3 其他格式化方案)
  • [4 综述](#4 综述)

1 概述

C++ 的 <iostream> 库提供类、函数与运算符来实现格式化字符串输入输出

2 示例

以下代码演示如何设置 cout 以将整数格式化为十六进制中的输出。

cpp 复制代码
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    ios state(nullptr);

    cout << "The answer in decimal is: " << 42 << endl;

    state.copyfmt(cout); // save current formatting
    cout << "In hex: 0x" // now load up a bunch of formatting modifiers
        << hex
        << uppercase
        << setw(8)
        << setfill('0')
        << 42            // the actual value we wanted to print out
        << endl;
    cout.copyfmt(state); // restore previous formatting
}

运行结果:

cout 的格式标记会一直生效,不会只作用于单行代码。因此在切换进制、对齐、填充字符之前,必须先保存流状态,使用完毕再恢复原状。

这种流操纵方式类型安全、扩展性强,但是代码冗长繁琐。

3 其他格式化方案

  1. 方案一:使用第三方库 Boost.Format(不属于 C++标准)
    Boost.Format 的优点:
    • 安全:类型严格校验,参数数量不匹配时直接抛出异常;
    • 可扩展:支持所有能够流式输出的自定义类型;
    • 简洁:兼容 POSIX 风格的格式化字符串;

Boost.Format 底层仍然基于 iostream 实现,安全灵活,但没有做极致性能优化。

  1. 方案二:追求极致性能时,可以选用 C语言的 printf、sprintf。
  • 它们执行速度快、写法简洁;
  • 缺点是不支持自定义类型,并且存在缓冲区溢出漏洞;
  • 微软提供了安全版本 sprintf_s,安全性更高,只略微损失一点性能;

4 综述

  1. std::cout 格式化痛点
    • 格式全局持久有效,每次修改都要保存 + 恢复现场,样板代码太多;
  2. 三类方案取舍
    • iostream:安全、支持自定义类型,写法啰嗦;
    • Boost.Format:语法简洁、带类型安全校验,非标准、性能一般;
    • C printf:速度最快,不安全,不支持 C++ 对象;
  3. 现代 C++ 新标准解决方案
    • C++20 正式引入 std::format,兼顾语法简洁、类型安全、高性能,是对以上几种方案的整合优化;