2013-10-09 102 views
0

我發誓我真的是一個體面的程序員,但是在Java編程多年後,我在C編程中的冒險讓我很生氣。二維字符陣列問題

我想用一組IP地址/端口對填充二維字符數組。我正在從文件中讀取它們。他們正在被正確地拉出文件,並且應該被正確地放入數組中。問題是,由於某種原因,當第二組被放入數組時,它將覆蓋第一組,並且我不能爲了我的生活找出原因。

該文件的第一行是文件中的IP地址/端口對數(我稱之爲元組)。以下行是由空格分隔的IP地址和端口。

下面是代碼:

//read the top line with the number of items 
    fgets(line, sizeof line, fp); 
    numLines = atoi(line); 
    printf("%s %d\n","numLines:",numLines); 
    char* tuples[numLines][2]; 
    char* rawLines[numLines]; 
    //read each line and put it into array 
    for(currentLine=0; currentLine<numLines; currentLine++){ 
    if(fgets(line, sizeof line, fp) == NULL){ 
     perror("fgets"); 
     return -1; 
    } 
    printf("%s %d \n","curentLine: ",currentLine); 
    char* port; 
    tuples[currentLine][0] = strtok(line, " "); 
    printf("%s %s \n", "IP Address: ", tuples[currentLine][0]); 
    //rawLines[currentLine] = line; 
    port = strtok(NULL, " "); 
    size_t ln = strlen(port) - 1; 
    if (port[ln] == '\n') 
     port[ln] = '\0'; 
    tuples[currentLine][1]=port; 
    printf("%s %s\n","port: ", tuples[currentLine][1]); 
    } 
    //list created and stored in tuples 
    //now that list is created choose a random server from the file and strip the value chosen from the list 

    //choose random server 
    srand (time(NULL)); 
    //randomServer = rand()%numLines; 
    randomServer = 0; 
    printf("%s %d\n", "randomServer: ", randomServer); 



    //connect to random server pulled 
    memset(&hints, 0, sizeof hints); // make sure the struct is empty 
    hints.ai_family = AF_UNSPEC;  // don't care IPv4 or IPv6 
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets 
    hints.ai_flags = AI_PASSIVE;  // fill in my IP for me 
    //setup client socket 
    printf("%s %s \n", "Setting up connection to: ", tuples[randomeServer][0]); 
    printf("%s %s \n", "Setting up connection on port: ", tuples[randomServer][1]); 

這裏是輸出我得到:

numLines: 2 
curentLine: 0 
IP Address: 127.0.0.1 
port: 3761 
curentLine: 1 
IP Address: 192.168.0.1 
port: 3762 
randomServer: 0 
Setting up connection to: 192.168.0.1 
Setting up connection on port: 1 

我希望得到的是: 連接設置到:127.0.0.1 建立連接在端口上:3761

如果我只在文件中有一行,那麼我會得到期望的值。

預先感謝您。

+1

看起來像是指派一個指向內容稍後改變的數組的指針的典型症狀。除此之外:1. **感謝您使用'fgets()'而不是死腦筋的'scanf()'(由於某種原因每個人都喜歡(ab)使用),2.但是爲什麼'printf (「%s%d \ n」,「numLines:」,numLines);'?更可讀的版本是'printf(「numLines:%d \ n」,numLines);'。此外,'strtol()'優於'atoi()'。 – 2013-10-09 19:40:38

+0

不應該是'sizeof(line)'? – John

+0

@John不,爲什麼? 'line'是一個對象,而不是一個類型。 – 2013-10-09 19:42:52

回答

2

而不是直接分配strtok回到你的二維數組,複製的內容與strcpy

char *ipAddress = strtok(line, " "); 
char *tuple0 = malloc(sizeof(char) * (strlen(ipAddress) + 1)); 
strcpy(tuple0, ipAddress); 
tuples[currentLine][0] = tuple0; 
+1

有幾點需要注意:malloc調用需要+1結束符。如果你'strcpy'「abc」那麼需要4個字節。其次,不需要'strcat'。 strcpy已經爲null會終止結果(如果沒有,那麼'strcat'將不起作用,因爲它需要一個以null開頭的終止目標:)。 –

+0

@MarkWilkins你是對的。固定。 – Mauren

0

的問題是,你沒有正確地複製數據。您有一個名爲line的變量,該變量看起來是char的一個數組,您可以使用fgets()將輸入的每一行讀入此變量。然後,您對輸入進行標記,對於每個標記,您將指針存儲到line數組tuples數組中的某個位置,但是隻要您在下一行中讀取,該數據就會被覆蓋。你真正需要做的是分配一個新的存儲器,將數據複製到該存儲器中,並將指向新存儲器的指針存儲到tuples陣列中。

0

好像你沒有爲你的「保存」字符串分配內存。您的聲明:

char* tuples[numLines][2]; 
char* rawLines[numLines]; 

聲明指向char的指針數組。不是「字符串」。所以,你失去了一些東西,如:

tuples[index_value][0] = malloc(number_of_characters); 

然後你應該寫你在任何的strcpy或strncpy()函數內存讀取線。

sizeof(char) is always one

+1

'sizeof(char)'總是一個。 – 2013-10-09 19:52:03

0

這是值得記住,有在C. 2D陣列沒有2D陣列是一個抽象的概念,其可以在C與(至少)兩個不同的構建體的具體實現。有數組數組,並有指針數組。當我們談論指針數組時,我們通常(並非總是)安排它們,使得單個指針指向不同的內存塊,以免我們的抽象二維數組最終包含同一行的重複項。爲了發生這種情況,我們通常在堆上明確分配每行,然後用值填充它。請注意0​​不分配任何東西。它接受一個字符數組並返回指向它的指針(並破壞那裏的原始字符串)。