整数转 IP 地址 - C

问题描述 投票:0回答:10

我正在准备测验,我强烈怀疑我的任务可能是实现这样的功能。基本上,给定网络表示法中的 IP 地址,我们如何将其从 32 位整数转换为点分十进制表示法的字符串(例如 155.247.182.83)...?显然我们也不能使用任何类型的 inet 函数......我被难住了!

c string ip-address
10个回答
117
投票

您实际上可以使用inet函数。观察。

main.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));
}

gcc main.c -ansi; ./a.out
的结果是

IP地址是54.208.202.125

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


84
投票

这里有一个简单的方法:

(ip >> 8)
(ip >> 16)
(ip >> 24)
将第 2、第 3 和第 4 个字节移动到低位字节,而
& 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]);        
}

第一步有一个隐含的

bytes[0] = (ip >> 0) & 0xFF;

使用

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


7
投票

另一种方法:

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);

6
投票

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

类似的东西(未编译,YMMV):

int i = 0xDEADBEEF; // some 32-bit integer
printf("%i.%i.%i.%i",
          (i >> 24) & 0xFF,
          (i >> 16) & 0xFF,
          (i >> 8) & 0xFF,
          i & 0xFF);

3
投票

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

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

这比先创建字节数组要快一些,而且我认为它更具可读性。我通常会使用 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;
}

1
投票
#include "stdio.h"

void print_ip(int ip) {
   unsigned char bytes[4];
   int i;
   for(i=0; i<4; i++) {
      bytes[i] = (ip >> i*8) & 0xFF;
   }
   printf("%d.%d.%d.%d\n", bytes[3], bytes[2], bytes[1], bytes[0]);
}

int main() {
   int ip = 0xDEADBEEF;
   print_ip(ip);   
}

1
投票

从字符串到整数再返回

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 读入 unsigned char 指针; (用scanf读取小int)


inet_ntoa 来自 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;
}

1
投票

我的减法替代解决方案:)

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] );
}

0
投票
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

}


0
投票

我可以在 Windows 下使用以下网络版本的 perror(),它使用 inet_ntoa()。我认为主要是 Windows 的包含文件有所不同;这应该是使用 TCP/IP 的一个很好的样板。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define soclose closesocket
#pragma comment( lib, "Ws2_32" )
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

void psock_errno(unsigned long srvr_in_adrs, char *Str)
{
    int iSockErr = WSAGetLastError();
    if (WSAENETUNREACH == iSockErr)
    {
        struct in_addr ia;
        ia.S_un.S_addr = srvr_in_adrs;
        printf("%s:%d (that network, %s, is unreachable)\n", Str, iSockErr, inet_ntoa(ia));
    }
    else printf("%s:%d\n", Str, iSockErr);
}
© www.soinside.com 2019 - 2024. All rights reserved.