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都被释放了啊,里面没东西了,为什么还能指向下一个节点?