web-dev-qa-db-fra.com

Entier à l'adresse IP - C

Je me prépare pour un quiz, et je soupçonne fortement que je pourrais être chargé d'implémenter une telle fonction. Fondamentalement, étant donné une adresse IP en notation réseau, comment pouvons-nous obtenir cela d'un entier 32 bits dans une chaîne en notation décimale en pointillés (quelque chose comme 155.247.182.83) ...? Évidemment, nous ne pouvons pas non plus utiliser n'importe quel type de fonctions inet ... Je suis perplexe!

23
Kris Richards

Voici une méthode simple pour le faire: (ip >> 8), (ip >> 16) Et (ip >> 24) Déplace les 2e, 3e et 4e octets dans l'octet de poids faible, tandis que le & 0xFF isole l'octet de poids faible à chaque étape.

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

Il y a une bytes[0] = (ip >> 0) & 0xFF; implicite à la première étape.

Utilisez snprintf() pour l'imprimer dans une chaîne.

61
Wernsey

En fait pouvez utiliser une fonction inet. Observer.

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

Les résultats de gcc main.c -ansi; ./a.out est

L'adresse IP est 54.208.202.125

Notez qu'un commentateur a déclaré que cela ne fonctionne pas sous Windows.

92
Rose Perrone

Une autre approche:

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
Nick Dandoulakis

Astuce: divisez l'entier 32 bits en 4 entiers 8 bits et imprimez-les.

Quelque chose dans le sens de cela (non compilé, YMMV):

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

Ma solution alternative avec soustraction :)

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

C'est ce que je ferais si je passais un tampon de chaîne à remplir et je savais que le tampon était assez grand (c'est-à-dire au moins 16 caractères):

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

Ce serait un peu plus rapide que de créer un tableau d'octets en premier, et je pense que c'est plus lisible. J'utiliserais normalement snprintf, mais les adresses IP ne peuvent pas comporter plus de 16 caractères, y compris le null final.

Alternativement, si on me demandait une fonction renvoyant un caractère *:

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
Ray Burns
#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
sthysel

De la chaîne à l'int et au dos

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 demande à sscanf de lire le pointeur de caractère non signé; ( Lecture du petit int avec scanf )


inet_ntoa de la 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
bartolo-otrit
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
user3461121