정수 대 IP 주소 - C
저는 퀴즈를 준비하고 있는데, 제가 그런 기능을 실행하는 임무를 맡을지도 모른다는 강한 의심이 듭니다.기본적으로 네트워크 표기법의 IP 주소가 주어졌을 때 32비트 정수에서 점선 10진수 표기법(155.247.182.83과 같은)의 문자열로 어떻게 가져올 수 있습니까?분명히 우리는 어떤 형태의 인터넷 기능도 사용할 수 없습니다.난감해요!
실제로 인터넷 기능을 사용할 수 있습니다.관찰하다.
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(윈도우)에서는 사용할 수 없다고 말했습니다.
간단한 방법은 다음과 같습니다.(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()
줄에 인쇄하는 것입니다.
또 다른 접근 방식:
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);
힌트: 32비트 정수를 48비트 정수로 분할하여 출력합니다.
여기에 따라 무언가가 있습니다. (집계되지 않은, YMMV):
int i = 0xDEADBEEF; // some 32-bit integer
printf("%i.%i.%i.%i",
(i >> 24) & 0xFF,
(i >> 16) & 0xFF,
(i >> 8) & 0xFF,
i & 0xFF);
입력할 문자열 버퍼를 전달하고 버퍼가 충분히 크다는 것을 알았다면 다음과 같이 수행합니다(즉, 최소 16자 길이).
sprintf(buffer, "%d.%d.%d.%d",
(ip >> 24) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 8) & 0xFF,
(ip ) & 0xFF);
이것은 먼저 바이트 배열을 만드는 것보다 약간 빠를 것이고, 나는 이것이 더 읽을 만하다고 생각합니다.저는 보통 snprintf를 사용하지만 IP 주소는 종단 null을 포함하여 16자를 초과할 수 없습니다.
또는 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);
}
문자열에서 int 및 back으로
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));
%hu는 sscanf에 서명되지 않은 문자 포인터로 읽으라고 지시합니다. (scanf로 작은 int 읽기)
glibc의 inet_ntoa
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 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
}
언급URL : https://stackoverflow.com/questions/1680365/integer-to-ip-address-c
'programing' 카테고리의 다른 글
MySQL 표준 시간대 (0) | 2023.10.23 |
---|---|
팬더는 가장 자주 열의 값을 얻습니다. (0) | 2023.10.23 |
서명되지 않은 MySQL TINYINT (0) | 2023.10.23 |
WebAPI를 사용한 ng-grid에 대한 서버측 페이징+필터링+정렬 (0) | 2023.10.23 |
시퀀스 캐시 및 성능 (0) | 2023.10.23 |