c语言链表节点删除问题求解

这是一个删除结点并输出的程序,总共有三个链表
错误为:当删除最后一个链表也就是3时程序发生错误,停止运行。
求大家帮忙解解决!

#include <stdio.h>  
#define NUll 0
#include <stdlib.h>
struct stu
{
    char name[6];
    int xuehao;
    int grade;
    struct stu *next;
};
typedef struct stu STU;
main()
{
   STU *p,*p_start,*p2,*p_print,*p_charu,*p_charu2;
   int i,xuehao;
   //输入 
   for (i=0;i<3;i++)
   {
    p=(STU *)malloc(sizeof(STU));
    printf("请输入学生姓名:\n");
    scanf("%s",&p->name);
    printf("请输入学生的学号:\n");
    scanf("%d",&p->xuehao);
    printf("请输入学生的成绩:\n");
    scanf("%d",&p->grade);
    if (i==0)
    p2=p_start=p;
    else
    {
     p2->next=p;
     p2=p;
     if (i==2)
     p->next=NULL;
    }
   }

   //链表的删除 
   p_charu=p_start;
   printf("请输入要删除的学号\n");
   scanf("%d",&xuehao);
   while (1)
   {
    p_charu2=p_charu->next;
   if (p_charu->next->xuehao==xuehao)
       {
       p_charu->next=p_charu->next->next;
       free(p_charu2);
        break;
       } 
 if (p_charu->xuehao==xuehao)
    {
      p_start=p_charu->next;
      free(p_charu);
      break;    
    }
    p_charu=p->next;
   } 
}

4个回答

既然用C++,用cin cout代替printf scanf比较好,你这个格式有问题。

sm123m
sm123m 编译没有错误 c语言 用的环境是dev c++
接近 5 年之前 回复

while (1)
{
p_charu2=p_charu->next;
if (p_charu->next!=NULL && p_charu->next->xuehao==xuehao)
{
p_charu->next=p_charu->next->next;
free(p_charu2);
break;
}
if (p_charu->xuehao==xuehao)
{
p_start=p_charu->next;
free(p_charu);
break;

}
p_charu=p->next;
if (p_charu==NULL) break;
}


说实话,程序写的太垃圾了

你的问题在p_charu = p->next;这一句,p是你用来接收输入的,在你删除的部分没有任何关系,改成p_charu = p_charu->next;就可以了。
另外你的还有一个问题,就是如果删除了第一个后,你没有更新p_start,这会导致你在最后输出的时候,第一个是错误的。不信你可以试一下。
我重写了删除部分
1. 使用p_charu2保存当前节点的上一个节点,初始值为NULL,因为第一个节点没有上一个节点
2. 在while循环中判断当前节点是否为NULL,如果不为NULL,判断当前节点的学好是否等于需要删除的学号,如果是,判断是否p_charu2是否为NULL,即是否为第一个节点,如果不是,则设置当前节点的上一个节点的下一个节点为当前节点的下一个节点,这里有点绕,比如节点1,2,3,删除2,则设置1(2的上一个节点)的下一个节点为3(2的下一个节点),如果p_charu2为NULL,则是第一个节点,这更新p_start为p_charu的下一个节点。然后释放当前节点
3.设置p_charu2为当前节点
4.设置当前节点为当前节点的下一个节点,进入下一个循环
最后的输出部分也用while而没有固定节点个数,免得万一输入前面输入的不是3个,还需要更改这里的代码。下面的是完整代码

#include <stdio.h> 
#define NUll 0
#include <stdlib.h>
struct stu
{
    char name[6];
    int xuehao;
    int grade;
    struct stu *next;
};

typedef struct stu STU;

main()
{
    STU *p, *p_start, *p2, *p_print, *p_charu, *p_charu2;
    int i, xuehao;
    //输入 
    for (i = 0; i < 3; i++)
    {
        p = (STU *)malloc(sizeof(STU));
        printf("请输入学生姓名:\n");
        scanf("%s", &p->name);
        printf("请输入学生的学号:\n");
        scanf("%d", &p->xuehao);
        printf("请输入学生的成绩:\n");
        scanf("%d", &p->grade);

        if (i == 0)
            p2 = p_start = p;
        else
        {
            p2->next = p;
            p2 = p;
            if (i == 2)
                p->next = NULL;
        }
    }
    //printf("%d", p_start->next->next->next);
    //printf("%d", p_start->next->next->xuehao);
    //链表的插入 
    p_charu = p_start;
    printf("请输入要删除的学号\n");
    scanf("%d", &xuehao);
    p_charu2 = NULL;
    while(p_charu)
    {
        if (p_charu->xuehao == xuehao)
        {
            if (p_charu2 != NULL) p_charu2->next = p_charu->next;
            else p_start = p_charu->next;
            free(p_charu);
            break;
        }
        p_charu2 = p_charu;
        p_charu = p_charu->next;
    }
    //输出
    p_print = p_start;
    while(p_print)
    {
        printf("学生姓名为:%s\n", p_print->name);
        printf("学生的学号为:%d\n",  p_print->xuehao);
        printf("学生的分数为:%d\n",p_print->grade);
        p_print = p_print->next;
    }   
}
save4me
save4me 你逻辑上考虑的还是很认真的。如果回答对你的问题有帮助,请顶一下,如果问题解决了,请标记为答案,谢谢!
接近 5 年之前 回复
sm123m
sm123m 判断的次数是一样的吧 只要满足第一个条件 程序用指针进行操作以后就会执行break语句 ,就不会执行第二个了。
接近 5 年之前 回复
save4me
save4me 你说的对,你的第二个if处理了第一个的情况。因为学好不可能重复,你的两个if只可能有一种情况满足,如果把第二个if改成else if,这样是不是可以减少重复判断,提高程序的效率?
接近 5 年之前 回复
sm123m
sm123m 不过,第二个您说的那个问题,我不太认同,因为循环里面第二个if语句就是用来处理第一个的呀?
接近 5 年之前 回复
sm123m
sm123m 感谢回答!问题确实是你说的那个,哈哈,敲代码的时候粗心了一下! 初学者,写代码习惯不好,老喜欢犯这种低级错误,以后一定要多加注意!!!以此为鉴!
接近 5 年之前 回复

save4me的回答很详细,赞一个。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!