如何在C中将十进制ascii字符串转换为整数数组?

时间:2021-02-17 15:58:37

I have written a program that works with IPv6 addresses, and I needed code that converts a four-integer array to decimal string that represented number of IPv6 addresses[1]. Now I ran into the situation when I need to do reverse: convert possibly large number (that do not fits into uint32_t or uint64_t, so atol() or strtol() are helpless here) represented as a single string to four-integer or byte (uint8_t) array (I converted function from [1] from 4-int to variable-uint8_t).

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

Is there any way to do that?

有没有办法做到这一点?

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

[1]如何在C中将128位整数转换为十进制ascii字符串?

Thanks. This is my first question here, so sorry for bad English if any.

谢谢。这是我的第一个问题,如果有的话,对不好的英语感到抱歉。

1 个解决方案

#1


0  

This is the kind of situation when using a library is recommended.

建议使用库时会出现这种情况。

Using GMP, you can do these conversions (gmp.c):

使用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;
} 

Output:

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

I tested this code on a 32 bit Linux system. Please pay attention to different int sizes and endianess on different platforms. You probably want the result in big endian, if so, just change mz_export to:

我在32位Linux系统上测试了这段代码。请注意不同平台上不同的int大小和endianess。您可能希望结果使用big endian,如果是这样,只需将mz_export更改为:

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

To compile the example, don't forget to install gmp and to add -lgmp -std=c99 on gcc command line parameters.

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

On Ubuntu, you can install gmp with:

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

sudo apt-get install libgmp-dev

And compile the example, gmp.c:

并编译示例,gmp.c:

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

This code can be a good start for your conversions. You can also initialize i to be a fixed 128 bit number (using init functions of GMP), just in case your big number starts with zeros.

此代码可以为您的转化提供良好的开端。您也可以将i初始化为固定的128位数字(使用GMP的初始化函数),以防您的大号以零开头。

#1


0  

This is the kind of situation when using a library is recommended.

建议使用库时会出现这种情况。

Using GMP, you can do these conversions (gmp.c):

使用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;
} 

Output:

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

I tested this code on a 32 bit Linux system. Please pay attention to different int sizes and endianess on different platforms. You probably want the result in big endian, if so, just change mz_export to:

我在32位Linux系统上测试了这段代码。请注意不同平台上不同的int大小和endianess。您可能希望结果使用big endian,如果是这样,只需将mz_export更改为:

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

To compile the example, don't forget to install gmp and to add -lgmp -std=c99 on gcc command line parameters.

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

On Ubuntu, you can install gmp with:

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

sudo apt-get install libgmp-dev

And compile the example, gmp.c:

并编译示例,gmp.c:

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

This code can be a good start for your conversions. You can also initialize i to be a fixed 128 bit number (using init functions of GMP), just in case your big number starts with zeros.

此代码可以为您的转化提供良好的开端。您也可以将i初始化为固定的128位数字(使用GMP的初始化函数),以防您的大号以零开头。