You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++将长十六进制字符串解析为std::vector<uint8_t>的异常问题

十六进制字符串转std::vector<uint8_t>的问题解决

我想用C++将长十六进制字符串分割为单个字节并存入std::vector<uint8_t>。例如输入字符串09e1c5f70a65ac519458e7e53f36,期望得到的std::vector<uint8_t>内容为{0x09, 0xe1, 0xc5, 0xf7, 0x0a, 0x65, 0xac, 0x51, 0x94, 0x58, 0xe7, 0xe5, 0x3f, 0x36},输出格式应为09 e1 c5 f7....,但实际输出仅得到字节值的一半,比如0 e c f.....。不想使用Boost库,我使用的代码如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>

int main(void)
{
    std::string in("09e1c5f70a65ac519458e7e53f36");
    size_t len = in.length();
    std::vector<uint8_t> out;
    for(size_t i = 0; i < len; i += 2) {
        std::istringstream strm(in.substr(i, 2));
        uint8_t x;

        strm >> std::hex >> x;
        out.push_back(x);

    }
    for (int i=0; i<out.size(); ++i)
    std::cout << out[i] << ' ';

    return 0;
}

问题原因

核心问题在于uint8_t的类型特性:它本质是unsigned char的别名。当用std::istringstream配合std::hex读取时,流会将其视为字符类型而非整数类型,因此只会读取十六进制子串的第一个字符,而非解析整个两位字符串为字节值。比如读取"09"时,只会取'0'对应的ASCII值0;读取"e1"时取'e'对应的ASCII值101,最终导致输出结果不符合预期。

另外,直接用std::cout输出uint8_t时,会将其当作字符输出(比如0x09是制表符、0xe1是不可见控制字符),这也会让你看到错误的输出表现。

解决方案

方法1:用整数类型中转解析

先将十六进制子串读取到更大的整数类型(比如unsigned int),再转换为uint8_t存入容器:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>

int main(void)
{
    std::string in("09e1c5f70a65ac519458e7e53f36");
    size_t len = in.length();
    std::vector<uint8_t> out;
    for(size_t i = 0; i < len; i += 2) {
        std::istringstream strm(in.substr(i, 2));
        unsigned int temp;
        strm >> std::hex >> temp;
        out.push_back(static_cast<uint8_t>(temp));
    }
    // 正确输出十六进制格式
    for (auto byte : out) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') 
                  << static_cast<int>(byte) << ' ';
    }
    return 0;
}

方法2:手动解析十六进制字符(更高效)

跳过字符串流,直接通过位运算将两位十六进制字符转换为字节,适合处理长字符串:

#include <iostream>
#include <string>
#include <vector>
#include <iomanip>

uint8_t hex_char_to_byte(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
    if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
    // 非法字符处理,可根据需求抛出异常或返回默认值
    return 0;
}

int main(void)
{
    std::string in("09e1c5f70a65ac519458e7e53f36");
    size_t len = in.length();
    std::vector<uint8_t> out;
    out.reserve(len / 2); // 预分配空间提升效率
    for(size_t i = 0; i < len; i += 2) {
        uint8_t byte = (hex_char_to_byte(in[i]) << 4) | hex_char_to_byte(in[i+1]);
        out.push_back(byte);
    }
    // 正确输出十六进制格式
    for (auto byte : out) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') 
                  << static_cast<int>(byte) << ' ';
    }
    return 0;
}

两种方法都能正确生成目标std::vector<uint8_t>,且无需依赖Boost库。

内容的提问来源于stack exchange,提问作者Vijayakumar Sargunam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:30:12