Twistzz.965 2022-10-24 17:33 采纳率: 40%
浏览 20

关于链表与指针的问题

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;//1
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;//1
        
      
   }
}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)//删除节点(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;
         

      }
}



}





int main(int argc,char *argv[ ])
{     
  int a;
printf("请输入学生信息\n");
   LinkList *head=createTailList() ; 
    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;
    
   
    
   }
}


}
 


已经修改过没问题,原来的问题是,如果要删除头节点(我这里的head里面是由数据的),已经释放了头节点的内存,但还是显示被任意填充。
void delete(LinkList **head)//删除节点(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;
         

      }
}


```将删除函数中的 指针值的传递改为了指针的地址传递,运行正常

###### 就我现在的问题是:在没改之前,子函数传进来的是主函数那个head接受的地址吧,相当于值传递了,在子函数中虽然可以对链表做了修改,比如删除第一个节点,虽然释放了head的空间,但主函数的head的指向仍然没有变,这就解释了为什么会有乱码问题,因为这时候主函数的head类似一个野指针吧,但是他只会出现删除的头节点乱码,但后续信息是存在的,但确实释放了头节点的信息,不应该已经将那个链表的链摧毁了吗,即头节点的那个next与data都被释放了啊,里面没东西了,为什么还能指向下一个节点?
  • 写回答

2条回答 默认 最新

  • 日向晚,声声慢 2022-10-24 23:02
    关注

    你可以参考我博客中的通讯录,单链表,顺序表的实现都有,还存在文件操作。希望帮到你

    评论

报告相同问题?

问题事件

  • 创建了问题 10月24日

悬赏问题

  • ¥15 python 打包sdk不成功,如何解决?
  • ¥15 adv找不到可向其添加属性的有效项目。
  • ¥15 cesm2.2.0移植问题。./manage_externals/checkout_externals
  • ¥15 ntp对时中的时标问题
  • ¥35 pcb上电后,不一会儿,主控过热烧毁
  • ¥15 ubuntu,windows,文件传输,Linux
  • ¥15 北斗定位,cors,无人机,图传
  • ¥15 Unity热更新框架问题
  • ¥20 如何提交icra的附录.应该在哪里提交
  • ¥20 请教yolov8出现如下bug怎么办