2013-01-06 49 views
7

我有inet_aton轉換網絡地址的問題。下面的代碼工作正常的地址10.0.0.1inet_aton轉換爲010.000.000.001錯誤?

char *x1; 
struct sockaddr_in si_other; 
inet_aton("10.0.0.1", &si_other.sin_addr); 
printf("si_other.sin_addr =%lu\n",si_other.sin_addr); 
x1 = inet_ntoa(si_other.sin_addr); 
printf("x1=%s\n",x1); 

它輸出轉換:

si_other.sin_addr =16777226 
x1=10.0.0.01 

沒有問題爲止。當192.168.0.1192.168.000.001傳遞

si_other.sin_addr2 =16777224 
x2=8.0.0.01 

功能正常工作:然而,當010.000.000.001傳遞

char *x2; 
struct sockaddr_in si_other2; 
inet_aton("010.000.000.001", &si_other2.sin_addr); 
printf("si_other2.sin_addr =%lu\n",si_other2.sin_addr); 
x2 = inet_ntoa(si_other2.sin_addr); 
printf("x2=%s\n",x2); 

輸出函數工作怪異。

任何人都可以解釋我有什麼問題以及如何解決問題? (注意:我需要通過我的代碼中的010.000.000.001的IP地址)

+2

如果無法將點分十進制地址標準化爲標準可變寬度表示法,則必須編寫自己的函數,大約相當於處理非標準固定寬度的「inet_aton」,前導零填充IPv4地址。玩的開心! –

回答

12

前導0是interpreted as indicating the number is octal。 010(oct)== 8(dec)。您需要將輸入修改爲inet_aton以避免這種情況,或者以不同的方式自行轉換它。

const char *str = "010.000.000.001"; 
inet_aton(str[0] == '0' ? str+1:str, &si_other.sin_addr); 

是最簡單的解決方案,但它會更好解決什麼(snprintf?)產生字符串中的首位,以避免混亂。 (因爲它表明解決方案仍然不能用於許多邊緣案例,包括「001.0.0.1」,「0xF.0.0.1」,「1」和更多有效的IPv4地址)。

你可以平凡「正常化」使用sscanf您的輸入,即使你無法控制它如何被擺在首位生成(雖然這確實應該是whever它在我看來,來到一個bug):

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    const char *str="010.020.030.040"; 
    int parts[4]; 
    sscanf(str, "%d.%d.%d.%d", parts+0, parts+1, parts+2, parts+3); 
    char *out = NULL; 
    asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]); 
    printf("%s\n", out); 
    free(out); 
    return 0; 
} 
+2

'010.020.030.040'上的產量會是多少?顯然,第一個字段將是「10」(十進制),但其他字符呢? –

+0

@JonathanLeffler仍然不會解決這個問題。 – Flexo

+4

正確的解決方案是從所有八位字節左移修剪0。 +1。 – jweyrich