练习链表的删除出现了问题求助!

完美教父 2019-03-12 05:47:46
以下是我练习链表创建,输出和删除,创建和输出都可以,就是删除这一块出问题。请帮我看看是哪里出了问题,请指点一下,谢谢!现在一运行就出现如下图的报错:


#include <stdio.h>
#include <malloc.h>

typedef struct NUM
{
int a;
struct NUM *next;

}num,*pnum;

pnum c_list(void); //创建链表
void s_list(pnum head); //输出链表
void d_list(pnum head , int a); //删除链表(删除指定的值)

int main(void)
{
pnum p;
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, 2); //删除链表(删除值为2的节点)
return 0;
}

//创建链表
pnum c_list(void)
{
pnum p;
pnum pend; //尾节点
int i;
pnum head; //首节点,指向头节点
head = (pnum)malloc(sizeof(pnum));
head->next = NULL;
p = head;
for(i=0; i < 3; i++)
{
pend = (pnum)malloc(sizeof(pnum));
pend->a = i;
pend->next = NULL;
p->next = pend;
p = p->next;
}
return head;
}

//输出链表
void s_list(pnum head)
{
pnum p;
p = head; //接收传过来的首节点
while(NULL != p->next)
{
printf("%d ",p->next->a);
p = p->next;
}
printf("\n");
}

//删除链表
void d_list(pnum head , int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while(NULL != p->next)
{
if(p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
p = p->next;
}
}
...全文
157 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
拥抱Linux 2019-03-12
  • 打赏
  • 举报
回复
问题解决了就好。
不过,对上面的代码和运行的情况,我还是有疑问,具体的疑问已经另外提了一个提问帖,就不在这里展开了。
只是把刚刚在gdb里查找到的内存访问错误的信息发上来给大家看看,问题的原因还是在于删除函数的逻辑错误,最后的free(q);并没有问题,有问题的是最后一次的while( NULL != p->next ),因为这个时候p已经被赋值为NULL了,所以它不能去指向任何一个next成员,于是出现内存段访问错误。截图如下:


希望能共同学习提高。至于malloc的疑问,这里就不谈了。
完美教父 2019-03-12
  • 打赏
  • 举报
回复
谢谢你们,问题已解!如7楼所说!
完美教父 2019-03-12
  • 打赏
  • 举报
回复
引用 7 楼 jone浩 的回复:
内存越界了,导致free( )出错。修改malloc处,因为申请的内存大小不够,sizeof(pnum)大小为4。
//创建链表
pnum c_list(void)
{
pnum p;
pnum pend; //尾节点
int i;
pnum head; //首节点,指向头节点
//head = (pnum)malloc(sizeof(pnum)); //修改为如下:
head = (pnum)malloc(sizeof(num));
head->next = NULL;
p = head;
for(i=0; i < 5; i++)
{
//pend = (pnum)malloc(sizeof(pnum)); //修改为如下:
pend = (pnum)malloc(sizeof(num));
pend->a = i;
pend->next = NULL;
p->next = pend;
p = p->next;
}
return head;
}


感谢回复,解决了。问题正如你说。修改后可以了。
完美教父 2019-03-12
  • 打赏
  • 举报
回复
引用 6 楼 完美教父 的回复:
[quote=引用 5 楼 儿童节 的回复:][quote=引用 4 楼 完美教父 的回复:]
[quote=引用 3 楼 儿童节 的回复:]
最后的删除函数,改了一下,


void d_list(pnum head, int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while (NULL != p->next)
{
if (p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p = p->next;
}
}


为了查看结果,把main()里的输入输出也调整了一下,这个与出错的原因无关。



int main(void)
{
int a;
while (1 == scanf("%d",&a))
{
pnum p;
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, a); //删除链表(删除值为2的节点)
s_list(p); // 输出链表
}
return 0;
}


Linux环境测试截图,



至于删除函数里,是否删除完了就return退出,没有修改,因为和问题无关,要修改的话也很容易就不谈了。

如果满意的话,还请您及时给个赞,结贴给分吧。谢谢!
:)

感谢回复,我按你的修改运行还是一样的情况。[/quote]

刚刚做饭没对比改前改后有什么不一样,重新对比了一下,只是加了一个else关键字而已。我这边把你的代码复制过来,加上一个else之后运行,没问题啊。



能不能把你改后的代码和运行的情况截图来看看?
[/quote]好的,正在回家路上。到家就贴出来。谢谢你![/quote]

这是我按照你改后的代码
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

typedef struct NUM
{
int a;
struct NUM *next;

}num,*pnum;

pnum c_list(void); //创建链表
void s_list(pnum head); //输出链表
void d_list(pnum head , int a); //删除链表(删除指定的值)

int main(void)
{
pnum p = NULL;
int a;
while(1==scanf("%d",&a))
{
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, a); //删除链表(删除值为2的节点)
s_list(p);
}
return 0;
}

//创建链表
pnum c_list(void)
{
pnum p = NULL;
pnum pend = NULL; //尾节点
int i;
pnum head = NULL; //首节点,指向头节点
head = (pnum)malloc(sizeof(pnum));
head->next = NULL;
p = head;
for(i=0; i < 3; i++)
{
pend = (pnum)malloc(sizeof(pnum));
pend->a = i;
pend->next = NULL;
p->next = pend;
p = p->next;
}
return head;
}

//输出链表
void s_list(pnum head)
{
pnum p;
p = head; //接收传过来的首节点
while(NULL != p->next)
{
printf("%d ",p->next->a);
p = p->next;
}
printf("\n");
}

