Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C语言中将`int`数组转换为IP地址字符串?_C - Fatal编程技术网

如何在C语言中将`int`数组转换为IP地址字符串?

如何在C语言中将`int`数组转换为IP地址字符串?,c,C,我有一个int数组,它存储一个IP地址: int ipArr[4] = {192,168,1,60} 我需要将上面定义的地址转换为类似于“192.168.1.60”的字符串。我尝试了sprintf和strcat函数,但代码仍然非常繁琐。处理句点标点是非常棘手的。 我的代码如下: char srcIp[16]; int i=0,index=0; for(i=0;i<4;i++){ index+=sprintf(&srcIp[index],"%d",sourceIpInt[i]

我有一个
int
数组,它存储一个IP地址:

int ipArr[4] = {192,168,1,60}
我需要将上面定义的地址转换为类似于
“192.168.1.60”
的字符串。我尝试了
sprintf
strcat
函数,但代码仍然非常繁琐。处理句点标点是非常棘手的。 我的代码如下:

char srcIp[16];
int i=0,index=0;
for(i=0;i<4;i++){
   index+=sprintf(&srcIp[index],"%d",sourceIpInt[i]);
   if(i<3){
      index+=sprintf(&srcIp[index],"%c",'.');
    }
}
charsrcip[16];
int i=0,索引=0;

对于(i=0;i而言,使用单个
sprintf()
在一次调用中格式化所有ip地址八位字节比在循环中格式化更简单、更容易

如果缓冲区可以是局部变量

char缓冲区[16];
const int ip[4]={172,0,0,1};
sprintf(缓冲区,“%d.%d.%d.%d”,*ip,ip[1],ip[2],ip[3]);
printf(“IP地址为:%s”,缓冲区);
或者,如果您需要使用动态内存,您可以执行以下操作

char*buffer=malloc(16);
const int ip[4]={172,0,0,1};
如果(!缓冲区){
佩罗尔(“马洛克”);
出口(1);
}
sprintf(缓冲区,“%d.%d.%d.%d”,*ip,ip[1],ip[2],ip[3]);
printf(“IP地址为:%s”,缓冲区);
自由(缓冲);
在上面的代码中,我使用动态内存分配来创建缓冲区,并使用
sprintf
将数据写入缓冲区


请注意
malloc(16)
-
sizeof(char)
根据定义等于
1
,因此我们不需要编写
malloc(sizeof(char)*16)

更好的方法是使用可移植库函数

它将:

  • 通过添加对IPv6的支持,使您的代码经得起未来的考验
  • 使您的代码与使用IP地址的许多其他函数兼容
例如:

#include <stdio.h> 
#include <string.h>
#include <arpa/inet.h> 

void main(){
  // IP addresses might be longer on this system eg. see https://stackoverflow.com/questions/55958327/how-to-convert-an-int-array-to-an-ip-address-string-in-c
  char str[INET_ADDRSTRLEN];

  // this "socket address" is a very portable address format which you will use when dealing with sockets
  struct sockaddr_in sa;

  // this format is not portable or usable when dealing with other libaries, unless you convert it
  // note that technically 'unsigned char' is more accurate, but it will be processed slower than int on modern PC's
  unsigned char a_ipv4addr[4] = {192,168,1,60};

  // Don't do this! This will only work on little-endian machines, when compiled without certain optimizations - so it's not portable. That's why you should rather use the functions - some day soon you might want your code to run on a RISC V processor...
  memcpy(&sa.sin_addr.s_addr,&a_ipv4addr,4);
  inet_ntop(AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN);
  printf("Bad example with memcpy: %s\n", str); 

  // sprintf your address, and then convert it - if you absolutely have to use your format
  sprintf(str,"%i.%i.%i.%i",a_ipv4addr[0],a_ipv4addr[1],a_ipv4addr[2],a_ipv4addr[3]);
  inet_pton(AF_INET, str, &(sa.sin_addr)); // now you can use it in other functions
  inet_ntop(AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN); // just to show that it's correct
  printf("Better example from generated string: %s\n", str); 

  // you can also represent it as an unsigned int
  unsigned int ipv4addr=0x3c01a8c0; // c0.a8.01.3c = 192.168.1.60 backwards aka little-endian
  sa.sin_addr.s_addr=ipv4addr;
  inet_ntop(AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN);
  printf("Example from unsigned int: %s\n", str);

  // you can also represent it as an unsigned int, in decimal
  ipv4addr=192+(168<<8)+(1<<16)+(60<<24);
  sa.sin_addr.s_addr=ipv4addr;
  inet_ntop(AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN);
  printf("Example from unsigned int decimal example: %s\n", str);

  // Or just store it as a string to begin with...
  inet_pton(AF_INET, "9.9.9.9", &(sa.sin_addr));
  // or if you read it from another function, you can convert it back and print it
  inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);
  printf("Example from string: %s\n", str); // prints "9.9.9.9"

}

学习更多!

如您所知,一小段示例代码将有助于查看您已经尝试过的内容。请显示代码并解释UNIX系统中的繁琐或棘手之处,您可能需要考虑修改代码以使用<代码> iNETNtoA < /COD>及其亲属。您需要以不同的格式输入。(压缩为32位整数,而不是整数数组),但标准化的代码可能更健壮。sprintf就是这样做的。是的,代码会很麻烦,因为在C中处理字符串很麻烦。习惯它吧。@LeeDanielCrocker我认为;当代码编写正确时,理解它就没有问题了。我不是反对票,但可能是因为一些吹毛求疵的事情s、 例如:使用
sprintf
中的指针寻址或索引(所有
*ip
或所有
ip[n]
)执行
malloc(16*sizeof(char))
,可读性更高。@anonmes
sizeof(char)
的定义是1.
*ip
更短。
char
有一个字节大;唯一可以改变的是char中的位数,用
char\u-BIT
表示。数组寻址只是一种同步糖,从
a[n]
*(a+n)
所以这真的没什么区别。我知道,这只是一个好习惯,特别是对刚开始学习的人来说C@user3386109:
sizeof(char)当以前使用的
char
代码被更改为
wchar\u t
int
或其他内容时,
是有利的,因为进行更改的人可以搜索出现
char
的位置,并决定是否需要更改。他们不能轻易地搜索
1会出现,尤其是在写入
malloc(16*1)
后,即使该代码已被删除
malloc(16)
。不使用“幻数”的规则适用:在从foo到bar的转换代码中,不应写入
12
。1是基本数并不意味着它……不是“幻数”对于
sizeof(char)
。编写代码的一部分应该是为了向读者表达意义,而
sizeof(char)
向读者表示程序员正在为
char
对象分配空间。如果代码只是说
malloc(16)
,那么它是否丢失显然不仅仅是因为这个原因
。但是如果上面写的是
malloc(16*sizeof(char))
,你可以看到它的意图。它们不是无处不在吗?不是吗:?另外,我不知道IP.ToString…太好了!但是它与他的数组格式兼容吗?
man inet_addr