用 std::hex 读十六进制字符串时,别直接用 >> 操作符读取字符串,而应先用 std::stoi 或 std::stoul 配合基底 16 转换,或用 std::istringstream 配合 std::hex 格式化读取整数。

用 std::hex 读十六进制字符串时,别直接
很多人写成这样:std::cout ,然后想把输出重定向到文件——这得到的是 ASCII 字符串 "414243",不是字节 <code>0x41 0x42 0x43。真正要存 bin 文件,必须把数值按字节原样写入,而不是写它的十六进制表示文本。
正确做法:先解析字符串为整数,再逐字节提取写入 std::ofstream(binary 模式)
常见场景是处理类似 "414243" 或 "AB CD 0F" 这样的输入。关键步骤:
- 用
std::stoi或std::stoul配合base=16解析完整十六进制字符串(注意长度:4 字符 →uint16_t,8 字符 →uint32_t) - 或用
std::istringstream+std::hex逐字段读取(更安全,适合空格分隔) - 打开文件必须加
std::ios::binary标志,否则 Windows 下可能把0x0A换成0x0D 0x0A - 写入用
.write(reinterpret_cast<const char>(&val), sizeof(val))</const>,不能用
示例(处理空格分隔的字节):
std::istringstream iss("AB CD 0F");
unsigned int byte;
std::ofstream out("out.bin", std::ios::binary);
while (iss >> std::hex >> byte) {
char b = static_cast<char>(byte & 0xFF);
out.write(&b, 1);
}</char>
用 std::hex 控制输出格式?那是给“看”的,不是给“存”的
std::hex 只影响流的格式化输出行为,和底层数据存储无关。它会让 int x = 10 输出成 "a",但不会改变 x 的二进制值。bin 文件要的是原始字节,所以:
- 别在写文件前用
std::hex影响ofstream—— 它对.write()无作用 - 如果真需要调试输出十六进制值,单独用
std::cout -
std::setw和std::setfill只对格式化插入()生效,对 <code>.write()完全无效
容易漏掉的坑:字节序、大小写、非法字符、截断
十六进制字符串解析极易出错,尤其来自用户输入或配置文件时:
-
std::stoul("FFGG", nullptr, 16)不报错,但只解析到第一个非法字符,返回255(即 "FF")——建议用std::from_chars(C++17)做严格解析 - 字符串含大小写字母?
std::stoul和std::istringstream都支持,无需预处理 - 输入是大端还是小端?比如
"01020304"存成 4 字节,是按0x01 0x02 0x03 0x04还是反过来?取决于你的协议,代码里得显式控制字节顺序 - 单个字节写成
"0A"还是"A"?std::stoul能处理,但std::from_chars要求严格两位,得自己补零
最稳妥的解析方式(C++17+):
std::string_view sv = "AB";
unsigned char b;
auto [p, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), b, 16);
if (ec != std::errc()) { /* 解析失败 */ }
解析和写入逻辑一旦混合 std::hex 流控制与二进制 I/O,就容易把“显示格式”和“数据内容”搞混——这是最常被跳过的认知断层。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











