我正在使用此代码将固定大小为32的十六进制字符串转换为16字节的uint8数组。
const uint8_t* c = "0123456789abcdef0123456789abcdef";
uint8_t Bytes[16];
for (int i = 0; i < 16; i++) {
sscanf (&c[2*i], "%2hhx", &(Bytes[i]));
}
尽管hh
指定了1字节的目标宽度,但每步写入4个字节。因此,代码在缓冲区末尾写入3个字节。那是为什么?
(目前,我使用临时int修复它,并在每一步中复制到数组。)
重现:
#include <stdint.h>
#include <string>
void main (int argc, char* argv[])
{
const char* c = "0123456789abcdef0123456789abcdef";
uint8_t b[20];
for (int i = 0; i < 20; i++) {
b[i] = i;
}
for (int i = 0; i < 16; i++) {
sscanf (&c[2*i], "%2hhx", &(b[i]));
}
for (int i = 0; i < 20; i++) {
fprintf(stdout, "%02x\n", (int)(b[i]));
}
}
预期的产出是 01 23 45 67 89 AB 光盘 EF 01 23 45 67 89 AB 光盘 EF 10 11 12 13
但是,使用Visual Studio 2010的实际输出是:
01 23 ... 光盘 EF 00 00 00 13
答案 0 :(得分:4)
您的代码在开始时存在一个小问题。
const uint8_t* c = "0123456789abcdef0123456789abcdef";
在C ++中,未指定char
是signed
还是unsigned
。更确切地说,类型
char
,signed char
,unsigned char
是截然不同的,事实上你必须考虑到这一点
当重载函数和专门化模板时。
现在的代码是:
const char* c = "0123456789abcdef0123456789abcdef";
uint8_t Bytes[16];
for (int i = 0; i < 16; i++) {
sscanf (&c[2*i], "%2hhx", &(Bytes[i]));
}
让我们分析一下您的格式字符串:
2 : maximum field witdh to be read
hh : expecting a pointer to signed or unsigned char
x : means unsigned hex-input
(http://linux.die.net/man/3/scanf)
有了这些信息,到目前为止它看起来是正确的。
据我所知,在符合C99的库中没有问题 * 。
* :在这方面,MSVC库不支持hh
说明符。
答案 1 :(得分:1)
我在Mac OS X上使用gcc 4.2.1构建并运行以下代码:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
const char *c = "0123456789abcdef0123456789abcdef";
uint8_t b[20] = { 0 };
int i;
for (i = 0; i < 20; i++) {
b[i] = i;
}
for (i = 0; i < 16; i++) {
sscanf (&c[2*i], "%2hhx", &b[i]);
}
for (i = 0; i < 20; i++) {
printf("%02x", b[i]);
}
printf("\n");
return 0;
}
似乎表现得如预期:
$ gcc -v
...
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
$ gcc -Wall scanf_hex.c
$ ./a.out
0123456789abcdef0123456789abcdef10111213
$
请尝试使用编译器等构建并运行上述代码,以便我们可以查看它是否是可能的编译器/库错误,或者是否是代码中的其他问题。 (您可能希望尝试调试和发布版本。)
答案 2 :(得分:1)
完美适合我:
#include <stdio.h>
#include <stdint.h>
int main()
{
const char* c = "0123456789abcdef0123456789abcdef";
unsigned char Bytes[16];
int i;
for (i = 0; i < 16; i++)
{
sscanf (&c[2*i], "%2hhx", &(Bytes[i]));
}
for (i=0; i < 16; ++i)
{
fprintf(stdout, "%02x\n", (int)(Bytes[i]));
}
}
期运用:
> gcc gh.c
> ./a.out
01
23
45
67
89
ab
cd
ef
01
23
45
67
89
ab
cd
ef
答案 3 :(得分:1)
c ++解决方案 with iostream 可能如下:
#include<iostream>
#include<sstream>
#include<iomanip>
using namespace std;
//...
const char* c = "0123456789abcdef0123456789abcdef";
unsigned char Bytes[16];
stringstream s_in(c);
for (int i = 0; i < 16; i++)
{
string s;
s_in >> setw(2) >> s;
unsigned int t;
stringstream(s) >> hex >> t;
Bytes[i] = t;
}
注意,如果变量类型不是字符串,则s_in不希望服从setw(2)。 如果变量的类型为char,则宽度为1 ,因此从int转换。
测试它:
for (int i = 0; i < 16; i++)
{
cout << setfill('0') << setw(2) << hex << (int) Bytes[i] << " ";
}