最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
C++ 如何对字符串进行高效十六进制编码
时间:2026-06-19 08:31:03 编辑:袖梨 来源:一聚教程网
std::hex不能直接用于字符串编码,因其仅为I/O流操纵器,仅作用于整数输出;字符串需手动逐字节转十六进制,且必须用unsigned char强转以防符号扩展越界。
为什么 std::hex 不能直接用于字符串编码
因为 std::hex 是 I/O 流操纵器,只影响整数类型的格式化输出,对 std::string 或 char 数组无作用。直接写 std::cout 会输出地址(隐式转为指针),不是你想要的每个字节的十六进制表示。
用 std::format(C++20)最简洁安全
C++20 的 std::format 支持逐字节格式化,自动处理宽度、大小写和分隔,且不依赖流状态,线程安全:
std::string hex_encode(const std::string& s) { std::string out; out.reserve(s.size() * 2); // 预分配避免多次 realloc for (unsigned char c : s) { out += std::format("{:02x}", c); // 小写、两位、补零 } return out;}
-
{:02x}:固定宽度 2,小写十六进制,不足补零;换成{:02X}得大写 - 不推荐
std::format("{}", c)—— 默认不补零,单字节可能输出 "a" 而非 "0a" - 若项目未启用 C++20,
std::format不可用,需降级方案
兼容 C++11 的手动查表法最快
查表法避免格式化开销,也绕过 std::stringstream 的构造/析构成本,实测比流式方法快 3–5 倍:
static constexpr char hex_chars[] = "0123456789abcdef";std::string hex_encode(const std::string& s) { std::string out(s.size() * 2, ' '); for (size_t i = 0; i < s.size(); ++i) { unsigned char c = static_cast<unsigned char>(s[i]); out[2*i] = hex_chars[c >> 4]; out[2*i + 1] = hex_chars[c & 0x0F]; } return out;}
- 必须用
unsigned char强转:否则负值 char(如 xFF)会符号扩展成大整数,查表越界 - 预设
out容量并用空格初始化,避免 push_back 动态增长开销 - 大写表用
"0123456789ABCDEF",别混用大小写
用 std::stringstream 容易踩的坑
虽可工作,但默认行为极易出错:
立即学习“C++免费学习笔记(深入)”;
std::stringstream ss;ss << std::hex << std::setfill('0');for (unsigned char c : s) { ss << std::setw(2) << static_cast<int>(c);}return ss.str();
- 漏掉
std::setfill('0')→ 补空格而非 '0' - 漏掉
std::setw(2)→ 单字节输出 "a" 而非 "0a" - 漏掉
static_cast<int>(c)</int>→ 输出字符本身(如 '@')而非其 ASCII 码 - 流状态(
std::hex,std::setw)是全局的,多线程下需加锁或改用局部流
查表法没有状态污染,也没有隐式类型转换风险,复杂场景下更值得优先考虑。
相关文章
- 刀剑缭乱2026公测兑换码大全一览 07-05
- 崩坏星穹铁道4.0卡池7个新角色一览 07-05
- 明日方舟终末地开服工业蓝图一览 工业蓝图作用与使用思路解析 07-05
- 原神梦之树怎么开启 梦之树开启条件 07-05
- 帕瓦勇者传说持续伤害阵容搭配推荐 07-05
- 明日方舟:终末地全新玩法 蚀像寻遗怎么玩介绍 07-05