第一个函数读取一个包含一堆’char’的文件,并将它们放在一个链表中。 它无法正常工作:(。
#include #include struct list { char val; struct list* next; }; typedef struct list element; int lcreate(char* fname, element* list); int ldelete(element* list); int linsert(char a, char b, element* list); int lremove(char a, element* list); int lsave(char* fname, element* list); int lcreate(char* fname, element* list) { element* elem = list; char c = 0; FILE * file = NULL; file = fopen(fname, "r"); while ((c = getc(file)) != EOF) { if(list == NULL) { list = (element*)malloc(sizeof(element)); if(list == NULL) { return 0; } list->val = c; } else { elem->next=(element*)malloc(sizeof(element)); elem = elem->next; elem-> val = c; } } fclose(file); elem->next = NULL; return 1; } int main(void) { int i = 0; element * list = NULL; lcreate("list.txt", list); for(i = 0; ival); list = list->next; } return 0; }
修复了’file’为空的问题。
一个明显的问题就在这里:
FILE * file = NULL; fopen(fname, "r");
为了使fopen
能够完成很多工作,你需要将fopen
的结果赋给你的FILE *
:
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);
file
为NULL
,您永远不会为其分配文件句柄。
在main
函数中,您还将按值传递给lcreate
。 在lcreate()
函数中,您将覆盖list
的本地副本,而不是更改main函数中list
的值。 由于list
初始化为NULL
,因此在调用list->val
。
是的 – 其他人对FILE
指针的说法,并且按值传递而不是引用lcreate()
,是真的。
你也没有从lcreate()
返回列表的大小 – 你应该通过返回值或指针参数返回它。
您试图在main()
函数中迭代列表4次,但列表中可能少于4个项目。 如果list
为NULL,最终printf()
将导致分段错误。
如果在进行这些更改后仍然存在问题,我建议您在代码中添加跟踪,以确定何时发生分段错误。
更新:
还要记得在遍历列表后释放你已经分配的内存,否则你最终会出现内存泄漏(虽然实际上这对你来说不是一个问题,因为程序结束了,但释放内存是进入的好习惯)。
我也可以看到另外一个问题。 在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
不会是非null但是elem
仍然是null所以elem-> next的赋值会尝试依赖空指针,从而导致分段错误(顺便说一句,这意味着你试图访问内存,尚未分配给您的流程): –
else { elem->next=(element*)malloc(sizeof(element));
正如其他人指出的那样,你也没有将list
返回到main,所以当你点击printf()循环时它仍然是NULL。
最后,在查看这些问题时,调试器是您的朋友。 您将确切地看到哪条线触发了seg故障以及变量的状态。
通过检查非null pinter来检查malloc是否成功会很好。 此外,您可能希望在while之外分配head / first链接,以避免每次在while循环中对头进行空检查。 当然,这些都是优化,万一你的链表变得非常大!
以上就是c/c++开发分享为什么这个C链表程序会出现“分段错误”?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/522044.html