2016-11-28 7 views
0

Dictionaryオブジェクトを作成し、3ワード追加することをお勧めします。 私のプログラムにはコンパイルエラーはありませんが、2回目の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

の作成しますか? forループはどこにありますか?私は1つしか見ることができません。 – dave

+0

すべての関数パラメータは、Cの値によって渡されます。つまり、 'd'の* copy *を' addNewWord'に渡しています。したがって、その関数の 'dic'に対するすべての変更は、呼び出し元の元の' d'変数に影響しません。その結果、同じ 'd.word'が複数回解放されます(したがって、2番目のループのエラー)。 – kaylum

+0

1)一般的に、 'malloc'&friendsや' void * 'の結果をキャストしないでください。 2) 'fflush(stdin)'は_undefined behaviour_を呼び出します。 3)[ask]を参照してください。 – Olaf

答えて

1

あなたのコードには多くの問題があります:英語で最長の単語を考える

は約30文字で、このサイズの割り当ては単語のためではなくdefintionのために現実的である:

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()通話だけではなく、1に適用するために使用した修正します!

パー@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); 

あなたがランダムにメモリにコピーしているので、あなたがdicnamemeanのための任意の領域を割り当てていなかったとして。

パー@Jarvis、動作しません:

​​

あなたがdicのコピーをしましたので、元のdicsizeがそれと同じになりますaddnewWord()内部ようにするには、値によってdicを渡していますコールの前にあった!

メモリリーク:

addNewWord(createNewWord(), d); 

あなたは何createNewWord()にあなたのハンドルを落としそうあなたがメモリを解放することはできません返さそれはmalloc()

あなたmalloc()メモリをdはそれ最終的には自由に何の手段を提供しません。

構造体を値渡しして返すことは、データがそのままコピーされるため、このような状況では災害です。最低でも、上記の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; 
} 

実行時エラーが何PUN DICTIONARY

> ./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

コードに間違いがあります。まず第一に、あなたはaddNewWord、関数にpointerしてDictionaryオブジェクトを渡す必要があり、かつ機能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