为什么这个C链表程序会给出';分段错误';?

为什么这个C链表程序会给出';分段错误';?,c,linked-list,C,Linked List,第一个函数读取一个有一堆“char”的文件,并将它们放入一个链表中。它不工作:( #包括 #包括 结构列表{ char-val; 结构列表*下一步; }; typedef结构列表元素; int lcreate(字符*fname,元素*list); int L删除(元素*列表); int linsert(字符a、字符b、元素*列表); int lremove(字符a,元素*列表); int lsave(字符*fname,元素*list); int lcreate(字符*fname,元素*list)

第一个函数读取一个有一堆“char”的文件,并将它们放入一个链表中。它不工作:(

#包括
#包括
结构列表{
char-val;
结构列表*下一步;
};
typedef结构列表元素;
int lcreate(字符*fname,元素*list);
int L删除(元素*列表);
int linsert(字符a、字符b、元素*列表);
int lremove(字符a,元素*列表);
int lsave(字符*fname,元素*list);
int lcreate(字符*fname,元素*list){
元素*elem=列表;
字符c=0;
FILE*FILE=NULL;
file=fopen(fname,“r”);
而((c=getc(文件))!=EOF)
{
if(list==NULL){
list=(element*)malloc(sizeof(element));
if(list==NULL){
返回0;
}
列表->val=c;
}
否则{
元素->下一个=(元素*)malloc(元素大小);
元素=元素->下一步;
elem->val=c;
}
}
fclose(文件);
elem->next=NULL;
返回1;
}
内部主(空){
int i=0;
元素*list=NULL;
lcreate(“list.txt”,list);
对于(i=0;ival);
列表=列表->下一步;
}
返回0;
}

修复了“file”为null的问题。

file
null
,并且您从未为其分配文件句柄。

一个明显的问题就在这里:

FILE * file = NULL;

fopen(fname, "r");
要使
fopen
完成很多工作,您需要将
fopen
的结果分配给您的
文件*

file = fopen(fname, "r");
编辑:由于您使用的是C语言,因此无法通过引用传递指针。或者,您可以将指针传递给指针:

int lcreate(char *fname, element **list) {

     // ...
     *list = malloc(sizeof(element));
     (*list)->next = null;
     (*list)->val = c;
// ...
}
基本上,
lcreate
中的所有代码都需要引用
*list
,而不仅仅是
list
。或者,您可以将指向现有列表的指针作为输入,并返回指向该列表的指针,因此在
main
中,您将有如下内容:
list=lcreate(“list.txt”,list)

是的——其他人所说的关于
文件
指针,以及按值传递
列表
,而不是引用
lcreate()
,是正确的

您也没有从
lcreate()
返回列表的大小——您可能应该通过返回值或指针参数返回此值

您正试图在
main()
函数中遍历列表4次,但列表中的项目可能少于4项。如果
list
为空,则
printf()
最终将导致分段错误

如果在进行这些更改后仍然存在问题,我建议在代码中添加跟踪,以确定分段错误发生的时间点

更新:


另外,请记住在遍历列表后释放已分配的内存,否则将导致内存泄漏(虽然在实践中,随着程序即将结束,这对您来说并不是一个问题,但释放内存是一个好习惯)函数,您正在覆盖
list
的本地副本,而不是更改主函数中
list
的值。由于
list
初始化为
NULL
,因此调用
list->val
时,您将得到一个segfault。我还可以看到另一个问题。在
lcreate()的while语句中
if语句malloc的true子句保留一些内存并将其分配给
list
但是
elem
不会更新

while ((c = getc(file)) != EOF)
{
    if(list == NULL) {
        list = (element*)malloc(sizeof(element));
        if(list == NULL) {
            return 0;
        }
        list->val = c;
    }
    else {
下一次通过while循环
list
将不会是非空的,但是
elem
仍然是空的,因此elem->Next的赋值尝试遵从空指针,从而导致分段错误(顺便说一句,这意味着您试图访问尚未分配给进程的内存):-

正如其他人指出的那样,您也不会将
list
返回到main,因此当您点击printf()循环时,它仍然是空的


最后,在研究这些问题时,调试器是您的朋友。您将确切地看到哪一行触发seg故障以及变量的状态是什么。

最好通过检查非空pinter来检查malloc是否成功。
此外,您可能希望在while之外分配head/first链接,以避免每次在while循环中对head进行空检查。当然,这些都是优化,以防您的链接列表变得非常大!

好的,那么我如何在lcreate中覆盖列表?谢谢!@ron-将双指针传递到
列表
,即
元素**list;lcreate(“list.txt”,list);
。然后在
lcreate
方法中,按如下方式分配它:
*list=malloc(…)
。这将确保调用者看到被调用者所做的更改。不要忘记
elem=list
分配了一个值。如果您希望
elem
list
更新时更新
elem
,则需要将原始代码中的
elem
更改为
elem=&list
,或者
element**elem=list
>在杰瑞的版本中。
while ((c = getc(file)) != EOF)
{
    if(list == NULL) {
        list = (element*)malloc(sizeof(element));
        if(list == NULL) {
            return 0;
        }
        list->val = c;
    }
    else {
else {
    elem->next=(element*)malloc(sizeof(element));