2009-11-05 53 views
18

Tôi đang chuẩn bị cho bài kiểm tra và tôi có một nghi ngờ mạnh mẽ rằng tôi có thể được giao nhiệm vụ triển khai chức năng như vậy. Về cơ bản, được đưa ra một địa chỉ IP trong ký pháp mạng, làm thế nào chúng ta có thể nhận được rằng từ một số nguyên 32 bit vào một chuỗi trong ký hiệu thập phân chấm của nó (một cái gì đó giống như 155.247.182.83) ...? Rõ ràng là chúng tôi không thể sử dụng bất kỳ loại chức năng inet nào cả ... Tôi bị bối rối!Số nguyên cho Địa chỉ IP - C

+8

Nếu bạn đang viết mã - bạn nên sử dụng inet funct các ion - và nếu tôi thử nghiệm, tôi sẽ thất bại khi bạn phát minh lại mã thử nghiệm làm việc :) – Mark

+2

@Mark Nếu bạn đang ở trên các cửa sổ, bạn không thể dựa vào các chức năng inet ... Chúng bằng cách nào đó đã quản lý chúng thành thư viện winsock do đó, 'inet_ntoa', được cho là chỉ làm bit cơ bản, có thể thất bại. –

Trả lời

56

Dưới đây là một phương pháp đơn giản để làm điều đó: Các (ip >> 8), (ip >> 16)(ip >> 24) di chuyển 2, byte thứ 3 và thứ 4 vào bậc thấp byte, trong khi & 0xFF tách byte ít quan trọng nhất ở mỗi bước.

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

Có ngụ ý bytes[0] = (ip >> 0) & 0xFF; ở bước đầu tiên.

Sử dụng snprintf() để in thành chuỗi.

+0

Cảm ơn một loạt iWerner! –

+0

Vì vậy, hãy chờ đợi, hãy để tôi hỏi bạn nghĩ ... làm thế nào tôi sẽ đi theo cách khác xung quanh sau đó? Nếu tôi đã có chuỗi, làm thế nào tôi có thể lấy lại int? –

+0

Để trở về từ chuỗi đến int bạn sẽ cần phải phân tích chuỗi. tức là không có cách hack bit dễ dàng. –

5

Gợi ý: chia nhỏ số nguyên 32 bit thành 4 số nguyên 8 bit và in chúng ra.

cái gì đó dọc theo dòng này (không được biên dịch, YMMV):

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

Uh ... Điều này không biên dịch, có một cuộc gọi chức năng bị thiếu? Và số lần thay đổi là sai, họ dường như nghĩ rằng hai chữ số hex bằng bốn bit. Hơn nữa, nó tốt hơn để thay đổi đầu tiên và mặt nạ sau, như iWerner. – unwind

+0

Tại sao điều này nhận được bất kỳ phiếu bầu nào? – janm

+0

Như tôi đã nói, đó là một câu trả lời nhanh. Đã sửa lỗi dịch chuyển bit. –

5

cách tiếp cận khác:

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); 
+2

Đây không phải là di động; nó phụ thuộc vào sizeof (unsigned) là 4 (giống như một số câu trả lời khác) và thứ tự byte trong một int. – janm

+0

@janm, tất nhiên nó không di động. Nếu có nhu cầu về mã di động, chúng ta có thể định nghĩa các tổ hợp IP thay thế để xử lý nhiều kiến ​​trúc cpu mà không sửa đổi mã * thực tế *. –

+0

Các phương pháp chuyển bit là di động, không cần sửa đổi mã _actual_. Tại sao lại giới thiệu một loạt các trường hợp đặc biệt khi có phiên bản di động ngắn hơn, rõ ràng hơn? Hiệu suất? Trên một trình biên dịch hiện đại, tôi sẽ ngạc nhiên nếu bạn có thể đo lường sự khác biệt (mặc dù tôi chưa kiểm tra). Và bạn có thể muốn% d thay vì% x. – janm

1

Đây là những gì tôi sẽ làm gì nếu thông qua một bộ đệm chuỗi để điền vào và tôi biết bộ đệm đủ lớn (dài tức là ít nhất 16 ký tự):

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

Điều này sẽ nhanh hơn một chút so với việc tạo mảng byte trước và tôi nghĩ rằng nó dễ đọc hơn. Tôi thường sử dụng snprintf, nhưng địa chỉ IP không thể dài hơn 16 ký tự bao gồm cả kết thúc null.

Ngoài ra nếu tôi được yêu cầu cho một hàm trả về một 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; 
} 
1
#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); 
} 
73

Bạn thực sự có thể sử dụng một chức năng inet. Quan sát.

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

Kết quả gcc main.c -ansi; ./a.out

Địa chỉ IP là 54.208.202.125

Lưu ý rằng một commenter nói này không làm việc trên Windows .

+14

Đây rõ ràng là câu trả lời hay nhất. Tại sao nó không có dấu màu xanh lá cây? Không cần phải tái phát minh ra bánh xe. –

+1

Won't hoạt động trên Winodows. Vì tác giả đã không chỉ định nền tảng cá nhân tôi không thích câu trả lời này. – MarcinG

+0

Hãy chắc chắn rằng inet_ntoa() của bạn là chủ đề nhận biết nếu ứng dụng của bạn là đa luồng. GNU Libc, ít nhất, khai báo chuỗi địa chỉ chuỗi tĩnh trả về tĩnh cục bộ. https://sourceware.org/git/?p=glibc.git;f=inet/inet_ntoa.c;h=513d22c75e#l24 –

0

Từ chuỗi int và lưng

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 chỉ thị sscanf để đọc vào unsigned char trỏ; (Reading small int with scanf)


inet_ntoa từ 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

giải pháp thay thế của tôi với phép trừ :)

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

}

Các vấn đề liên quan