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!
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.
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.
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);
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);
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] );
}
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;
}
#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);
}
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 *) ∈
__snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d",
bytes[0], bytes[1], bytes[2], bytes[3]);
return buffer;
}
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
}