2016-11-28 67 views
0

我更喜歡創建一個Dictionary對象並向其中添加3個單詞。 我的程序沒有編譯錯誤,但在第二個for循環中得到運行時錯誤,是addNewWord函數中的問題?我需要傳遞一個指向DictionaryWord對象的指針嗎?卡在字典項目中C

請幫幫我。

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

typedef struct{ 
    char* name; 
    char* mean; 
} Words; 

typedef struct{ 
    Words* word; 
    int size; 
} Dictionary; 

Dictionary createNewDictionary(); 
Words createNewWord(); 
void addNewWord(Words newword, Dictionary dic); 

Dictionary createNewDictionary(){ 
    Dictionary dic; 
    dic.size = 0; 
    dic.word = (Words*)malloc(dic.size*sizeof(Words)); 
    return dic; 
} 

Words createNewWord(){ 
    Words newword; 
    newword.name = (char*)malloc(30*sizeof(char)); 
    newword.mean = (char*)malloc(30*sizeof(char)); 
    printf("============================\n"); 
    printf("Enter word: "); 
    scanf("%[^\n]", newword.name); 
    fflush(stdin); 
    printf("\nEnter meaning: "); 
    scanf("%[^\n]", newword.mean); 
    return newword; 
} 

void addNewWord(Words newword, Dictionary dic){ 
    dic.size++; 
    dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words)); 
    strcpy(dic.word[dic.size-1].name, newword.name); 
    strcpy(dic.word[dic.size-1].mean, newword.mean); 
} 

int main(){ 
    Dictionary d = createNewDictionary(); 
    for (int i=0;i<3;i++){ 
     addNewWord(createNewWord(), d); 
    } 
    return 0; 
} 
+0

什麼是運行時錯誤? 「第二」循環在哪裏?我只能看到一個。 – dave

+0

所有函數參數都以C的值傳遞。這意味着您將'd'的*副本*傳遞給'addNewWord'。因此,在該函數中'dic'的所有修改都不會影響調用者的原始'd'變量。結果是相同的'd.word'被多次釋放(因此第二個循環出現錯誤)。 – kaylum

+0

1)一般不要投放'malloc'和朋友或'void *'的結果。 2)'fflush(stdin)'調用_undefined behaviour_。 3)見[問]。 – Olaf

回答

1

你的代碼有很多問題:

鑑於在英語中最長的單詞大約是30個字符,這個大小分配是現實的話,而不是把定義:

newword.name = (char*)malloc(30*sizeof(char)); 
newword.mean = (char*)malloc(30*sizeof(char)); 

這使得小明顯的感覺:

dic.size = 0; 
dic.word = (Words*)malloc(dic.size*sizeof(Words)); 

你叫零malloc()!你只能在以後的realloc()下倖免。即使是故意的,它確實值得評論。

這並沒有真正的工作爲fflush()是輸出流:

fflush(stdin); 

見:How to clear input buffer in C?而且不管修復使用有權申請scanf()呼叫,而不只是一個!

每@Jarvis,這不起作用:

dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words)); 
strcpy(dic.word[dic.size-1].name, newword.name); 
strcpy(dic.word[dic.size-1].mean, newword.mean); 

因爲你沒有爲namemeandic所以你複製到隨機內存分配任何空間。

每@Jarvis,不工作:

​​

你傳遞dic的值,因此內部addnewWord()你已經的dic副本,以便原始dicsize將是相同的,因爲它在電話會議之前!

內存泄漏:

addNewWord(createNewWord(), d); 

你把你的手柄上有什麼createNewWord()回到這樣你就可以永遠釋放它malloc()「內存ð

malloc()的內存,但沒有提供手段,最終釋放它。

隨着數據不斷被複制,按值傳遞和返回結構是一種災難。至少它效率低下,最壞的情況是像上面size這個問題。而不是冒險,假裝他們只能通過指針傳遞和返回,你會安全地玩,並獲得更好的結果。

下面是你的代碼的返工(在C)與修正,風格的調整和嘗試一致的術語。它也提供一些最起碼的測試代碼,並釋放你的數據的能力:

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

#define MAX_WORD_LENGTH 30 
#define MAX_DEFINITION_LENGTH 1024 

typedef struct entry { 
    char *word; 
    char *definition; 
} Entry; 

