【问题标题】:How to convert hex values inside a string into a actual byte如何将字符串中的十六进制值转换为实际字节
【发布时间】:2024-01-15 09:15:01
【问题描述】:

我需要将“FAFBFCFD”等字符串中包含的十六进制转换为数组或 uint32。

我试过这样的 sscanf:

uint8_t ns[4];
sscanf("FAFBFCFD", "%X%X%X%X", &ns[0], &ns[1], &ns[2], &ns[3]);

但我在数组中得到的只是 ff ff ff 7f

编辑:

就像@Clifford 所说,在这种情况下 sscanf 返回的值是一个 int ,如果你传递一个指向 uint8_t 的指针,程序就会崩溃。

【问题讨论】:

  • SO 中的正常做法是让您向我们展示您的尝试,然后您会得到帮助和建议——而不是免费的代码或家庭作业服务。
  • "转换为数组""转换为 uint32" 是两个非常不同的事情。所以第一步是决定你在做什么。
  • 提示:uint32_t digit = strchr(character, "0123456789abcdefABCDEF"); value = value - 6*(value > 15); 可以帮助转换单个数字。您还需要将各个数字组合为value = value * 16 + digit;,假设您从前面开始读取字符串。还要考虑,如果找不到字符,strchr 可能会返回 -1,即。 e.包含非法字符,因此您可能需要一些错误处理。
  • 从手册页中,%X 转换 “匹配可选带符号的十六进制整数;下一个指针必须是指向无符号整数的指针。” 所以有两个问题. 1) 第一个%X 将获取整个字符串。它不知道您只希望它读取 2 个字符。这可以通过指定最大宽度来解决,例如%2X2) 格式字符串后面的参数必须与格式字符串的要求相匹配。在您的情况下,所有指针都必须是指向 unsigned int 的指针,因为这是 %X 所要求的。
  • ns 需要先输入int,然后输入sscanf("FAFBFCFD", "%2X%2X%2X%2X", &ns[0], &ns[1], &ns[2], &ns[3]);,然后您可以根据需要将ns 元素转换为uint8_t。 IMO 关闭得太早了-您对问题的解决就足够了。我的回答使用循环将两个数字一次解析为一个临时 int,然后转换为一个 uint8_t 数组。允许它处理可变长度的字符串。如果它重新打开,我会发布它。

标签: c scanf


【解决方案1】:

启用编译器警告,您会发现它们在这种情况下非常有用。当我在 x64 GCC 11.1 上启用 -Wall -Wextra -pedantic-errors 时,我收到以下警告:

<source>:9:26: warning: format '%X' expects argument of type 'unsigned int *', but argument 3 has type 'uint8_t *' {aka 'unsigned char *'} [-Wformat=]
    9 |     sscanf("FAFBFCFD", "%X%X%X%X", &ns[0], &ns[1], &ns[2], &ns[3]);
      |                         ~^         ~~~~~~
      |                          |         |
      |                          |         uint8_t * {aka unsigned char *}
      |                          unsigned int *
      |                         %hhX

这让问题变得非常清楚。 %X 仅适用于 unsigned int *,但您的参数类型为 uint8_t *(又名 unsigned char *)。结果是未定义的行为。该警告还告诉您改用%hhx,但您还必须指定您只想为每个参数读取两个字符。因此,您对sscanf 的调用应如下所示:

sscanf("FAFBFCFD", "%2hhx%2hhx%2hhx%2hhx", &ns[0], &ns[1], &ns[2], &ns[3]);

此外,inttypes.h 中定义了一些宏,它们扩展为uintX_t/intX_t 类型的正确格式说明符,等等。所以你可以使用SCNx8 宏,它保证是uint8_t 的正确格式,而不是hhx

sscanf("FAFBFCFD",
       "%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"",
       &ns[0], &ns[1], &ns[2], &ns[3]);

虽然它确实让事情看起来有点难看......

【讨论】:

    最近更新 更多