Twistzz.965 2022-10-20 13:57 采纳率: 40%
浏览 70
已结题

c语言用链表删除头节点的问题

自学完c语言尝试写一个学生管理系统
用代码块功能插入代码,请勿粘贴截图
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct         /*学生类型定义*/
{
 int sno;         /*学号*/      
 char sname[8];    /*姓名*/
 int score;       /*成绩*/

}Student;

typedef struct Node
{
 Student data;
 struct Node *next;
}LinkList;



LinkList  *createTailList ()                        /*以尾插法建立带头节点的单链表*/
{   
    int x;
   LinkList * head=NULL;           /遍历找last
do{
   printf("输入学生学号\n");
   scanf("%d",&x);
   if(x!=0)    //输出0时结束录入信息
   {
      LinkList *p=(LinkList*)malloc(sizeof(LinkList));//建立学生信息空间
      p->data.sno=x;
         printf("输入学生姓名,成绩。\n");
         scanf("%s %d",&(p->data.sname),&(p->data.score)); 
          p->next=NULL;
         LinkList *last=head;
         if(last)
         {
            while(last->next)
            {
               last=last->next;
            }
            last->next=p;
         }
         else
         head=p;
        
      
   }
}while (x!=0);
return head; //返回头地址
}


//输出函数
void printElem(LinkList *head)   
{   
 LinkList *p=head;//指向head
printf("链表中所有的学生信息如下:\n");
   while (p)
 {
     printf("学号:%d,姓名:%s,成绩:%d\n",p->data.sno,p->data.sname,p->data.score); /*输出p的节点信息*/
      p=p->next;//指向下一个
   }
}

void menu()//菜单
{
 printf("请输入你需要实现的功能\n");
 printf("1.显示学生信息\n");
 printf("2.修改学生信息\n");
 printf("3.插入学生信息\n");
 printf("4.删除学生信息\n");
 printf("5.退出系统\n");

}


void fix(LinkList *head)//修改学生信息
{
   int o1=0;
   LinkList *t2=head;
   printf("输入被修改的学生的学号\n");
  scanf("%d",&o1);
  for(t2;t2;t2=t2->next)
  {
   if(t2->data.sno==o1)
   {printf("输入新的姓名与成绩,中间用空格隔开\n");
   scanf("%s %d",&(t2->data.sname),&(t2->data.score));//赋值新的数据
   printf("修改完成\n");
   }
   
  
  }
}

void myinsert(LinkList *head)//插入节点,不能插入到头节点之前
{
   int k1=0;
   LinkList *t3=head;
   printf("输入被插入的学生的学号\n");
   scanf("%d",&k1);
   LinkList *n;
   LinkList *t31=head->next;
   while (t31&&t31->data.sno!=k1)//不能在头节点前插入
   {
      t3=t31;
      t31=t31->next;
   }
   if(!t31)//坐标
   {
      printf("无后驱学生,将插入到最后\n");
     
   }
 
   printf("请输入插入学生的学号,姓名,成绩,中间用空格\n");
   n=(LinkList *)malloc(sizeof(LinkList));
   scanf("%d %s %d",&(n->data.sno),&(n->data.sname),&(n->data.score));
   n->next=t31;
   t3->next=n;
}


void delete(LinkList *head)//删除节点
{
  int w=0;
   printf("请输入要删除的学生的学号\n");
   scanf("%d",&w);
   LinkList *t1;
   LinkList *q;
for(q=NULL,t1=head;t1;q=t1,t1=t1->next)// t1会指向要删除的节点;
{
   if(t1->data.sno==w)//删除的不是头节点
      {if(q)
         {
            q->next=t1->next;
         
         }
         else
         {
      head=t1->next;//要删除的是头节点
     
         }
         printf("删除完毕\n");
         free (t1); 
         t1=NULL;
   
         
         break;
         

      }
}
printElem(head) ;

}





int main(int argc,char *argv[ ])
{     
  int a;
printf("请输入学生信息\n");
   LinkList *head=createTailList(*head ) ; 
    system("pause");//暂停  输入其他案件继续执行后续的代码
 system("CLS");//清屏 清除之前的输入提示等等 使页面干净
  
  menu();
   while(1)
   {
    printf("请选择所需功能:");
   scanf("%d",&a);
    switch(a)
   {
    case 1:
           printElem(head);//输出
    menu();
     break;


   case 2:
       fix(head);//修改
    menu();
     break;


   case 3:
           myinsert(head);//插入
    menu();
     break;


     case 4:
           delete(head);//删除
    menu();
     break;

    


     case 5://退出系统
            exit(0);
      
   break;
    
   
    
   }
}


}
 


在之前写过这个一模一样的,只不过没用函数,而是一长串的写下来,删除模块可以删除掉头结点的,而且不会出现垃圾值,但是用了函数后,删除头节点是不行的,我已经释放了头结点的内存,但那段内存仍然被垃圾值填充,并没有消失。我试着在删除完节点的函数中继续添加了一个输出链表的函数,这个输出是正常的,但是你在菜单页面让他再次输出,就会出现头节点并没有消失,而是被垃圾值填充。
我的解答思路和尝试过的方法 :我尝试过在释放内存后,让指向头结点的指针指向null,但仍然无济于事。
我想要达到的结果 :头节点可以正常删除,直接消失,而不是出现垃圾值。
  • 写回答

2条回答 默认 最新

  • wwc2017 2022-10-20 15:36
    关注
    • 原因在于delete函数中,是把形参head的值设为了null,并没有影响函数外的实参head。

    • C语言的函数中通过指针操作数据,给人一种假象,好像传递指针就是引用变量本身了似的。
      而实际上,传递指针依然传递的是指针的值,形参与实参依旧是两个不同的指针变量,只不过他们的值(也就是指针指向的地址)相同,让它们通过*和->解引用后能指向相同的地方。

    • 对于你这个问题,可以考虑给delete加个返回值,把形参head返回到外部,就能判断是否所有节点都删除了。
      也可以用更高一级的指针作为形参,

    void delete(LinkList **head)//删除节点
    

    然后传入的实参是&head。这样在函数里通过*head = null也能给实参赋值。不过这样会让程序更难看懂,不推荐用二级指针。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 10月29日
  • 已采纳回答 10月21日
  • 创建了问题 10月20日

悬赏问题

  • ¥15 用lstm来预测股票价格
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上