为什么这个C链表程序会给出';分段错误';?
第一个函数读取一个有一堆“char”的文件,并将它们放入一个链表中。它不工作:(为什么这个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-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));