C 斯特托克(我想)我能';我不明白

C 斯特托克(我想)我能';我不明白,c,strtok,C,Strtok,编辑:复制行为的最小编译代码 这段代码读取一个蹩脚的字典文件,以便尝试从中提取一些有趣的信息。每行转换为一个结构条目。总是提取单词,因此newentry()不会检查其单词参数的有效性 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct entry { char *word; char *cat; char *gen; } entry; entry *newent

编辑:复制行为的最小编译代码

这段代码读取一个蹩脚的字典文件,以便尝试从中提取一些有趣的信息。每行转换为一个结构条目。总是提取单词,因此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;
}
谢谢

整个输入文件,以防有人真的好奇:

这是错误的:

entry *w = malloc(sizeof(entry *));
你想要:

entry *w = malloc( sizeof *w );
或:


您为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()
中分配所有内存,将结构作为指针传递,然后在返回时释放所有内存

这是如何做到的…
创建
结构项的数组

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数组的指针,所以在为entry的char*成员调用malloc后,它可以很容易地作为参数传递。(当它返回时,不要忘记
free()

以下是我为使其运行所做的编辑(不包括重新写入以获取free()调用)

#包括
#包括
#包括
typedef结构条目{
字符*字;
char*cat;
char*gen;
}入境;
条目*新条目(字符*字,字符*猫,字符*根)
{
条目*w=malloc(sizeof(条目));
w->word=malloc(strlen(word)+1);
strcpy(w->word,word);
如果(cat)
{
w->cat=malloc(strlen(cat)+1);
strcpy(w->cat,cat);
}
其他的
{
w->cat=“”;
}
如果(一般)
{
w->gen=malloc(strlen(gen)+1);
strcpy(w->gen,gen);
}
其他的
{
w->gen=“”;
}
返回w;
}
int main()
{
文件*original=fopen(“French.txt”,“r”);
字符行[260];
int len=260;
//阅读;
while(fgets(线条、透镜、原件))
{
//char*word=strtok(StrDup(line),“\t”);//我没有StrDup,必须使用这个
char*word=strtok(strdup(行),“\t”);
char*tmp=strtok(空,[\n”);
char*cat=strtok(空,]\n“);
如果(!word)| |(!tmp)| |(!cat))返回0;
字[strlen(字)]=0;
tmp[strlen(tmp)]=0;
cat[strlen(cat)]=0;
newentry(word、cat、tmp);//这里有bug
}
返回0;
}

你能解释一下怎么回事吗?这两个表达式都不会改变错误。
malloc(sizeof(entry*)
分配内存到条目的指针大小,而
malloc(sizeof*w)
分配内存到w指向的指针大小。@pouzzler
sizeof(entry*)
只返回指针的大小,而不是整个结构。因此,malloc的内存太少。谢谢,知道这一点很有用。我希望这就是导致它出现错误的原因,但这确实很有用。再次感谢。在这里,malloc(strlen+1)是分配字符串副本的正确方法,是吗?@pouzzler:
malloc(sizeof(strlen(word))+1)
是错误的,
malloc(strlen(word)+1);
是正确的。更好的方法是使用
strdup()
来避免所有手动操作。虽然现在可能没有问题,但您应该检查
malloc
是否失败(返回
NULL
)。您正在
newentry
中分配内存,但决不能释放该内存。请显示文件的一行示例。如果生成此代码段,以及在代码中添加注释,说明问题在何处出现,这将非常有帮助。(结构中的成员
列表
)我目前的直觉是,输入文件中有一些错误的数据,什么样的数据会破坏这个简单的strtok序列?当没有[noon]时,cat通常为null最后是段,它在cat上从来没有bug,所以我不明白为什么它应该在tmp上bug,不管是否为NULL。输入文件是错误的。原始文件中有一个选项卡,但so和PB都将它们转换为空格。我为时间的损失道歉。
typedef struct {
    char *word;
    char *cat;
    char *gen;
} ENTRY;  
ENTRY entry[linesInFile], *pEntry;  
int main(void)
{
    pEntry = &entry[0];
    //allocate memory 
    //call redefined newentry() function
    //use results of newentry() function
    //free memory
}  
#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;
}