2012-02-13 25 views
2

我是編程新手,想學習鏈表。我決定通過編寫一個簡單的程序來實驗鏈表,該程序將從文件中讀取,每次只讀一個字符,並將每個字符插入鏈表中。然後我打印出鏈表。很簡單,對吧?好吧,如果這是你第一次,也許不會。我在網上教程哦,如此小心,但我的輸出不是它應該是。 (程序編譯並運行時沒有錯誤或警告,我正在使用代碼塊。)我沒有獲取任何字符,而是得到兩個數字,就這些了。c中的鏈表,意想不到的結果

這裏是我寫的代碼:

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

typedef struct Tokens_read_in{ 
    char character; 
    int number; 
    char whichOne[5]; 
    struct Tokens_read_in* next; 
}Tokens; 

int main() 
{ 

    //declare variables 
    char c; 

    //create a struct for the array that will hold the tokens 
    Tokens* token_array; 
    token_array = malloc(sizeof(Tokens)); 
    token_array->next = NULL; 

    //open the input file 
    FILE *ifp; //input file pointer 
    char *filename = "input.txt"; 
    ifp = fopen(filename, "r"); 

    if(!ifp){ 
     printf("Error in opening '%s' for reading!", filename); 
     exit(0); 
    } 

    while(!feof(ifp)){ 

     //prepare to read in file one character at a time 
     c = getc(ifp); 

     //create a struct for the current token that is read in 
     Tokens* current_token = token_array; 

     //let the current_token point to the beginning of token_array 
     current_token = token_array; 

     //let the current_token point to the LAST of token_array 
     while(current_token->next != NULL){ 
      current_token = current_token->next; 
     } 

     //create a node at the end of token_array 
     current_token->next = malloc(sizeof(Tokens)); 

     //move the current_token to the last (new) of token_array 
     current_token = current_token->next; 
     if(current_token == NULL){ 
      printf("Out of memory"); 
      exit(0); 
     } 

     //plug character into current_token 
     current_token->next = NULL; 
     //letter 
     if(isalpha(c)){ 
      printf("%c", c); 
      current_token->character = c; 
      strcpy(current_token->whichOne, "char"); 
     } 
     //number 
     else if(isdigit(c)) 
     { 
      printf("%d", (int)c); 
      current_token->number = (int)c; 
      strcpy(current_token->whichOne, "num"); 
     } 
     //space 
     //this does not need to go into the token array 
     else if (c == ' '){ 
      printf(" "); 
     } 
     //newline 
     //this does not need to go into the token array 
     else if (c == '\n'){ 
      printf("\n"); 
     } 
     //anything else 
     else if ((!isdigit(c) && !isalpha(c))){ 
      printf("%c", c); 
      current_token->character = c; 
      strcpy(current_token->whichOne, "char"); 
     } 

     //now that the current_token is plugged into token_array, free current_token 
     free(current_token); 

    }//end while(!feof(ifp)) 

    //print the token_array 
    Tokens* conductor; 
    conductor = token_array; 
    while(conductor != NULL){ 
     if(strcmp(conductor->whichOne, "num")){ 
      printf("%d ", conductor->number); 
     } 
     else if(strcmp(conductor->whichOne, "char")){ 
      printf("%c ", conductor->character); 
     } 
     conductor = conductor->next; 
    } 
    //done printing, so free conductor 
    free(conductor); 

    //done with program, so free token_array 
    free(token_array); 

    //close input file 
    fclose(ifp); 

    return 0; 
}//end main 

這裏是我使用的輸入文件(名爲input.txt中):

<I don't know why every beginner program says hello world, 
but hello world anyway.> 

我真的很感激任何人誰看這個並指出我正確的方向。

+0

每個初學者程序

說「你好世界」,因爲經典文本* C程序設計語言*開始於一個程序,打印「Hello ,世界!「。 – Caleb 2012-02-13 17:27:12

+0

您的程序有幾個主要缺陷需要修復,然後才能繼續。第一個缺陷是你要通過每次迭代收集一個新角色來重置和遍歷你的列表。如果你只是堅持根(第一個)節點和終端(最後一個)節點,這是完全不必要的。接下來,您聲明一個堆棧變量指向根節點並將其分配兩次。最後,釋放剛剛初始化的節點,從而創建無效指針的鏈接列表。你需要更好地理解C和完成你的任務的指針。 – BitBank 2012-02-13 17:37:47

回答

5

您不應該在讀取循環結束時釋放current_token。這會導致問題,因爲您釋放了鏈接列表中的節點的內存。

另外,作爲旁註,當給定表示數字的字符時,isdigit成功,因此例如字符'1'。您仍然應該使用%c來打印出來,因爲%d會爲您提供字符'1'的ascii編號。

+0

我瞭解它的方式,一旦current_token被「插入」token_array,token_array將接管所有插入它的內容,即使當current_token被釋放時也會存在。我是否明白這完全錯誤 - 我要走了嗎?如果是這樣,我應該在哪裏free_array - 我應該釋放它與自由(token_array)?或者如果兩者仍然交織在一起,是否意味着我只需要釋放token_array並且會自動消除current_array? – Tabitha 2012-02-13 17:49:29

0
//now that the current_token is plugged into token_array, free current_token 
     free(current_token); 

    }//end while(!feof(ifp)) 

嘗試呼叫評論到free(current_token);

的malloc的工作和自由是跟蹤的內存已經分配了什麼。當你打電話給免費的時候,下一次malloc調用可能會發回你剛纔使用的相同的內存地址。

此外

//create a struct for the current token that is read in 
Tokens* current_token = token_array; 

//let the current_token point to the beginning of token_array 
current_token = token_array; 

第二分配是多餘的。不是一個錯誤(但),但只是一個新的程序員的筆記。

另外,讓我們知道你正在得到什麼數字。獲取數字而不是字符有時可能表示您正在輸出ASCII碼而不是字符本身。

4

您需要if (strcmp(a,b)==0)來測試是否相等。

+1

這是您遇到的最大問題之一。您正在使用您的號碼打印字符和字符打印數字。 – 2012-02-13 17:39:30

1
  • 你絕對不想free(current_token)
  • 如果你想爲一個字符轉換爲int,一個簡單的方法(在ASCII)要做到這一點是:
char c = '3'; 
    int i = c - '0'; 
    printf("As a char: %c\n", c); // Prints 3. 
    printf("As an int: %d\n", i); // Prints 3. 
  • 當你的malloc數據,這是可能的,可能會有是該地區的隨機數據。一旦你使用memset malloc,你應該清除整個結構。
  • 正如其他答案中所提到的,strcmp在匹配時返回0。這意味着你正在做你想要的比較的反面。
  • 當字符是空格或換行符時,結構中的數據非常奇怪。這是因爲數據以未確定的狀態開始。

如果您修復上述錯誤(不包括memset),程序的輸出更像您想要的。