C语言的链表(显然malloc不想成为我的朋友)

C语言的链表(显然malloc不想成为我的朋友),c,linked-list,C,Linked List,昨天晚上,我很高兴自己在第一次尝试时没有出现任何错误或警告!但是,当然,我换了一堆填充物,把它搞砸了。。。 当我尝试gdb它时,this.ytxt中的列表似乎可以加载到内存中。我认为问题在于写它。现在。它再次工作,但只写入文件的第一行。我注释掉了整个函数和printf'd测试标记,但仍然无法理解。 其思想是从文件中读取可变数量的行,并成对打印。(实际上 这本应该像学习抽认卡一样,但我从来没有想到这一部分。) #包括 #包括 #包括 结构成员{//这模拟字典 char键[20];//并将每个单词+

昨天晚上,我很高兴自己在第一次尝试时没有出现任何错误或警告!但是,当然,我换了一堆填充物,把它搞砸了。。。 当我尝试gdb它时,this.ytxt中的列表似乎可以加载到内存中。我认为问题在于写它。现在。它再次工作,但只写入文件的第一行。我注释掉了整个函数和printf'd测试标记,但仍然无法理解。 其思想是从文件中读取可变数量的行,并成对打印。(实际上 这本应该像学习抽认卡一样,但我从来没有想到这一部分。)

#包括
#包括
#包括
结构成员{//这模拟字典
char键[20];//并将每个单词+定义对链接到下一对。
char-def[20];
结构成员*ptr;
};
结构成员*根;
结构成员*curr;
文件*f;
int fill_list(){//用下面两行
curr=根;
char this[20];//文件*f
while(EOF){
如果(!fgets(this,20,f))断裂;
strcpy(curr->key,this);
如果(!fgets(this,20,f))断裂;
strcpy(curr->def,this);
curr=curr->ptr;
curr=malloc(sizeof(结构成员));
curr->ptr=0;
}
返回0;
}
全部无效{
curr=NULL;
while(curr!=根){
curr=根;
而(curr->ptr)curr=curr->ptr;
免费(货币);
}
}
int terminate(inti){//终止函数关闭文件并
free_all();//释放malloc的内存,然后返回main func的
fclose(f);//返回值。
返回i;
}
int main(){
f=fopen(“this.txt”,“r”);
如果(!f)返回-1;
root=malloc(sizeof(结构成员));
root->ptr=NULL;
填写清单();
curr=根;
如果(电流!=0){
while(curr!=0){
printf(“%s”,当前->键);
curr=curr->ptr;
}
}
全部免费;
返回终止(0);
}
填充列表()
中,您错误地分配了对象

curr=root;

// now curr is a copy of root->ptr
curr=curr->ptr;

// curr allocated properly, but not attached to root at all!
curr = malloc(...)
一些可能的错误:

没有名为“this”的变量。“这个”是C++保留字。(如果您是以C语言编译,可能还可以)

您的free_all()函数看起来可疑。我看了几眼才弄明白发生了什么事。看起来您正试图通过遍历到尾部、取消分配最后一个节点并再次从根的顶部开始来释放链表。与以线性方式释放相比,这将具有n平方性能。我想你应该这样说:

void free_all()
{
    struct member* curr = root;
    while (curr)
    {
        struct member* next = curr->ptr;
        free(curr);
        curr = next;
    }
}

详细阐述乍得的答案,你可以:

int fill_list(){                //Fill each member struct with next two lines of
    struct member *new_mem;
    curr=root;
    char this[20];              //FILE *f
    while(1){ /* relying on the breaks below to exit the loop */
        if(!fgets(this,20,f)) break;
        strcpy(curr->key,this);
        if(!fgets(this,20,f)) break;
        strcpy(curr->def,this);
        /* create the new member */
        new_mem=malloc(sizeof(struct member));
        /* set the new member's next ptr to NULL */
        new_mem->ptr = NULL;
        /* set the current member's next to the new member */
        curr->ptr=new_mem;
        /* current is now the new member */
        curr = new_mem;
    }
    return 0;
}
编辑:我想我应该补充一点,如果我要对你的代码做一些轻微的修改,这就是我要做的。如果我从头开始做,我就不会这样构造循环,也不会有不必要的全局变量,比如curr。sarnold也提出了同样的观点,即只有一个临时缓冲区。更不用说你在列表中的最后一个条目可能是无效的;只有在成功地将两个字符串读入两个临时缓冲区后,才能分配列表中的下一个成员条目,这可能是一个更好的主意

int fill_list(){                //Fill each member struct with next two lines of
    curr=root;
    char this[20];              //FILE *f
    while(EOF){
        /* ... */
您的
while(EOF)
循环永远不会在此终止--
EOF
stdio.h
(-1)
中定义:

在您自己的程序中重新定义
EOF
是不明智的

如果您确实想要无限循环,请使用
while(1)
for(;;)
;这两个都是非常明显的无限循环,这两个都是无限循环的常见C语言习惯用法。最好是将循环的退出条件重新写入
while()
,但有时这很困难。(
do{/*foo*/}while()
有时是完美的解决方案,在这里可能更好。)

我不确定您应该做什么来修复
while()
循环条件,因为我不完全确定它应该做什么:

while(EOF){
    if(!fgets(this,20,f)) break;
    strcpy(curr->key,this);
    if(!fgets(this,20,f)) break;
    strcpy(curr->def,this);
您也可以直接阅读
curr->key
curr->def
。(如果您想在出现错误时保持对象的一致性,读入临时存储是有意义的,但您需要两个临时变量,并在两个IO命令后更新值。由您决定。)


在这一小段中,您用下一个节点的值覆盖了
curr
指针。然后分配一个新节点并再次重写
curr
指针。然后将新分配的对象中的
curr->ptr
指针清空。
curr
对象现在具有未初始化的
curr->key
curr->def
字符数组。这是故意的吗?(允许半初始化的对象存在于程序中通常会导致灾难。)

谢谢,我应该改为*curr=malloc(…)吗?如果我看起来很笨,我以前从未尝试过把malloc的东西联系起来,非常感谢。这是有道理的!它当然比我编织的网络简单。哇!你是我的英雄!成功了!这得到了一些线回来,仍然有seg故障,但我更接近,现在我知道什么样的事情要找。比以前更多了真的吗?有了这个补丁和selbie的,我就可以运行了。编辑:刚刚意识到你在4分钟前尝试了selbie的代码。你的代码正确保存了文件行,他的代码消除了segfault并准确运行。非常感谢,我会投赞成票,但我甚至没有足够的代表点数来为你投票。谢谢你。是的,循环会随着中断而退出,EOF并不重要,我只是厌倦了while(1)并决定把事情弄混一点,我想如果我不正确地关闭循环,可能会有十几种异常情况会杀死我的计算机ram,但嘿,有时候我对“足够好”感到满意。至于在curr上的文字,谢谢,我在一分钟前刚刚解决了这个问题,它修复了fill0函数,顺便说一下,我不确定我是否应该留下深刻的印象
/* End of file character.
   Some things throughout the library rely on this being -1.  */
#ifndef EOF
# define EOF (-1)
#endif
while(EOF){
    if(!fgets(this,20,f)) break;
    strcpy(curr->key,this);
    if(!fgets(this,20,f)) break;
    strcpy(curr->def,this);
    curr=curr->ptr;
    curr=malloc(sizeof(struct member));
    curr->ptr=0;
}