【问题标题】:How to convert a decimal ascii string to integer array in C?如何将十进制ascii字符串转换为C中的整数数组?
【发布时间】:2012-09-28 23:46:06
【问题描述】:

我编写了一个处理 IPv6 地址的程序,我需要将四整数数组转换为表示 IPv6 地址数量的十进制字符串的代码[1]。现在我遇到了需要做反向的情况:将可能很大的数字(不适合uint32_tuint64_t,所以atol()strtol()在这里无能为力)表示为单个字符串到四个-integer 或 byte (uint8_t) 数组(我将函数从 [1] 从 4-int 转换为 variable-uint8_t)。

有什么办法吗?

[1]How to convert a 128-bit integer to a decimal ascii string in C?

谢谢。这是我在这里的第一个问题,如果有英语不好,请见谅。

【问题讨论】:

  • 关于将 ip 地址转换为字符串以及其他方式,请参阅 inet_ntopinet_pton
  • 嗯,不,inet_ntop() 在这里也不适用;我输入了一个表示为字符串的十进制数,例如“188647402”或“65536”,我需要像 strtol() 那样进行转换,但数字大于 uint32_t 或 uint64_t 可以存储(所以我需要一个数组将值存储到的整数,如 [1] 或 uint8_t 数组,如 inet_pton() 所做的)。简单来说,我需要[1],但是反向操作。

标签: c string int ascii int128


【解决方案1】:

这是推荐使用库时的那种情况。

使用GMP,您可以进行这些转换(gmp.c):

#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

int main(int argc, char *argv)
{
  // From string
  char *s ="199999999999999999999999999999999999999";
  mpz_t i;
  // To big number, using GMP
  // 10 here means base 10.
  mpz_init_set_str(i, s, 10);
  // Just to test if s is 128 bits long
  printf("%s can be represented with %d digits in base 2\n",s, mpz_sizeinbase(i, 2));
  // Then you can print it in hex
  gmp_printf("%#32ZX\n", i);
  // Or convert it back to int[4]
  unsigned int a[4];
  mpz_export(&a, NULL, 1, 4, 0, 0, i);
  for(int x=0;x<4;x++)
      printf("%X\n", a[x]); 
  mpz_clear(i);
  return 0;
} 

输出:

199999999999999999999999999999999999999 can be represented with 128 digits in base 2
0X96769950B50D88F41314447FFFFFFFFF
96769950
B50D88F4
1314447F
FFFFFFFF

我在 32 位 Linux 系统上测试了这段代码。请注意不同平台上不同的 int 大小和字节序。 您可能想要大端的结果,如果是这样,只需将 mz_export 更改为:

mpz_export(&a, NULL, 1, 4, 1, 0, i);

要编译示例,别忘了安装 gmp 并在 gcc 命令行参数上添加 -lgmp -std=c99。

在 Ubuntu 上,您可以使用以下命令安装 gmp:

sudo apt-get install libgmp-dev

并编译示例,gmp.c:

gcc gmp.c -o gmp -lgmp -std=c99

此代码可以成为您转化的良好开端。您还可以将 i 初始化为一个固定的 128 位数字(使用 GMP 的 init 函数),以防万一您的大数字以零开头。

【讨论】:

  • 也许我别无选择,但我仍然认为对一个小程序的 gmp 依赖有点矫枉过正。不过谢谢你的详细解释!
  • 也许最好的办法是完全避免这个非常长的十进制数。如果您将规范更改为接受十六进制数字,那么您只需将其作为字符串处理,转换就变得很简单了。无论如何,是谁生成了这么长的十进制数?
  • 我尝试将命令行指定的特定地址范围内的 ip(v6) 地址的子网输出为 address+n,其中 n 是该数字。我最好从程序中完全删除此类功能,或者按照您的建议实现它 - 传递十六进制数而不是十进制数。
猜你喜欢
  • 2011-12-22
  • 2021-03-04
  • 2017-06-10
  • 1970-01-01
  • 2022-01-09
  • 2022-01-09
  • 2019-01-08
  • 2015-11-29
相关资源
最近更新 更多