C 斯特托克(我想)我能';我不明白
编辑:复制行为的最小编译代码 这段代码读取一个蹩脚的字典文件,以便尝试从中提取一些有趣的信息。每行转换为一个结构条目。总是提取单词,因此newentry()不会检查其单词参数的有效性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
#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指向的指针大小。@pouzzlersizeof(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;
}