c++ - 在 C++ 中将 vector<string> 转换为 unsigned char 数组

标签 c++ arrays vector char type-conversion

我有一个包含一些值的字符串 vector 。这些值应该是十六进制字节,但作为字符串存储在此 vector 中。 这些字节实际上是从一个文本文件中读取的,就像这样:

(文本文件的内容)

<jpeg1>
0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x60
</jpeg1>

到目前为止,我的代码所做的是,它开始读取 {JPEG1} 标记之后的行,直到 {/jpeg1} 标记,然后使用逗号 ' ,' 作为分隔符,它将字节存储到字符串 vector 中。

拆分字符串后,此时 vector 存储的值如下:

vector<string> myString = {"0xFF", "0xD8", "0xFF", "0xE0", "0x00", "0x10", "0x4A", "0x46", "0x49", "0x46", "0x00", "0x01", "0x01", "0x01", "0x00", "0x60"};

        and if i print this i get the following:
            0: 0xFF
            1: 0xD8
            2: 0xFF
            3: 0xE0
            4: 0x00
            5: 0x10
            6: 0x4A
            7: 0x46
            8: 0x49
            9: 0x46

我想要的是,我想将这些字节存储在一个无符号字符数组中,这样每个元素都被视为一个 HEX 字节而不是一个字符串值。

最好是这样的:

     unsigned char myHexArray[] = {0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x60};

        if i print this i get:
            0:  
            1: ╪
            2:  
            3: α
            4:
            5: 
            6: J
            7: F
            8: I
            9: F

已解决!
感谢你们的帮助,到目前为止“ranban282”解决方案对我有用,我也会尝试其他用户提供的解决方案。

最佳答案

我什至不会浏览 std::vector<std::string>阶段,你不需要它,它无缘无故地浪费了很多分配;只需将字符串解析为“在线”字节。

如果您已经有一个 istream对于您的数据,您可以直接从中解析它,尽管我对它的性能有过糟糕的体验。

// is is some derived class of std::istream
std::vector<unsigned char> ret;
while(is) {
    int val = 0;
    is>>std::hex>>val;
    if(!is) {
        break; // failed conversion; remember to clean up the stream
               // if you need it later!
    }
    ret.push_back(val);
    if(is.getc()!=',') break;
}

如果相反,您将它放在一个字符串中——从 XML 文件中提取数据时经常发生这种情况,您可以使用 istringstream 来解析它。和上面的代码(一个额外的字符串拷贝+通常很慢),或者使用例如直接从字符串中解析它sscanf%i ;假设你的字符串在 const char *sz 中:

std::vector<unsigned char> ret;
for(; *sz; ++sz) {
    int read = 0;
    int val = 0;
    if(sscanf(sz, " %i %n", &val, &read)==0) break; // format error
    ret.push_back(val):
    sz += read;
    if(*sz && *sz != ',') break; // format error
} 
// now ret contains the decoded string

如果你确定字符串总是十六进制的,不管 0x前缀,并且该空格不存在 strtol效率更高,IMO 更好用:

std::vector<unsigned char> ret;
for( ;*sz;++sz) {
    char *endp;
    long val = strtol(sz, &endp, 16);
    if(endp==sz) break; // format error
    sz = endp;
    ret.push_back(val);
    if(*sz && *sz!=',') break; // format error
}

如果 C++17 可用,您可以使用 std::from_chars而不是 strtol消除语言环境废话,这可能会破坏您的解析功能(尽管这对于浮点解析更为典型)并且无缘无故地减慢速度。

OTOH,如果性能很关键但是from_chars不可用(或者如果它可用但你测量它很慢),手动滚动整个解析器可能是有利的。

auto conv_digit = [](char c) -> int {
    if(c>='0' && c<='9') return c-'0';
    // notice: technically not guaranteed to work;
    // in practice it'll work on anything that doesn't use EBCDIC
    if(c>='A' && c<='F') return c-'A'+10;
    if(c>='a' && c<='f') return c-'a'+10;
    return -1;
};
std::vector<unsigned char> ret;
for(; *sz; ++sz) {
    while(*sz == ' ') ++sz;
    if(*sz!='0' || sz[1]!='x' || sz[1]!='X') break; // format error
    sz+=2;
    int val = 0;
    int digit = -1;
    const char *sz_before = sz;
    while((digit = conv_digit(*sz)) >= 0) {
        val=val*16+digit; // or, if you prefer: val = val<<4 | digit;
        ++sz;
    }
    if(sz==sz_before) break; // format error
    ret.push_back(val);
    while(*sz == ' ') ++sz;
    if(*sz && *sz!=',') break; // format error
}

关于c++ - 在 C++ 中将 vector<string> 转换为 unsigned char 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43464922/

相关文章:

javascript - 用这个字符: "\"分割

c++ - vector 元素似乎没有连续存储

java - 我们如何在 Java 中定义函数 vector ,让函数记住它们的参数?

c++ - C/C++ 中的线程,任何标准?

c++ - 为什么我会用完堆内存?

c++ - C++ 中用户定义的 CUDA 代码

css - 为什么有 std::vector 的迭代器

c# - 局域网连接开启或关闭

java - 使用java for循环恢复int数组

PHP - 将字符串添加到数组