首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C语言中的字典项目

C语言中的字典项目
EN

Stack Overflow用户
提问于 2016-11-28 03:06:15
回答 2查看 158关注 0票数 0

我更喜欢创建一个Dictionary对象,并在其中添加3个单词。我的程序没有编译错误,但是在第二个for循环中得到一个运行时错误,addNewWord函数中有问题吗?是否需要传递指向DictionaryWord对象的指针?

请帮帮我。

代码语言:javascript
复制
#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;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-28 05:21:46

您的代码有很多问题:

考虑到英语中最长的单词约为30个字符,这种大小分配对于单词来说是现实的,但对于定义则不是这样:

代码语言:javascript
复制
newword.name = (char*)malloc(30*sizeof(char));
newword.mean = (char*)malloc(30*sizeof(char));

这没有什么明显的意义:

代码语言:javascript
复制
dic.size = 0;
dic.word = (Words*)malloc(dic.size*sizeof(Words));

你给malloc()打了个电话!你只能通过你后来的realloc()才能幸免。即使是故意的,它也值得一提。

这实际上并不适用于输出流,因为fflush()适用于输出流:

代码语言:javascript
复制
fflush(stdin);

请参见:How to clear input buffer in C?和您使用的任何修复程序都必须应用于两个scanf()调用,而不仅仅是一个!

Per @Jarvis,这不管用:

代码语言:javascript
复制
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中分配任何空间,所以您要复制到随机内存中。

Per @Jarvis不起作用:

代码语言:javascript
复制
void addNewWord(Words newword, Dictionary dic){
    dic.size++;
    dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));

您要通过值传递dic,所以在addnewWord()中,您有一个dic的副本,所以原始的dicsize将与调用前相同!

内存泄漏:

代码语言:javascript
复制
addNewWord(createNewWord(), d);

你把你的手柄丢到了createNewWord()返回的东西上,所以你永远不能释放它的内存malloc()d。

malloc()内存,但没有提供最终释放它的方法。

在这种情况下,按值传递和返回结构是一场灾难,因为数据一直在被复制。至少它是低效的,最糟糕的是,它的buggy就像上面提到的size问题一样。与其冒险,不如假装它们只能通过指针传递并返回,这样您就可以安全地使用它,并获得更好的结果。

下面是您的代码的重做(在C中),使用修复、样式调整和尝试使用一致的术语。它还提供了一些最低限度的测试代码和释放数据的能力:

代码语言:javascript
复制
#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;
}

创建双关字典

代码语言:javascript
复制
> ./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) 
>
票数 1
EN

Stack Overflow用户

发布于 2016-11-28 03:30:42

我知道你的密码出了什么问题。首先,您需要将Dictionary对象通过pointer传递给函数addNewWord,在函数addNewWord中,再次需要为dic对象的每个char*字段( namemean )分配内存。以下是修正后的代码:

代码语言:javascript
复制
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);
}

将字典地址传递为:

代码语言:javascript
复制
addNewWord(createNewWord(), &d);

并更改函数的定义和原型:

代码语言:javascript
复制
void addNewWord(Words newword, Dictionary *dic)

在这里找到完整的代码:http://pastebin.com/ZN69hevj

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40836609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档