Przygotowuję się do quizu i mam poważne podejrzenie, że mogę zostać poproszony o wdrożenie takiej funkcji. Zasadniczo, biorąc pod uwagę adres IP w notacji sieciowej, jak możemy uzyskać to od 32-bitowej liczby całkowitej do ciągu w notacji dziesiętnej z kropkami (coś w stylu 155.247.182.83) ...? Oczywiście nie możemy też używać żadnych funkcji inet ... Jestem zaskoczony!Integer to IP Address - C
Odpowiedz
Oto prosty sposób, aby to zrobić: The (ip >> 8)
, (ip >> 16)
i (ip >> 24)
przesuwa 2, 3 i 4 bajty do niższego rzędu bajt, podczas gdy & 0xFF
izoluje najmniej znaczący bajt na każdym kroku.
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]);
}
Na pierwszym etapie znajduje się domniemana bytes[0] = (ip >> 0) & 0xFF;
.
Użyj snprintf()
, aby wydrukować ciąg.
Dzięki za paczkę iWerner! –
Więc poczekaj, pozwól, że cię zapytam ... jak mam się wtedy odwrócić? Gdybym miał ciąg, jak mógłbym odzyskać int? –
Aby wrócić z ciągu znaków do int, musisz przeanalizować ciąg znaków. tj. nie jest łatwy sposób na hackowanie bitów. –
Podpowiedź: podziel 32-bitową liczbę całkowitą na 4 8-bitowe liczby całkowite i wydrukuj je.
Coś na wzór tego (nie skompilowane, YMMV):
int i = 0xDEADBEEF; // some 32-bit integer
printf("%i.%i.%i.%i",
(i >> 24) & 0xFF,
(i >> 16) & 0xFF,
(i >> 8) & 0xFF,
i & 0xFF);
Uh ... To się nie kompiluje, czy brakuje funkcji? A liczba zmian jest zła, wydaje się, że dwie cyfry heksadecymalne to cztery bity. Co więcej, lepiej jest przesunąć najpierw i maskę później, jak iWerner. – unwind
Dlaczego to dostało jakieś głosy? – janm
Tak jak powiedziałem, była to szybka odpowiedź. Naprawiono przesunięcie bitowe. –
Innym podejściem:
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);
To nie jest przenośne; zależy to od sizeof (unsigned) będącego 4 (jak niektóre inne odpowiedzi) i kolejności bajtów wewnątrz int. – janm
@janm, oczywiście, że nie jest przenośny. Jeśli istnieje potrzeba przenośnego kodu, możemy zdefiniować alternatywne związki IP do obsługi większej liczby architektur procesorów bez modyfikowania * rzeczywistego * kodu. –
Podejścia do przenoszenia bitów są przenośne, nie jest wymagany żaden modyfikujący kod _actual_. Po co wprowadzać grono specjalnych przypadków, w których istnieje krótsza, jaśniejsza, przenośna wersja? Wydajność? Na nowoczesnym kompilatorze byłbym zaskoczony, gdybyś mógł zmierzyć różnicę (chociaż nie sprawdziłem). Prawdopodobnie chcesz% d zamiast% x. – janm
To jest to, co chciałbym robić, gdy przeszedł bufor ciąg wypełnić i wiedziałem bufor był wystarczająco duży (długi czyli przynajmniej 16 znaków):
sprintf(buffer, "%d.%d.%d.%d",
(ip >> 24) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 8) & 0xFF,
(ip ) & 0xFF);
To byłoby nieco szybsze niż tworzenie tablicy bajtów jako pierwszej i uważam, że jest bardziej czytelna. Zwykle używam snprintf, ale adresy IP nie mogą być dłuższe niż 16 znaków, w tym kończąca się wartość null.
Alternatywnie, jeśli został poproszony o powrót do funkcji 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;
}
#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);
}
rzeczywiście może korzystania funkcję inet. Przestrzegać.
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));
}
Wyniki gcc main.c -ansi; ./a.out
jest
Adres IP to 54.208.202.125
Zauważ, że komentator powiedział, że ten nie działa w systemie Windows .
To jest oczywiście najlepsza odpowiedź. Dlaczego nie ma zielonego kleszcza? Nie trzeba już wymyślać nowych kół. –
Nie pracuję nad Winodowami. Ponieważ autor nie określił platformy, ja osobiście nie podoba mi się ta odpowiedź. – MarcinG
Upewnij się, że funkcja inet_ntoa() ma wątek, jeśli twoja aplikacja jest wielowątkowa. Przynajmniej GNU Libc deklaruje zwrotny wątek bufora ciągów lokalnych. https://sourceware.org/git/?p=glibc.git;f=inet/inet_ntoa.c;h=513d22c75e#l24 –
Od ciąg do int iz powrotem
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));
% RTK instruuje sscanf do zapoznania się unsigned char wskaźnik; (Reading small int with scanf)
inet_ntoa z 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;
}
Moja alternatywne rozwiązanie z odejmowaniem :)
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
}
- 1. C/C++ Linux MAC Address wszystkich interfejsów
- 2. ruby integer to boolean
- 3. Integer to real conversion function
- 4. Binary to Integer -> Erlang
- 5. Integer to Bit w SQL
- 6. Objective-C Integer arithmetic
- 7. Integer konwersji w C#
- 8. Co to jest typ odniesienia integer w C#?
- 9. Integer Division in C++ 11
- 10. Integer promotion in C program
- 11. C#: Wyliczanie adresów IP w zakresie
- 12. JQuery/JavaScript MAC Address Validation
- 13. Wywołanie przeciążony operator() Address wskaźnik
- 14. GSON Integer to Boolean dla konkretnych pól
- 15. Java 9 integer to String obsada
- 16. Co to jest "upakowana" struktura w C?
- 17. Co zrobić, aby aplikacja Large Address Aware?
- 18. Uwierzytelnianie według adresu IP wiosną 3.1: Najmądrzejszy sposób to zrobić?
- 19. sortowanie java HashMap <String, Integer>. Jak to posortować?
- 20. Wskaźnik funkcji Casting do Integer w C++
- 21. Najlepszy sposób obsługi przepełnienia Integer w C#?
- 22. Rozwiązywanie Integer Knapsack
- 23. Integer unosić
- 24. nie znaleziono zasobu @ integer/google_play_services_version co to jest?
- 25. if statement integer
- 26. Integer podział zawsze zero
- 27. Little-Endian Signed Integer
- 28. Resolve ip na nazwę hosta
- 29. Jak zweryfikować adres IP w C#
- 30. Integer dzielenie przez 7
Jeśli pisania kodu - należy użyć inet funct jony - i gdybym podał test, to zawiodę cię na nowo na funkcjonujący testowany kod :) – Mark
@Mark Jeśli jesteś w systemie Windows, nie możesz polegać na funkcjach ineta ... W jakiś sposób udało im się powiązać je z biblioteką winsock tak, że 'inet_ntoa', które ma po prostu zrobić podstawowe bicie twiddling, może zawieść. –