当前位置:首页 > 技术 > 正文内容

C++ 输出格式化技术详解

访客 技术 2026年6月19日 1

在 C++ 编程中,格式化输出是常见需求。本文将详细介绍三种主要的输出格式化方法:C 风格的 printf 函数、C++ 流式输出以及 C++20 的 std::format 库。特别关注不同进制(二进制、八进制、十进制、十六进制)的输出实现。

一、C 风格格式输出(兼容传统 C)

C 风格的格式输出通过 printf 函数实现,与 C 语言完全兼容。使用时需要包含 头文件。

常用格式说明符:

格式字符 功能描述 示例代码
%d 十进制整数 printf("数值: %d\n", 100);
%u 无符号十进制整数 printf("无符号: %u\n", 100);
%o 八进制表示 printf("八进制: %o\n", 100); // 输出 144
%x / %X 十六进制小写/大写 printf("十六进制: %x\n", 100); // 输出 64
%#o 带前缀的八进制 printf("带前缀八进制: %#o\n", 100); // 输出 0144
%#x / %#X 带前缀的十六进制 printf("带前缀十六进制: %#x\n", 100); // 输出 0x64
%f 浮点数默认格式 printf("浮点: %f\n", 3.14159);
%.2f 两位小数的浮点数 printf("两位小数: %.2f\n", 3.14159);
%e / %E 科学计数法 printf("科学计数: %e\n", 1000.0);
%g / %G 自动选择 %f 或 %e printf("自动格式: %g\n", 1000.0);

二进制输出实现

标准 C 库没有直接提供二进制格式输出,需要自定义函数:

// 自定义二进制输出函数
void display_binary(int num) {
if (num == 0) {
printf("0");
return;
}

char buffer[33]; // 足够存储32位整数的二进制表示
int position = 0;

// 从最低位开始处理
while (num > 0) {
buffer[position++] = (num & 1) ? '1' : '0';
num >>= 1;
}

// 反向输出结果
while (position--) {
putchar(buffer[position]);
}
}

二、C++ 流式输出(面向对象方法)

C++ 提供了面向对象的流式输出机制,主要使用 和 头文件。

进制控制

使用流操纵符控制输出进制:

#include
#include

int main() {
int number = 255;

// 默认十进制
std::cout << "十进制: " << number << std::endl;

// 设置十六进制输出
std::cout << "十六进制: " << std::hex << number << std::endl;

// 设置八进制输出
std::cout << "八进制: " << std::oct << number << std::endl;

// 显示进制前缀
std::cout << std::showbase;
std::cout << "带前缀十六进制: " << std::hex << number << std::endl;
std::cout << "带前缀八进制: " << std::oct << number << std::endl;

// 大写十六进制
std::cout << "大写十六进制: " << std::uppercase << std::hex << number << std::endl;

return 0;
}

二进制输出

使用 std::bitset 实现二进制输出:

#include
#include

void show_binary(int value, int width = 8) {
std::cout << std::bitset(value) << std::endl;
}

int main() {
int num = 42;
std::cout << "8位二进制: ";
show_binary(num, 8);

std::cout << "16位二进制: ";
show_binary(num, 16);

return 0;
}

浮点数格式化

#include
#include

int main() {
double pi = 3.1415926535;

// 默认输出
std::cout << "默认: " << pi << std::endl;

// 固定小数位数
std::cout << std::fixed << std::setprecision(2) << "两位小数: " << pi << std::endl;

// 科学计数法
std::cout << std::scientific << "科学计数: " << pi << std::endl;

return 0;
}

宽度与对齐控制

#include
#include

int main() {
int value = 123;

// 设置输出宽度
std::cout << "宽度8右对齐: " << std::setw(8) << value << std::endl;

// 设置填充字符
std::cout << "宽度8填充0: " << std::setfill('0') << std::setw(8) << value << std::endl;

// 左对齐
std::cout << "左对齐: " << std::left << std::setw(8) << value << std::endl;

return 0;
}

三、C++20 std::format(现代格式化方法)

C++20 引入了类似 Python 和 C# 的格式化库,提供了更简洁、更安全的格式化输出方式。

基本语法

#include
#include

int main() {
int number = 42;
double pi = 3.14159;

// 基本格式化
std::cout << std::format("十进制: {}\n", number);
std::cout << std::format("十六进制: {:x}\n", number);
std::cout << std::format("八进制: {:o}\n", number);
std::cout << std::format("二进制: {:b}\n", number);  // C++20新增

// 带前缀的格式
std::cout << std::format("带前缀十六进制: {:#x}\n", number);
std::cout << std::format("带前缀八进制: {:#o}\n", number);
std::cout << std::format("带前缀二进制: {:#b}\n", number);

// 宽度和对齐
std::cout << std::format("右对齐: {:>8}\n", number);
std::cout << std::format("左对齐: {:<8}\n", number);
std::cout << std::format("居中对齐: {:^8}\n", number);

// 浮点数格式
std::cout << std::format("两位小数: {:.2f}\n", pi);
std::cout << std::format("科学计数: {:e}\n", pi);

return 0;
}

常用格式说明符

格式说明符 功能描述 示例输出
{} 默认格式 42
{:d} 十进制 42
{:x} / {:X} 十六进制小写/大写 2a / 2A
{:o} 八进制 52
{:b} 二进制 101010
{:#x} 带前缀十六进制 0x2a
{:#o} 带前缀八进制 052
{:#b} 带前缀二进制 0b101010
{:5d} 宽度5右对齐 42
{:05d} 宽度5补零 00042
{:.2f} 两位小数 3.14
{:8.2f} 宽度8两位小数 3.14
{:e} 科学计数法 3.141590e+00

四、三种方法对比

特性 C风格 printf C++ 流式输出 C++20 std::format
类型安全
二进制支持 需自定义 使用 bitset 原生支持 {:b}
进制控制 %o/%x 操纵符 {:o}/{:x}
格式字符串 复杂 分散 集中
性能 中等
可读性 一般
C++标准要求 C++98 C++98 C++20

五、选择建议

  1. 遗留代码或性能关键场景:使用 C 风格的 printf
  2. 面向对象代码或类型安全要求高:使用 C++ 流式输出
  3. 现代 C++ 项目(C++20 可用):优先选择 std::format,它提供了最佳的可读性和类型安全性

二进制输出的通用解决方案

#include
#include

template
std::string create_binary_string(IntType value, bool with_prefix = false, int min_width = 0) {
if (value == 0) return with_prefix ? "0b0" : "0";

std::string result;
// 处理负数
if constexpr (std::is_signed_v && value < 0) {
value = -value;
result += '-';
}

// 转换为二进制字符串
while (value > 0) {
result.push_back((value & 1) ? '1' : '0');
value >>= 1;
}

// 反转字符串
std::reverse(result.begin(), result.end());

// 添加前缀
if (with_prefix) result = "0b" + result;

// 添加前导零以达到最小宽度
if (min_width > 0 && (int)result.size() < min_width + (with_prefix ? 2 : 0)) {
result = std::string(min_width + (with_prefix ? 2 : 0) - result.size(), '0') + result;
if (with_prefix) result.insert(2, "0b");
}

return result;
}

使用示例:

int main() {
int num = 42;
std::cout << create_binary_string(num, true, 8) << std::endl;  // 0b00101010
return 0;
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。