comandos - Entero a la dirección IP-C
comandos cluster linux (9)
Me estoy preparando para un cuestionario, y tengo una fuerte sospecha de que puedo encargarme de implementar una función de este tipo. Básicamente, dada una dirección IP en notación de red, ¿cómo podemos obtener eso de un entero de 32 bits en una cadena en su notación decimal con puntos (algo así como 155.247.182.83) ...? Obviamente, tampoco podemos usar ningún tipo de funciones inet ... ¡Estoy perplejo!
Aquí hay un método simple para hacerlo: (ip >> 8)
, (ip >> 16)
y (ip >> 24)
mueve los bytes 2, 3 y 4 hacia el byte de orden inferior, mientras que el & 0xFF
aísla lo menos Byte significativo en cada paso.
void print_ip(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]);
}
Hay un bytes[0] = (ip >> 0) & 0xFF;
implícito bytes[0] = (ip >> 0) & 0xFF;
en el primer paso
Use snprintf()
para imprimirlo en una cadena.
De cuerda a int y atrás
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 le indica a sscanf que lea el puntero de carácter sin signo; ( Lectura pequeña int con scanf )
inet_ntoa de 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;
}
Esto es lo que haría si pasara un búfer de cadena para rellenar y sabía que el búfer era lo suficientemente grande (es decir, al menos 16 caracteres de longitud):
sprintf(buffer, "%d.%d.%d.%d",
(ip >> 24) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 8) & 0xFF,
(ip ) & 0xFF);
Esto sería un poco más rápido que crear primero una matriz de bytes, y creo que es más legible. Normalmente utilizaría snprintf, pero las direcciones IP no pueden tener más de 16 caracteres, incluido el nulo de terminación.
Alternativamente, si me piden una función que devuelva un 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;
}
Mi solución alternativa con la resta :)
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] );
}
Otro enfoque:
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);
Realmente puedes usar una función inet. Observar.
C Principal:
#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));
}
Los resultados de gcc main.c -ansi; ./a.out
gcc main.c -ansi; ./a.out
es
La dirección IP es 54.208.202.125
Tenga en cuenta que un comentarista dijo que esto no funciona en Windows.
Sugerencia: divida el entero de 32 bits en 4 enteros de 8 bits e imprímalos.
Algo en el sentido de esto (no compilado, YMMV):
int i = 0xDEADBEEF; // some 32-bit integer
printf("%i.%i.%i.%i",
(i >> 24) & 0xFF,
(i >> 16) & 0xFF,
(i >> 8) & 0xFF,
i & 0xFF);
#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);
}
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
}