整数到IP地址-C

整数到IP地址-C,c,string,ip-address,C,String,Ip Address,我正在准备一个小测验,我强烈怀疑我可能要执行这样一个功能。基本上,给定一个网络表示法中的IP地址,我们如何将它从一个32位整数转换成点十进制表示法中的字符串(类似于155.247.182.83)。。。?显然,我们也不能使用任何类型的inet函数……我被难住了 提示:将32位整数分解为4个8位整数,然后打印出来 与此类似的内容(未编译,YMMV): 这里有一个简单的方法:(ip>>8)、(ip>>16)和(ip>>24)将第二、第三和第四个字节移到低阶字节中,而&0xFF在每一步中分离最低有效字节

我正在准备一个小测验,我强烈怀疑我可能要执行这样一个功能。基本上,给定一个网络表示法中的IP地址,我们如何将它从一个32位整数转换成点十进制表示法中的字符串(类似于155.247.182.83)。。。?显然,我们也不能使用任何类型的inet函数……我被难住了

提示:将32位整数分解为4个8位整数,然后打印出来

与此类似的内容(未编译,YMMV):


这里有一个简单的方法:
(ip>>8)
(ip>>16)
(ip>>24)
将第二、第三和第四个字节移到低阶字节中,而
&0xFF
在每一步中分离最低有效字节

void print_ip(unsigned int ip)
{
    unsigned char bytes[4];
    bytes[0] = ip & 0xFF;
    bytes[1] = (ip >> 8) & 0xFF;
    bytes[2] = (ip >> 16) & 0xFF;
    bytes[3] = (ip >> 24) & 0xFF;   
    printf("%d.%d.%d.%d\n", bytes[3], bytes[2], bytes[1], bytes[0]);        
}
有一个隐含的
字节[0]=(ip>>0)&0xFF在第一步

使用
snprintf()
将其打印为字符串。

另一种方法:

union IP {
    unsigned int ip;
    struct {
      unsigned char d;
      unsigned char c;
      unsigned char b;
      unsigned char a;
    } ip2;
};

...
char  ips[20];
IP ip;
ip.ip = 0xAABBCCDD;

sprintf(ips, "%x.%x.%x.%x", ip.ip2.a, ip.ip2.b, ip.ip2.c, ip.ip2.d);
printf("%s\n", ips);

如果传递一个字符串缓冲区来填充,并且我知道缓冲区足够大(即至少16个字符长),我会这样做:

这将比首先创建字节数组稍微快一点,而且我认为它更可读。我通常会使用snprintf,但IP地址的长度不能超过16个字符,包括终止null

或者,如果要求我使用返回char*的函数:

char* IPAddressToString(int ip)
{
  char[] result = new char[16];

  sprintf(result, "%d.%d.%d.%d",
    (ip >> 24) & 0xFF,
    (ip >> 16) & 0xFF,
    (ip >>  8) & 0xFF,
    (ip      ) & 0xFF);

  return result;
}
#包括“stdio.h”
无效打印ip(内部ip){
无符号字符字节[4];
int i;
对于(i=0;i>i*8)&0xFF;
}
printf(“%d.%d.%d.%d\n”,字节[3],字节[2],字节[1],字节[0]);
}
int main(){
int ip=0x0;
打印ip(ip);
}
您实际上可以使用inet功能。观察

主要条款c:

#include <arpa/inet.h>

main() {
    uint32_t ip = 2110443574;
    struct in_addr ip_addr;
    ip_addr.s_addr = ip;
    printf("The IP address is %s\n", inet_ntoa(ip_addr));
}
#包括
main(){
uint32_t ip=2110443574;
地址中的结构ip地址;
ip_addr.s_addr=ip;
printf(“IP地址是%s\n”,inet_ntoa(IP_addr));
}
gcc main.c-ansi;的结果/a、 out

IP地址是54.208.202.125


请注意,一位评论员说这在Windows上不起作用。

从字符串到int再到int

const char * s_ip = "192.168.0.5";
unsigned int ip;
unsigned char * c_ip = (unsigned char *)&ip;
sscanf(s_ip, "%hhu.%hhu.%hhu.%hhu", &c_ip[3], &c_ip[2], &c_ip[1], &c_ip[0]);
printf("%u.%u.%u.%u", ((ip & 0xff000000) >> 24), ((ip & 0x00ff0000) >> 16), ((ip & 0x0000ff00) >> 8), (ip & 0x000000ff));
%hhu指示sscanf读入无符号字符指针;()


来自glibc

char *
inet_ntoa (struct in_addr in)
{
unsigned char *bytes = (unsigned char *) &in;
__snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
bytes[0], bytes[1], bytes[2], bytes[3]);
return buffer;
}

我的减法替代方案:)