//删除链表
void d_list(pnum head , int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while(NULL != p->next)
{
if(p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p=p->next;
// p = p->next;
}
}
jone浩 2019-03-12
  • 打赏
  • 举报
回复
内存越界了,导致free( )出错。修改malloc处,因为申请的内存大小不够,sizeof(pnum)大小为4。 //创建链表 pnum c_list(void) { pnum p; pnum pend; //尾节点 int i; pnum head; //首节点,指向头节点 //head = (pnum)malloc(sizeof(pnum)); //修改为如下: head = (pnum)malloc(sizeof(num)); head->next = NULL; p = head; for(i=0; i < 5; i++) { //pend = (pnum)malloc(sizeof(pnum)); //修改为如下: pend = (pnum)malloc(sizeof(num)); pend->a = i; pend->next = NULL; p->next = pend; p = p->next; } return head; }
完美教父 2019-03-12
  • 打赏
  • 举报
回复
引用 5 楼 儿童节 的回复:
[quote=引用 4 楼 完美教父 的回复:]
[quote=引用 3 楼 儿童节 的回复:]
最后的删除函数,改了一下,


void d_list(pnum head, int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while (NULL != p->next)
{
if (p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p = p->next;
}
}


为了查看结果,把main()里的输入输出也调整了一下,这个与出错的原因无关。



int main(void)
{
int a;
while (1 == scanf("%d",&a))
{
pnum p;
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, a); //删除链表(删除值为2的节点)
s_list(p); // 输出链表
}
return 0;
}


Linux环境测试截图,



至于删除函数里,是否删除完了就return退出,没有修改,因为和问题无关,要修改的话也很容易就不谈了。

如果满意的话,还请您及时给个赞,结贴给分吧。谢谢!
:)

感谢回复,我按你的修改运行还是一样的情况。[/quote]

刚刚做饭没对比改前改后有什么不一样,重新对比了一下,只是加了一个else关键字而已。我这边把你的代码复制过来,加上一个else之后运行,没问题啊。



能不能把你改后的代码和运行的情况截图来看看?
[/quote]好的,正在回家路上。到家就贴出来。谢谢你!
拥抱Linux 2019-03-12
  • 打赏
  • 举报
回复
引用 4 楼 完美教父 的回复:
[quote=引用 3 楼 儿童节 的回复:]
最后的删除函数,改了一下,


void d_list(pnum head, int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while (NULL != p->next)
{
if (p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p = p->next;
}
}


为了查看结果,把main()里的输入输出也调整了一下,这个与出错的原因无关。



int main(void)
{
int a;
while (1 == scanf("%d",&a))
{
pnum p;
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, a); //删除链表(删除值为2的节点)
s_list(p); // 输出链表
}
return 0;
}


Linux环境测试截图,



至于删除函数里,是否删除完了就return退出,没有修改,因为和问题无关,要修改的话也很容易就不谈了。

如果满意的话,还请您及时给个赞,结贴给分吧。谢谢!
:)

感谢回复,我按你的修改运行还是一样的情况。[/quote]

刚刚做饭没对比改前改后有什么不一样,重新对比了一下,只是加了一个else关键字而已。我这边把你的代码复制过来,加上一个else之后运行,没问题啊。



能不能把你改后的代码和运行的情况截图来看看?
完美教父 2019-03-12
  • 打赏
  • 举报
回复
引用 3 楼 儿童节 的回复:
最后的删除函数,改了一下,


void d_list(pnum head, int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while (NULL != p->next)
{
if (p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p = p->next;
}
}


为了查看结果,把main()里的输入输出也调整了一下,这个与出错的原因无关。



int main(void)
{
int a;
while (1 == scanf("%d",&a))
{
pnum p;
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, a); //删除链表(删除值为2的节点)
s_list(p); // 输出链表
}
return 0;
}


Linux环境测试截图,



至于删除函数里,是否删除完了就return退出,没有修改,因为和问题无关,要修改的话也很容易就不谈了。

如果满意的话,还请您及时给个赞,结贴给分吧。谢谢!
:)

感谢回复,我按你的修改运行还是一样的情况。
拥抱Linux 2019-03-12
  • 打赏
  • 举报
回复
最后的删除函数,改了一下,


void d_list(pnum head, int a) //int a 接收删除指定的节点
{
pnum p;
pnum q; //用于指向需要删除的节点
p = head; //接收传过来的首节点
while (NULL != p->next)
{
if (p->next->a == a)
{
q = p->next;
p->next = q->next;
free(q);
q = NULL;
}
else
p = p->next;
}
}


为了查看结果,把main()里的输入输出也调整了一下,这个与出错的原因无关。



int main(void)
{
int a;
while (1 == scanf("%d",&a))
{
pnum p;
p = c_list(); //创建链表,并将链表首节点赋给P
s_list(p); //输出链表
d_list(p, a); //删除链表(删除值为2的节点)
s_list(p); // 输出链表
}
return 0;
}


Linux环境测试截图,



至于删除函数里,是否删除完了就return退出,没有修改,因为和问题无关,要修改的话也很容易就不谈了。

如果满意的话,还请您及时给个赞,结贴给分吧。谢谢!
:)
完美教父 2019-03-12
  • 打赏
  • 举报
回复
引用 1 楼 qq_42307333 的回复:
删除完了直接return吧,你这样写,如果要删除的元素是最后一个,就会出错吧,会对NULL操作

我试了直接return和break都不行。并且,我试了不删最后一个,删中间的也是一样的情况。使用vc6的调试看了一下逻辑好像也对呀。
就不知道是哪个环节错了!
qq_42307333 2019-03-12
  • 打赏
  • 举报
回复
删除完了直接return吧,你这样写,如果要删除的元素是最后一个,就会出错吧,会对NULL操作

69,370

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