编辑:复制行为的最小编译代码。
这段代码读取了一个糟糕的字典文件,以便尝试从中提取一些有趣的信息。每行转换为结构条目。始终提取一个单词,因此newentry()不会检查其单词参数的有效性。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct entry {
char *word;
char *cat;
char *gen;
} entry;
entry *newentry(char *word, char *cat, char *gen) {
entry *w = malloc(sizeof(entry));
w->word = malloc(sizeof(strlen(word)) + 1);
strcpy(w->word, word);
if (cat) {
w->cat = malloc(sizeof(strlen(cat)) + 1);
strcpy(w->cat, cat);
}
else {
w->cat = "";
}
if (gen) {
w->gen = malloc(sizeof(strlen(gen)) + 1);
strcpy(w->gen, gen);
}
else {
w->gen = "";
}
return w;
}
int main() {
FILE *original = fopen("French.txt", "r");
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, original)) != -1) {
char *word = strtok(strdup(line), "\t");
char *tmp = strtok(NULL, "[\n");
char *cat = strtok(NULL, "]\n");
newentry(word, cat, tmp); //bugs here
}
return 0;
}
此代码在其行(代码)行上失败,我完全不知道为什么。如果我用word,cat或常量替换tmp,它每次都有效。 如果我要更改newentry()的参数的顺序,它每次都会失败,只要tmp是一个参数。 我试着通过打破时间进行调试。正在解析的文件大约是4千行,所以我想象某些行(它是一个非常糟糕的文件)以某种方式被破坏了,我尝试继续1000,并得到一个例外。所以我重新启动并尝试了其他值继续 - 但是通过继续100次11次,我能够超过前1000次。
我的结论是tmp在某种程度上被以下strtok损坏了。所以我试过了 char * tmp = strdup(strtok(NULL,“[\ n”));它没有更好的效果。
用printf替换newentry()失败行(“%s%s%s”,word,tmp,cat);虽然我无法通过眼睛检查4000个值,但100%的时间都有效。
我真的不知道如何摆脱这种混乱,并且会感激任何指针。
编辑:数据文件中的几行:
courthouse palais de justice[Noun]
courtier courtisan[Noun]
courtliness e/le/gance[Adjective]
courtly e/le/gant[Adjective]
courtmartial conseil de guerre[Noun]
courtroom salle d'audience[Noun]
感谢。
整个输入文件,以防有人真正好奇:http://pastebin.com/VPp8WpuK
答案 0 :(得分:3)
这是错误的:
entry *w = malloc(sizeof(entry *));
你想:
entry *w = malloc( sizeof *w );
或:
entry *w = malloc( sizeof( entry ))
答案 1 :(得分:2)
您可能需要调整为strtok选择的解析字符串。使用示例输入文件。我在第二行strtok上得到一个null,因为在第一次调用strtok时读取整行(即行中没有“\ t”
char *word = strtok(StrDup(line), "\t");//reads entire line of input
char *tmp = strtok(NULL, "[\n");//NULL is returned here
char *cat = strtok(NULL, "]\n");
因此,您将null传递给函数newentry(,,)
可行吗 将解析字符串更改为:
char *word = strtok(StrDup(line), "\t ");//added space
以下行
w->word = malloc(sizeof(strlen(word)) + 1);
w->cat = malloc(sizeof(strlen(cat)) + 1);
w->gen = malloc(sizeof(strlen(gen)) + 1);
应 :
w->word = malloc(strlen(word) + 1);
w->cat = malloc(strlen(cat) + 1);
w->gen = malloc(strlen(gen) + 1);
另一件事 ,您需要释放newentry()
中分配的内存,如果您需要返回结构w,这将是一个问题。建议在main()
中分配全部,将结构作为指针传递,然后在它返回时释放所有结构。
这是怎么做的......
创建一个struct entry
的数组:
typedef struct {
char *word;
char *cat;
char *gen;
} ENTRY;
ENTRY entry[linesInFile], *pEntry;
然后 在main()
初始化它:
int main(void)
{
pEntry = &entry[0];
//allocate memory
//call redefined newentry() function
//use results of newentry() function
//free memory
}
现在,因为pEntry是entry
整个数组的指针 ,所以在为char *成员调用malloc之后,它可以很容易地作为参数传递进入(回归时不要忘记free()
)
以下是我必须进行的编辑才能使其运行(不包括重写以获取free()调用)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct entry {
char *word;
char *cat;
char *gen;
} entry;
entry *newentry(char *word, char *cat, char *gen)
{
entry *w = malloc(sizeof(entry));
w->word = malloc(strlen(word) + 1);
strcpy(w->word, word);
if (cat)
{
w->cat = malloc(strlen(cat) + 1);
strcpy(w->cat, cat);
}
else
{
w->cat = "";
}
if (gen)
{
w->gen = malloc(strlen(gen) + 1);
strcpy(w->gen, gen);
}
else
{
w->gen = "";
}
return w;
}
int main()
{
FILE *original = fopen("French.txt", "r");
char line[260];
int len = 260;
//ssize_t read;
while ( fgets(line, len, original))
{
//char *word = strtok(StrDup(line), "\t ");//I dont have strdup, had to use this
char *word = strtok(strdup(line), "\t ");
char *tmp = strtok(NULL, "[\n");
char *cat = strtok(NULL, "]\n");
if((!word)||(!tmp)||(!cat)) return 0;
word[strlen(word)]=0;
tmp[strlen(tmp)]=0;
cat[strlen(cat)]=0;
newentry(word, cat, tmp); //bugs here
}
return 0;
}