这是我的当前代码:
//Input:hex string , 1234ABCDEEFF0505DDCC ....
//Output:BYTE stream
void HexString2Hex(/*IN*/ char* hexstring, /*OUT*/ BYTE* hexBuff)
{
for (int i = 0; i < strlen(hexstring); i += 2)
{
BYTE val = 0;
if (hexstring[i] < 'A')
val += 0x10 * (hexstring[i] - '0');
else
val += 0xA0 + 0x10 * (hexstring[i] - 'A');
if (hexstring[i+1] < 'A')
val += hexstring[i + 1] - '0';
else
val += 0xA + hexstring[i + 1] - 'A';
hexBuff[i / 2] = val;
}
}
问题是:当输入的十六进制字符串非常大时(例如长度为1000000),这个函数需要花费数百秒的时间,这对我来说是不可接受的。(CPU:i7-8700,3.2GHz。内存:32G)
那么,是否有任何替代算法可以更快地完成工作?
谢谢各位。
编辑1: 感谢Paddy的评论。 我太粗心了,没有注意到strlen(时间:O(n))被执行了数百次。 所以我的原始函数是O(n * n),这太糟糕了。
下面是更新后的代码:
int len=strlen(hexstring);
for (int i = 0; i < len; i += 2)
针对Emanuel P的建议,我尝试了一下,但效果似乎不太好。 以下是我的代码:
map<string, BYTE> by_map;
//init table (map here)
char *xx1 = "0123456789ABCDEF";
for (int i = 0; i < 16;i++)
{
for (int j = 0; j < 16; j++)
{
_tmp[0] = xx1[i];
_tmp[1] = xx1[j];
BYTE val = 0;
if (xx1[i] < 'A')
val += 0x10 * (xx1[i] - '0');
else
val += 0xA0 + 0x10 * (xx1[i] - 'A');
if (xx1[j] < 'A')
val += xx1[j] - '0';
else
val += 0xA + xx1[j] - 'A';
by_map.insert(map<string, BYTE>::value_type(_tmp, val));
}
}
//search map
void HexString2Hex2(char* hexstring, BYTE* hexBuff)
{
char _tmp[3] = { 0 };
for (int i = 0; i < strlen(hexstring); i += 2)
{
_tmp[0] = hexstring[i];
_tmp[1] = hexstring[i + 1];
//DWORD dw = 0;
//sscanf(_tmp, "%02X", &dw);
hexBuff[i / 2] = by_map[_tmp];
}
}
编辑2: 实际上,当我修复strlen错误时,我的问题已经解决了。 以下是我的最终代码:
void HexString2Bytes(/*IN*/ char* hexstr, /*OUT*/ BYTE* dst)
{
static uint_fast8_t LOOKUP[256];
for (int i = 0; i < 10; i++)
{
LOOKUP['0' + i] = i;
}
for (int i = 0; i < 6; i++)
{
LOOKUP['A' + i] = 0xA + i;
}
for (size_t i = 0; hexstr[i] != '\0'; i += 2)
{
*dst = LOOKUP[hexstr[i]] << 4 |
LOOKUP[hexstr[i + 1]];
dst++;
}
}
顺便说一下,非常感谢你们。你们真的很棒!是真正的研究人员!
strlen
函数。 - paddy_mm_cmpgt_epi8
或_mm_shuffle_epi8
一次处理16或32字节吗? 这对于 int->hex 字符串非常有效,可以参考 这里,同时也可以在其他方向上发挥作用。 - Peter CordeshexBuff
。这已经不是一堆16进制数字对了,这正是重点所在。它是打包的二进制数据流,这会更加混淆。 - Peter Cordesstd::map
的想法很好,但速度不太快。构建一个std::string
然后进行字母搜索有点慢。查找表真的应该是一个char nibbles[UCHAR_MAX]
。CPU 在这种指针算术方面非常擅长。 - MSaltersbyte b = (nibbles[char0] << 4) | nibbles[char1];
。 - Emanuel P