为什么 sscanf 忽略指定的宽度
Why does sscanf ignore the specified width?
我正在使用此代码将固定大小为 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 修复了它,该 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, "%02xn", (int)(b[i]));
}
}
预期输出为0123456789血型光盘英 孚0123456789血型光盘英 孚10111213
但是,使用 Visual Studio 2010 的实际输出是:
0123...光盘英 孚00000013
一开始你的代码有一个小问题。
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
说明符。
非常适合我:
#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, "%02xn", (int)(Bytes[i]));
}
}
用途:
> gcc gh.c
> ./a.out
01
23
45
67
89
ab
cd
ef
01
23
45
67
89
ab
cd
ef
我在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
$
请尝试使用编译器等构建和运行上述代码,以便我们查看它是否是可能的编译器/库错误,或者它是否是您代码中的其他问题。(你可能想要同时尝试调试版本和发布版本。
iostream 的 c++ 解决方案可能如下:
#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] << " ";
}
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 为什么在全局范围内使用"extern int a"似乎不行?
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 为什么会发生堆损坏
- 为什么使用 "this" 指针调用派生成员函数?
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么比较运算符如此快速
- 为什么 Serial.println(<char[]>);返回随机字符?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 为什么不;名字在地图上是按顺序排列的吗
- 我的字符计数代码计算错误.为什么
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 为什么 sscanf 忽略指定的宽度
- 为什么 sscanf 跳过每个字符串中的前 4 个字符
- 为什么sscanf不能正常工作与bool类型