std::stoi转十六进制字符串最快但需显式指定基数16,含"0x"前缀时应截取或用std::stoul(s,nullptr,0)自动识别;多值空格分隔用std::stringstream配合std::hex;字节序列转十六进制字符串需逐字节格式化。

std::stoi 转十六进制字符串为整数
直接用 std::stoi 最快,但必须确保输入格式合法(如 "FF"、"0xFF" 或带空格前缀的字符串)。它默认按十进制解析,所以得显式传入基数 16:
std::string s = "FF"; int val = std::stoi(s, nullptr, 16); // 得到 255
常见错误是漏掉第三个参数 16,结果当成十进制解析,"FF" 就会抛 std::invalid_argument;另外,如果字符串含前缀 "0x",std::stoi 默认不识别(除非用 0 作基数让其自动推断),所以建议统一去掉前缀或手动处理:
- 输入含
"0x":先用s.substr(2)截掉,再传给std::stoi(..., 16) - 不确定是否含前缀:用
std::stoul(s, nullptr, 0),0表示自动识别进制(支持0x、0X、无前缀十六进制) - 输入可能超
int范围:改用std::stoul或std::stoull,避免溢出未定义行为
std::stringstream 处理带空格/混合格式的十六进制字符串
当输入是类似 "FF 0A 1B" 这种空格分隔的多个十六进制值,或需要逐字段解析时,std::stringstream 更灵活:
std::string s = "FF 0A 1B";
std::stringstream ss(s);
unsigned int val;
while (ss >> std::hex >> val) {
// val 依次为 255, 10, 27
}
注意点:
立即学习“C++免费学习笔记(深入)”;
-
std::hex是流操纵符,只影响后续读取,不是一次性设置整个流 - 若字符串含非法字符(如
"FF G1"),读取到G时流会进入失败状态(ss.fail()为 true),需手动ss.clear()并跳过坏字符 - 默认读取的是
int,大写/小写十六进制字母都支持,但不能混用前缀(比如"0xFF 0A"中的0xFF会被当作三个 token:"0"、"FF")
从字节序列(如 vector)转十六进制字符串
这不是“字符串转整数”,而是反过来——常用于日志、网络协议调试。别用 std::to_string,它输出十进制。正确做法是逐字节格式化:
std::vector<uint8_t> data = {0xFF, 0x0A, 0x1B};
std::ostringstream oss;
for (uint8_t b : data) {
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(b);
}
std::string hex_str = oss.str(); // "ff0a1b"
关键细节:
- 必须把
uint8_t强转成int,否则std::ostream会把它当字符输出(0xFF变成ÿ) -
std::setw(2)和std::setfill('0')确保每个字节占两位,避免"a"这种单字符 - 如需大写,加
oss ;如需加 <code>"0x"前缀,手动拼接即可
边界与兼容性问题:非 ASCII 字符、locale、C++ 标准版本
所有上述方法在 C++11 及以上都可用,但有隐含依赖:
-
std::stoi在 C++11 引入,旧编译器(如 GCC 4.6 以前)不支持,需用strtol - 如果程序设置了非默认 locale(如中文 locale),
std::stringstream的>>可能因空格判定异常而提前截断,建议显式ss.imbue(std::locale::classic()) - 十六进制字母大小写不敏感,但某些嵌入式环境或自定义解析器可能只认小写,生产中建议统一转小写后再解析
- 空字符串、全空白字符串传给
std::stoi会抛异常,务必先!s.empty() && s.find_first_not_of(" \t\n\r") != std::string::npos检查
最易被忽略的是符号位处理:std::stoi("FF", ..., 16) 返回的是有符号 int,而 0xFF 对 int8_t 是 -1,但对 int 是 255 —— 解析结果类型由目标变量决定,不是原始字节含义。











