2017-06-03 79 views
0

我一直在努力通過K & R中的練習來學習C,並且遇到了一個奇怪的問題。我編寫了一個程序來計算文件中的單詞,字符和行數,然後繪製一個顯示每個文件計數的直方圖。一切都運行良好,直到我試圖讓我的代碼更容易與結構重用。我的結構如下:訪問C列表中的結構成員C

struct category { 
    char *name; 
    int namelen; 
    int count; 
}; 

,它的值由構造函數分配:

struct category createCat(char *name) { 
    struct category cat = {name, get_width(name), 0}; 
return cat; 
} 

最後我有包括所有類別的清單,內容如下:

struct category catList[] = {words, lines, characters}; 

當我按名稱訪問這些結構的成員時,我沒有任何問題。但是,如果我嘗試通過catList[i].member來循環訪問它們,則成員count始終返回0.其他兩個成員name和namelen在循環中表現正確,並且從循環外部訪問count會正確返回。如果有人願意幫助我瞭解發生了什麼,我將不勝感激。

,如果它是必要的,這是我的整個方案:

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


int get_width(char* word) { 
    return 15 - strlen(word); 
} 

struct category { 
    char *name; 
    int namelen; 
    int count; 
}; 

struct category createCat(char *name) { 
    struct category cat = {name, get_width(name), 0}; 
    return cat; 
} 


int main() { 
    int c; 
    int inside_word; 
    int i; 
    int p; 
    struct category words = createCat("words"); 
    struct category lines = createCat("lines"); 
    struct category characters = createCat("characters"); 

    struct category catList[] = {words, lines, characters}; 

    while ((c = getchar()) != EOF) { 
     characters.count++; 
     if (c != '\n' && c != ' ' && c != '\t') { 
      putchar(c); 
      if (!inside_word) { 
       inside_word = 1; 
       words.count++; 
      } 
     } 

     else { 
      if (inside_word) 
       printf("\n"); 
      inside_word = 0; 
      if (c == '\n') 
       lines.count++; 
     } 
    } 
    printf("\n%d words, %d lines, %d characters\n", 
      words.count, lines.count, characters.count); 

    for (i = 0; i < 3; i++) { 
     printf("%s:%*s", catList[i].name, catList[i].namelen, " "); 
     printf("%d", catList[i].count); 
     for (p = 0; p < catList[p].count; p++) 
      printf("#"); 
     printf("\n"); 

    } 
    return 0; 
} 

回答

1

當你這樣做:

struct category catList[] = {words, lines, characters}; 

您是副本荷蘭國際集團的3層結構數據到catList。因此,當您按名稱更新3個結構時,catList中的結構是不同的副本,並且不會更新。

要解決這個問題,我會建議使用指針類型。有兩種方法可以做到這一點。

  1. 您可以在createCat方法中返回一個指針。

    struct category* createCat(char *name) { 
        struct category* cat = (struct category*) malloc(sizeof(struct category)); 
        //... 
        return cat; 
    } 
    

    從這時起,始終使用指針進行存儲。這是相當常用的。

  2. 您可以將指針存儲陣列catList在:

    struct category *catList[] = {&words, &lines, &characters}; 
    

    ,當你在循環使用它們,使用這樣的:

    catList[i]->count++; 
    
+0

這似乎意義的,我,但是當我在第一個選項中設置了你描述的wat時,我會在循環之前的'printf(word-> count等)節中得到一個段錯誤。使用第二個選項時,代碼的行爲與我從副本打印時的行爲相同。謝謝! – EthanS

+0

對不起,我只是想出了問題所在:我在嵌套for循環中錯誤地調用了catList [p]而不是catList [i]。標記你的答案是正確的,謝謝! – EthanS

0

要複製的words, lines, characters結構到你的列表中。

但是你在處理數據之前要這麼做,所以他們永遠不會更新。如果你想保持一組,刪除其他

words.count++; 
catList[0].count++; 

如果你想保持這兩套結構,必須在你的循環更新。 (除了頂部和底部之外,您現在擁有的幾乎是所有東西)。

如果您希望它們共享數據,然後使用指針,那麼列表(或獨立變量)指向其他結構。