typedef struct dictionary { 
    Entry *entries; 
    int num_entries, max_entries; 
} Dictionary; 

Dictionary *createNewDictionary() { 
    Dictionary *dictionary = malloc(sizeof(*dictionary)); 

    dictionary->num_entries = 0; 
    dictionary->max_entries = 1; 
    dictionary->entries = calloc(dictionary->max_entries, sizeof(*dictionary->entries)); 

    return dictionary; 
} 

void freeEntry(Entry *entry) { 
    free(entry->word); 
    free(entry->definition); 
    free(entry); 
} 

void freeDictionary(Dictionary *dictionary) { 
    for (--dictionary->num_entries; dictionary->num_entries >= 0; --dictionary->num_entries) { 
     // we can't call freeWord() here -- why. 
     free(dictionary->entries[dictionary->num_entries].word); 
     free(dictionary->entries[dictionary->num_entries].definition); 
    } 

    free(dictionary->entries); 
    free(dictionary); 
} 

void purgeInput() { 
    int c; 

    while ((c = getchar()) != '\n' && c != EOF) { } 
} 

Entry *requestNewEntry() { 
    Entry *entry = malloc(sizeof(*entry)); 
    entry->word = malloc(MAX_WORD_LENGTH); 
    entry->definition = malloc(MAX_DEFINITION_LENGTH); 

    printf("============================\n"); 
    printf("Enter word: "); 
    scanf("%[^\n]", entry->word); 

    purgeInput(); 

    printf("\nEnter definition: "); 
    scanf("%[^\n]", entry->definition); 

    purgeInput(); 

    return entry; 
} 

void addNewEntry(Entry *entry, Dictionary *dictionary) { 
    if (dictionary->num_entries == dictionary->max_entries) { 
     dictionary->max_entries *= 2; 
     dictionary->entries = realloc(dictionary->entries, dictionary->max_entries * sizeof(*dictionary->entries)); 
     // check if realloc returns NULL and if so, handle the error. 
    } 

    dictionary->entries[dictionary->num_entries].word = strdup(entry->word); 
    dictionary->entries[dictionary->num_entries].definition = strdup(entry->definition); 

    dictionary->num_entries++; 
} 

int main() { 
    Dictionary *d = createNewDictionary(); 

    for (int i = 0; i < 3; i++) { 
     Entry *e = requestNewEntry(); 

     addNewEntry(e, d); 

     freeEntry(e); 
    } 

    printf("\nRead: "); 
    for (int i = 0; i < d->num_entries; i++) { 
     printf("%s (%lu chars) ", d->entries[i].word, strlen(d->entries[i].definition)); 
    } 
    printf("\n"); 

    freeDictionary(d); 

    return 0; 
} 

創建潘詞典

> ./a.out 
============================ 
Enter word: silkworm 

Enter definition: Two silkworms had a race but ended up in a tie. 
============================ 
Enter word: horse 

Enter definition: A horse is a stable animal. 
============================ 
Enter word: termite 

Enter definition: A termite walks into a pub and asks, "Is the bar tender here?" 

Read: silkworm (47 chars) horse (27 chars) termite (62 chars) 
> 
+0

非常感謝您的幫助,我從您的回答中學到了很多經驗。 – Applepine

0

我看你的代碼有什麼問題。首先,您需要將您的Dictionary對象pointer傳遞給函數addNewWord,並在函數addNewWord中再次分配內存給dic對象的char*字段,namemean中的每一個。以下是更正代碼:

void addNewWord(Words newword, Dictionary *dic){ 
    dic->size++; 
    dic->word = (Words*)realloc(dic->word, dic->size*sizeof(Words)); 
    dic->word[dic->size-1].name = (char*)malloc(30*sizeof(char)); //added 
    dic->word[dic->size-1].mean = (char*)malloc(30*sizeof(char)); //added 
    strcpy(dic->word[dic->size-1].name, newword.name); 
    strcpy(dic->word[dic->size-1].mean, newword.mean); 
} 

把字典的地址爲:

addNewWord(createNewWord(), &d); 

,並更改定義以及函數的原型以及:

void addNewWord(Words newword, Dictionary *dic) 

找到完整代碼在這裏:http://pastebin.com/ZN69hevj

+0

是不是'addNewWord(createNewWord(),&d)'內存泄漏? – cdlane