2017-10-07 23 views
-2
void main(int argc, char* argv[]) { 

    char* hostname = (char*)malloc(sizeof(char)*1024); 
    hostname = getClientHostName("122.205.26.34"); 
    printf("%s\n", hostname); 
    free(hostname); 
} 

char* getClientHostName(char* client_ip) { 

    char hostnames[5][2]; 
    hostnames[0][0] = "122.205.26.34"; 
    hostnames[0][1] = "aaaaa"; 
    hostnames[1][0] = "120.205.36.30"; 
    hostnames[1][1] = "bbbbb"; 
    hostnames[2][0] = "120.205.16.36"; 
    hostnames[2][1] = "ccccc"; 
    hostnames[3][0] = "149.205.36.46"; 
    hostnames[3][1] = "dddddd"; 
    hostnames[4][0] = "169.205.36.33"; 
    hostnames[4][1] = "eeeeee"; 
    for(int i = 0; i<5; i++) { 
     if(!strcmp(hostnames[i][0], client_ip)) 
      return (char*)hostnames[i][1]; 
    } 
    return NULL; 
} 

初學C.以下代碼中的分段錯誤11。如何避免溢出?

我不知道是否會有實現的東西,我想實現一個更好的辦法。代碼是不言自明的。有什麼方法可以預先定義主機名的大小,使用一些通用大小的IP地址來避免seg故障?有沒有更好的方法,我不必硬編碼的大小?

+0

你的代碼不應該乾淨地編譯。使用[gcc](http://gcc.gnu.org/)用'gcc -Wall -Wextra -g'編譯它 –

回答

1

*添加到類型定義char * hostnames[5][2]。這必須是指針數組,不是簡單的char s。另一個必要的變化是strcpy而不是=strcpy(hostname, getClientHostName("122.205.26.34"));

PS:總是嘗試使用0編譯器警告進行編譯,而不僅僅是0錯誤!

+0

當然,那麼你必須從堆中分配內存...... – torstenvl

2

固定的編譯器錯誤和警告後,您將獲得:

const char* getClientHostName(const char* client_ip) { 

    const char * hostnames[5][2]; 
    hostnames[0][0] = "122.205.26.34"; 
    hostnames[0][1] = "aaaaa"; 
    hostnames[1][0] = "120.205.36.30"; 
    hostnames[1][1] = "bbbbb"; 
    hostnames[2][0] = "120.205.16.36"; 
    hostnames[2][1] = "ccccc"; 
    hostnames[3][0] = "149.205.36.46"; 
    hostnames[3][1] = "dddddd"; 
    hostnames[4][0] = "169.205.36.33"; 
    hostnames[4][1] = "eeeeee"; 
    for(int i = 0; i<5; i++) { 
     if(!strcmp(hostnames[i][0], client_ip)) 
      return hostnames[i][1]; 
    } 
    return NULL; 
} 

int main(int argc, char* argv[]) { 
    const char * hostname = getClientHostName("128.205.36.34"); 
    printf("%s\n", hostname); 
} 
2

有沒有更好的方法,我沒有硬編碼的大小?

養成編譯所有警告和調試信息的習慣:gcc -Wall -Wextra -gGCC。改進代碼以獲取任何警告。

如果你想獲得真正的IP地址,這是操作系統特定的(因爲標準C11不知道IP地址;請通過閱讀​​進行檢查)。在Linux上,您可以使用名稱服務例程,例如getaddrinfo(3) & getnameinfo(3)或過時的gethostbyname(3)

如果這僅僅是沒有到TCP/IP套接字的實際關係(見tcp(7)ip(7)socket(7)),你可以在表存儲在一些全球陣列練習:

struct myipentry_st { 
    const char* myip_hostname; 
    const char* myip_address; 
}; 

然後定義global陣列包含它們,與一些{NULL, NULL}進入終止它的約定:

const struct myipentry_st mytable[] = { 
    {"aaaaa", "122.205.26.34"}, 
    {"bbbb", "120.205.36.30"}, 
    /// etc 
    {NULL, NULL} // end marker 
}; 

你最好有一個全球static variable(而不是automatic一個坐在call stack),因爲你不想每次打電話給你的getClientHostName

那麼你的查找程序(效率低,因爲線性時間)將是:

const char* getClientHostName(char* client_ip) { 
    for (const struct myipentry_st* ent = mytable; 
     ent->myip_hostname != NULL; 
     ent++) 
    // the if below is the only statement of the body of `for` loop 
    if (!strcmp(ent->myip_address, client_ip)) 
     return ent->myip_hostname; 
    // this happens after the `for` when nothing was found 
    return NULL; 
} 

你甚至可以聲明表作爲heap allocated指針:

const struct myipentry_st**mytable; 

然後使用calloc其分配並從一些文本文件中讀取其數據。

請閱讀每個standard或您正在使用的外部功能的文檔。不要忘記檢查失敗(例如,calloc,如here)。通過適當調用free避免memory leaks。使用調試器gdbvalgrind。當心undefined behavior

在現實世界中,您可能會有數千個條目,並且您可能會多次執行查找(可能是數百萬次,例如,每個在網絡服務器或客戶端上的HTTP請求一次)。然後選擇更好的​​(hash tablered-black tree也許)。讀一些Introduction to Algorithms

+0

感謝投入。但事情是,我肯定可以實施更好的方法,我可以做到這一點。但不是在C.這是我第一次用C編碼。第一次。就像,第一次。我有一個星期做這個任務。所以我沒有足夠的時間來學習C語言。我對Java更加適應,在某種程度上也適用於Python,但是C卻非常不同。所以現在我只是試圖讓它工作。 – Manic