void转换(无符号整数地址)
{    
无符号整数[OCTET],
下一个地址[八位字节];
整数位=8;
无符号整数移位\u位;
int i;
下一个地址[0]=addr;
移位_位-=位;
num[0]=下一个地址[0]>>移位位;
对于(i=0;ishift_bits;//八位组
}
printf(“%d.%d.%d.%d\n”,num[0],num[1],num[2],num[3]);
}
void ul2chardec(char*pcIP,无符号长ulIPN){
inti;intk=0;字符c0,c1;
对于(i=0;i((3-i)*8))/100)+0x30;
如果(c0!='0'){*(pcIP+k)=c0;k++;}
c1=((((ulIPN&(0xff>((3-i)*8))%100)/10)+0x30;
如果(!(c1=='0'和&c0=='0'){*(pcIP+k)=c1;k++;}
*(pcIP+k)=(((((ulIPN&(0xff>((3-i)*8))%10)+0x30;
k++;

如果(如果您正在编写代码-您应该使用inet函数-如果我进行了测试,我会因为重新创建可工作的测试代码而使您失败:)@标记如果你在windows上,你不能依赖inet函数…他们设法将它们绑定到winsock库中,因此,
inet\u ntoa
,它应该只做基本的位旋转,可能会失败。呃…这没有编译,是否缺少函数调用?移位计数都是错误的,他们似乎认为两个十六进制的gits等于四位。此外,最好先移位,然后再屏蔽,就像iWerner一样。就像我说的,这是一个快速的答案。修复了位移位。哦,天哪!永远不要写0xDEADBEEF之类的东西,除非你想发现自己调试了几个小时等等。参见1)这只是一个示例,2)代码现在已经编译和测试了,等等,让我问你想一想……我该怎么做呢?如果我有字符串,我该如何返回int?要从字符串返回int,你需要解析字符串。也就是说,没有简单的破解方法。这里有个大问题,你为什么要反向打印?@ytpillai
bytes[3]
包含最高有效字节(如127.0.0.1中的127个),应首先打印。同样地,
字节[0]
包含最不重要的bytei。我尝试了这种方法。我想,我们需要将其向前写入。我通过调制解调器检查了设备的ip地址。如果我像你一样打印,看起来是相反的。这是ip:192.168.43.182如果我使用你的方法,看起来像:182.43.168.192这是不可移植的;它取决于sizeof(unsigned)是4(和其他一些答案一样)一个int.@janm中的字节顺序当然是不可移植的。如果需要可移植的代码,我们可以定义替代的IP联合来处理更多的cpu架构,而无需修改实际代码。位转移方法是可移植的,不需要修改实际代码。为什么要在有shor的情况下引入一系列特殊情况更清晰、可移植的版本?性能?在现代编译器上,如果您能测量差异,我会感到惊讶(尽管我没有检查)。而且你可能想要%d而不是%x。这显然是最好的答案。为什么没有绿色记号?没有必要重新发明轮子。不会在Winodows上工作。因为作者没有指定平台,我个人不喜欢这个答案。请确保你的inet_ntoa()如果您的应用程序是多线程的,那么线程是否感知。至少,GNU Libc将返回的静态字符串缓冲线程声明为本地。@MarcinG为什么不呢?我要提到
inet_ntoa()
使用小的尾数顺序。这就是为什么它可以返回您不期望的结果。在上面的示例中,
2110443574
等于
125.202.208.54
,但该函数反转字节顺序,因此我们获得
54.208.202.125
。如另一个答案中所述,该函数的全部要点不是产生一个“可读”的整数,但是
#include <arpa/inet.h>

main() {
    uint32_t ip = 2110443574;
    struct in_addr ip_addr;
    ip_addr.s_addr = ip;
    printf("The IP address is %s\n", inet_ntoa(ip_addr));
}
const char * s_ip = "192.168.0.5";
unsigned int ip;
unsigned char * c_ip = (unsigned char *)&ip;
sscanf(s_ip, "%hhu.%hhu.%hhu.%hhu", &c_ip[3], &c_ip[2], &c_ip[1], &c_ip[0]);
printf("%u.%u.%u.%u", ((ip & 0xff000000) >> 24), ((ip & 0x00ff0000) >> 16), ((ip & 0x0000ff00) >> 8), (ip & 0x000000ff));
char *
inet_ntoa (struct in_addr in)
{
unsigned char *bytes = (unsigned char *) &in;
__snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
bytes[0], bytes[1], bytes[2], bytes[3]);
return buffer;
}
void convert( unsigned int addr )
{    
unsigned int num[OCTET], 
            next_addr[OCTET];

int bits = 8;
unsigned int shift_bits;
int i;

next_addr[0] = addr; 
shift_bits -= bits;  
num[0] = next_addr[0] >> shift_bits;

for ( i = 0; i < OCTET-1; i ++ )
{       
    next_addr[i + 1] = next_addr[i] - ( num[i] << shift_bits ); // next subaddr
    shift_bits -= bits; // next shift
    num[i + 1] = next_addr[i + 1] >> shift_bits; // octet
}

printf( "%d.%d.%d.%d\n", num[0], num[1], num[2], num[3] );
}
void ul2chardec(char*pcIP, unsigned long ulIPN){
int i; int k=0; char c0, c1;
for (i = 0; i<4; i++){
    c0 = ((((ulIPN & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8))) / 100) + 0x30;
    if (c0 != '0'){ *(pcIP + k) = c0; k++; }
    c1 = (((((ulIPN & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8))) % 100) / 10) + 0x30;
    if (!(c1 =='0' && c0=='0')){ *(pcIP + k) = c1; k++; }
    *(pcIP +k) = (((((ulIPN & (0xff << ((3 - i) * 8)))) >> ((3 - i) * 8))) % 10) + 0x30;
    k++;
    if (i<3){ *(pcIP + k) = '.'; k++;}
}
*(pcIP + k) = 0; // pcIP should be x10 bytes