我更喜欢创建一个Dictionary对象,并在其中添加3个单词。我的程序没有编译错误,但是在第二个for循环中得到一个运行时错误,addNewWord函数中有问题吗?是否需要传递指向DictionaryWord对象的指针?
请帮帮我。
#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;
}发布于 2016-11-28 05:21:46
您的代码有很多问题:
考虑到英语中最长的单词约为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()调用,而不仅仅是一个!
Per @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);由于您没有为name和mean在dic中分配任何空间,所以您要复制到随机内存中。
Per @Jarvis不起作用:
void addNewWord(Words newword, Dictionary dic){
dic.size++;
dic.word = (Words*)realloc(dic.word,dic.size*sizeof(Words));您要通过值传递dic,所以在addnewWord()中,您有一个dic的副本,所以原始的dic的size将与调用前相同!
内存泄漏:
addNewWord(createNewWord(), d);你把你的手柄丢到了createNewWord()返回的东西上,所以你永远不能释放它的内存malloc()d。
您malloc()内存,但没有提供最终释放它的方法。
在这种情况下,按值传递和返回结构是一场灾难,因为数据一直在被复制。至少它是低效的,最糟糕的是,它的buggy就像上面提到的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)
>发布于 2016-11-28 03:30:42
我知道你的密码出了什么问题。首先,您需要将Dictionary对象通过pointer传递给函数addNewWord,在函数addNewWord中,再次需要为dic对象的每个char*字段( name和mean )分配内存。以下是修正后的代码:
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
https://stackoverflow.com/questions/40836609
复制相似问题