2013-08-17 44 views
0

我正在研究一個C程序,該類從一個文件中讀取行,然後使用qsort對它們進行排序。長話短說,我爲char*的數組動態地爲文件的每一行分配內存,存儲爲char*。讀取和存儲表面上可以正常工作,基於輸出(見下文),但是當我打印出這些行時,它們都是文件中最後一行的重複項。任何人都可以指出我的(很可能是很明顯的)錯誤嗎?爲什麼我的指針數組在動態分配後被覆蓋?

下面是相關代碼的問題我目前運行到:

char* trim_white_space(char* str); 
char* get_line(FILE* infile, char temp[]); 

int main(int argc, char* argv[]) { 
    FILE* infile; 
    char* input_file = argv[1]; 
    int cnt = 0; 
    char temp[MAX_LINE_LENGTH]; //to hold each line as it gets read in 
    char* tempPointer = temp; 

    if (argc < 2) { 
     printf("No input file provided"); 
     return EXIT_FAILURE; 
    } 

    //determine the number of lines in the file 
    infile = fopen(input_file, "r"); 
    int num_lines_in_file = num_lines(infile); 
    fclose(infile); 

    //allocate pointers for each line 
    char** lines = (char**) malloc(num_lines_in_file * sizeof(char*)); 

    //temporarily store each line, and then dynamically allocate exact memory for them 
    infile = fopen(input_file, "r"); 
    for (cnt = 0; cnt != num_lines_in_file; cnt++) { 
     tempPointer = get_line(infile, temp); 
     lines[cnt] = (char*) malloc(strlen(tempPointer) + 1); 
     lines[cnt] = trim_white_space(tempPointer); 
     printf("%d: %s\n", cnt, lines[cnt]); 
    } 

    fclose(infile); 

    //print the unsorted lines (for debugging purposes) 
    printf("Unsorted list:\n"); 
    for (cnt = 0; cnt != num_lines_in_file; cnt++) { 
     printf("%s\n", lines[cnt]); 
    } 

char* get_line(FILE* infile, char temp[]) { 
    fgets(temp, MAX_LINE_LENGTH-1, infile); 
    char* pntr = temp; 
    return pntr; 
} 

char *trimwhitespace(char *str) 
{ 
    char *end; 

    // Trim leading space 
    while(isspace(*str)) str++; 

    if(*str == 0) // All spaces? 
    return str; 

    // Trim trailing space 
    end = str + strlen(str) - 1; 
    while(end > str && isspace(*end)) end--; 

    // Write new null terminator 
    *(end+1) = 0; 

    return str; 
} 

我有這個樣本輸入文件5-1input.dat

Hi guys 
x2 My name is 
Slim Shady 
For real 

,這裏是我得到的輸出:

[email protected] ~/Desktop/Low-level/HW5 $ ./homework5-1 5-1input.dat 
0: Hi guys 
1: x2 My name is 
2: Slim Shady 
3: For real 
Unsorted list: 
For real 
For real 
For real 
For real 
+2

請添加'trim_white_space'的代碼。簡而言之,所有'lines'條目都被設置爲指向該函數返回的字符串,這可能是'tempPointer'本身或者一些靜態全局。無論如何它會覆蓋'malloc'返回的指針。 –

+1

沒錯。您首先分配'malloc'的結果,然後分配'trim_white_space'的結果,所以'malloc'丟失。試試'strncpy'。 –

+0

我已添加。我從另一個stackoverflow帖子獲得了該代碼。 – jkeys

回答

1

正如在評論中,你應該改變你的循環爲:

for (cnt = 0; cnt != num_lines_in_file; cnt++) { 
    tempPointer = get_line(infile, temp); 
    lines[cnt] = (char*) malloc(strlen(tempPointer) + 1); 
    strncpy(lines[cnt], trim_white_space(tempPointer), strlen(tempPointer)+1); 
    printf("%d: %s\n", cnt, lines[cnt]); 
} 

strncpy的大小是根據你使用的malloc大小。

當然,您可以優化此代碼,例如,只計算一次strlen等。

+0

哇,謝謝!你能解釋一下爲什麼我不能在一個任務中分配內存,然後用另一個任務將該內存指向修剪過的字符串? – jkeys

+0

@Hooked:簡單地說,你怎麼知道分配成功了? 'malloc'在失敗時返回NULL,這意味着你不能使用返回的指針。你正在檢查以確保任何對'malloc'的調用以及使用'malloc','realloc'等的函數都不會返回NULL,對嗎? –

+0

'trim_white_space'返回一個指針。它實際上只是一個數字,比如0x1234567。在這個地址下,你有你的數據,你可以通過*運營商訪問。行[cnt] =(char *)malloc(strlen(tempPointer)+ 1);意思是 - 爲我的數據分配一些內存,給我它的地址並保持行[cnt]。行[cnt] = trim_white_space(tempPointer);意思是 - 在tempPointer上執行一個函數,獲取它返回的地址並覆蓋已經存儲在行[cnt]中的數據(指向已分配內存的指針)。你想要做的就是從一個指針到另一個指針的內存中重寫*內容*。 –