2012-08-14 55 views
1

我寫一個程序,並具有以下循環:值在地址消失

while ((c = getchar()) != EOF){ 
    if (c == '\n'){ 
     char newword[strlen(word) + 1]; 
     strcpy(newword, word); 
     words[i].key = newword; 
     memset(word, '\0', MAXLENGTH);   
     i++; 
     j = 0; 
    } else { 
     word[j++] = c; 
    } 
} 

哪裏words是結構數組:

struct kvp{ 
    char *key; 
    int line; 
}; 

word是一個大陣列(大小MAXLENGTH的),其中的前幾個值構成一個字符串。

問題在於words[i].key。在if語句中,打印它(將其設置爲newword後)將返回正確的值,即與輸入的單詞相同的最小大小的字符串。一旦if語句退出並返回while循環的外部體,它就會變成完全隨機的東西,即?HBk?

有三件事情,我懷疑可能會發生:

  • strcpy不採取行動,我認爲它確實
  • newword是一個局部變量,並以某種方式影響的東西(不健全的權利的方式)
  • 我不正確理解指針或結構尚未(完全有可能的,我剛開始學習C)

這是怎麼回事?

+0

「聽起來不正確」 - 有趣的是,你會認爲......你的經驗可能是垃圾收集語言。但是在C中,變量的作用域限定了它的生命週期,並且在該作用域之外使用它是未定義的行爲。 – 2012-08-14 03:07:01

+0

絕對好知道,謝謝!是的,我的經驗來自於Java,JavaScript,Ruby和PHP。 – 2012-08-14 03:24:58

回答

4

當您在if塊中聲明newword時,該塊在退出後超出範圍。如果你想保持它,你需要在外部範圍內分配內存,或者在堆上分配字符串malloc

if (c == '\n') 
{ 
    // newword will persist beyond this block: 
    char *newword = malloc(strlen(word) + 1); 
    strcpy(newword, word); 
    words[i].key = newword; 

注意,現在你需要調用free這alloc'd塊上,或者創建一個內存泄漏。稍後您需要致電free(words[i].key)

Martin的建議使用strdup是一個不錯的選擇,它可以使用strdup:它會爲你做分配 - 但你以後還需要free

+0

+1,打敗我吧。 – Martin 2012-08-14 01:42:48

+0

非常好,謝謝!我希望K&R能夠更好地覆蓋malloc/free,因爲我已經在互聯網上看到了它。 – 2012-08-14 01:45:18

2

新字被存儲在堆棧中,所以每次while循環執行時它都會超出範圍。

您需要爲其動態分配內存。我建議用替換

char newword[strlen(word) + 1]; 
strcpy(newword, word); 

char * newword = strdup(word); 

這將分配的內存中,在複製內容。請注意,你應該用free()清理那些內存,否則你會發生內存泄漏。