大一,刚开始学数据结构,用c语言浅浅写了一个简单的学生信息管理系统
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
int id;
char name[10];
}Student;
typedef struct LNode
{
Student stu;
struct LNode *next;
}LNode,*LinkList; //LNode等价于struct LNode,LinkList等价于struct LNode* ,即LinkList 与LNode* 两种写法等价,都是表示一个指向结构体的指针类型
//创建单链表
void initLinkList(LNode* list); //list就是一个节点,函数头中的list均为形参,只是表示一个LNode类型的指针变量
//录入数据
void insertList(LNode* list);
//展示数据
void showList(LNode* list);
//删除数据
void deleStudent(LNode* list);
//查找数据
void getStudent(LNode* list,int i);
//根据学号查找学生数据
LNode* getStudentInform(LNode* list,int id);
//根据姓名查找学生数据
LNode* getStudentName(LNode* list,char name[10]);
//删除最后元素
void deleLastStudent(LNode* list);
//后插操作
void insertFromLastById(LNode* list,int i);
//插入数据(按位插入)
void insertData(LNode* list);
//插入数据(按学号插)
void insertNextNode(LNode* list);
//插入数据(按姓名插)
void insertNextName(LNode* list);
//更新数据
void updataStudent(LNode* list,int i);
int main()
{
LinkList list=(LinkList)malloc(sizeof(LNode));
initLinkList(list);//创建单链表
while(1){
printf("-------------------------------------------------------\n");
printf("---------------------菜 单-------------------\n");
printf("-------------------------------------------------------\n");
printf("---------------------请输入操作序号:------------------\n");
printf("---------------------1、录入学生信息-------------------\n");
printf("---------------------2、展示学生信息-------------------\n");
printf("---------------------3、删除学生信息-------------------\n");
printf("---------------------4、查询学生信息-------------------\n");
printf("---------------------5、修改学生信息-------------------\n");
printf("---------------------6、插入学生信息-------------------\n");
printf("---------------------0、退 出-------------------\n");
printf("-------------------------------------------------------\n");
int flag;
scanf("%d",&flag);
int i=0;
switch(flag){
case 0:
printf("正在退出......\n");
return 0;
case 1:
insertList(list);//录入数据
break;
case 2:
showList(list);//展示数据
break;
case 3:
deleStudent(list);//删除数据
break;
case 4:
printf("请输入查找方式:\n");
printf("1、按学号查找\n");
printf("2、按姓名查找\n");
scanf("%d",&i);
if(i==1||i==2){
getStudent(list,i);
}else{
printf("您输入的方式有误!\n");
}
i=0;
break;
case 5:
printf("请输入修改方式:\n");
printf("1、按学号修改\n");
printf("2、按姓名修改\n");
scanf("%d",&i);
if(i==1||i==2){
updataStudent(list,i);
}else{
printf("您输入的方式有误!\n");
}
i=0;
break;
case 6:
printf("请输入插入方式:\n");
printf("1、按学号插入\n");
printf("2、按姓名插入\n");
printf("3、按位置插入\n");
scanf("%d",&i);
if(i==1){
insertNextNode(list);//插入数据(按学号插)
}else if(i==2){
insertNextName(list);//插入数据(按姓名插)
}else if(i==3){
insertData(list);//插入数据(按位插入)
}else{
printf("您输入的方式有误!\n");
}
i=0;
break;
default:
printf("您输入的操作序号有误!请重新输入!\n");
}
}
return 0;
}
//创建单链表
void initLinkList(LNode* list)
{
list->next=NULL; //指针初始化
}
//录入数据
void insertList(LNode* list)
{
LNode* r; //定义尾指针
r=list;
int n;
printf("请输入要录入数据的个数:\n");
scanf("%d",&n);
printf("请输入要录入的学生的学号和姓名:\n");
while(n--){ //循环进行n次
LNode* p=(LNode*)malloc(sizeof(LNode)); //malloc 函数返回的是 void * 类型, malloc的返回值是一个指向空间首地址的指针,如果分配成功,返回一个非空指针。因此要进行类型转换
if(p==NULL){ //p是指向新创建的节点的指针
return;
}
scanf("%d%s",&p->stu.id,p->stu.name);
p->next=NULL;
r->next=p; //把p的指针域赋值为null,原来尾指针指向p,这样就将p成功链接到头指针后面了
r=p; //此时p就成了尾指针,把r地址修改成p
}
printf("录入数据成功!\n");
}
//展示数据
void showList(LNode* list)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
LNode* p=list->next; // list->next中存放的是地址,只能将地址赋给一个指针变量
while(p!=NULL){
printf("学号:%d,姓名:%s\n",p->stu.id,p->stu.name);
p=p->next;
}
}
//查找数据
void getStudent(LNode* list,int i)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
LNode* p=NULL;
if(i==1){
int id;
printf("请输入要查找的学号:\n");
scanf("%d",&id);
p=getStudentInform(list,id);
}else{
printf("请输入要查找的姓名:\n");
char name[10];
scanf("%s",name);
p=getStudentName(list,name);
}
if(p){
printf("查找成功!\n");
printf("学号:%d,姓名:%s\n",p->stu.id,p->stu.name);
}
}
//根据学号查找学生数据
LNode* getStudentInform(LNode* list,int id)
{
LNode* p=list->next;
while(p!=NULL&&p->stu.id!=id){
p=p->next;
}
if(p==NULL){
printf("您输入的学号有误!\n");
}
return p;
}
//根据姓名查找学生数据
LNode* getStudentName(LNode* list,char name[10])
{
LNode* p=list->next;
while(p!=NULL&&strcmp(p->stu.name,name)!=0){
p=p->next;
}
if(p==NULL){
printf("您输入的姓名有误!\n");
}
return p;
}
//删除数据
void deleStudent(LNode* list)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
printf("请输入要删除的学生学号:\n");
int id;
scanf("%d",&id);
//查找学生数据,根据学号,返回节点p
LNode* p=getStudentInform(list,id);
//如果删除的节点是最后一个就要遍历
if(p->next==NULL){
deleLastStudent(list);
return;
}
LNode* q=p->next; //q是指针,不是q是LNode类型,是q指向LNode类型的变量
p->stu=q->stu; //删除的本质就是复制后一个节点的数据将要删除节点的数据覆盖,并将要删除节点的指针域改为指向后面第二个节点,相当于将后一个节点内容复制给要删除节点之后,跨过后一个节点,去连接后面第二个节点
/*q=q->next;q只是一个临时指针后面不会用到,这样写没用,要达到删除的效果应该修改p,为节省空间释放q(不必须)*/
p->next=q->next;
free(q);
printf("删除成功!\n");
showList(list);
}
//删除最后元素
void deleLastStudent(LNode* list)
{
LNode* s=list;
LNode* pt=s->next; //采用双指针的办法
while(pt->next!=NULL){
s=s->next;
pt=s->next;
}
s->next=pt->next;
printf("删除成功!\n");
showList(list); //因为在函数中还要再次用到指针变量 list,因此引入和 list完全等价的指针变量 s,从而使list的值保持不变
}
//插入数据(按位插入)
void insertData(LNode* list)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
printf("请输入要插入数据的位置:\n");
int i;
scanf("%d",&i);
//创建函数进行后插操作
insertFromLastById(list,i);
showList(list);
}
//后插操作
void insertFromLastById(LNode* list,int i)
{
LNode* p=list;
int j=0;
while(p!=NULL&&j<i-1){
p=p->next;
j++;
}
if(p==NULL){
printf("您输入的位置有误!\n");
return;
}
LNode* s=(LinkList)malloc(sizeof(LNode));
printf("请输入要插入学生的学号和姓名:\n");
scanf("%d%s",&s->stu.id,s->stu.name);
s->next=p->next;
p->next=s;
printf("插入成功!\n");
}
//插入数据(按学号插)
void insertNextNode(LNode* list)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
printf("请输入要在哪个学号后插入:\n");
int id;
scanf("%d",&id);
LNode* p=getStudentInform(list,id);
LNode* s=(LinkList)malloc(sizeof(LNode));
printf("请输入要插入学生的学号和姓名:\n");
scanf("%d%s",&s->stu.id,s->stu.name);
s->next=p->next;
p->next=s;
printf("插入成功!\n");
showList(list);
}
//插入数据(按姓名插)
void insertNextName(LNode* list)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
printf("请输入要在哪个姓名后插入:\n");
char name[10];
scanf("%s",name);
LNode* p=getStudentName(list,name);
LNode* s=(LinkList)malloc(sizeof(LNode));
printf("请输入要插入学生的学号和姓名:\n");
scanf("%d%s",&s->stu.id,s->stu.name);
s->next=p->next;
p->next=s;
printf("插入成功!\n");
showList(list);
}
//更新数据
void updataStudent(LNode* list,int i)
{
if(list->next==NULL){
printf("对不起,您没有输入数据!\n");
return;
}
LNode* p=NULL;
if(i==1){
printf("请输入要更改的学生的学号:\n");
int id;
scanf("%d",&id);
p=getStudentInform(list,id);
}else{
printf("请输入要更改的学生的姓名:\n");
char name[10];
scanf("%s",name);
p=getStudentName(list,name);
}
if(p){
printf("请重新输入学生的学号和姓名:\n");
scanf("%d%s",&p->stu.id,p->stu.name);
printf("修改成功!\n");
showList(list);
}
}
有参考别人的写法,也加了自己的东西到里面,是一边写一边改进的,写到后面不想改了,所以删除只用了学号查找这一种方式
以及我没有考虑按姓名查找若有重名的情况,因此按姓名查询得到只有最前面符合条件的一条结果
还有就是录入姓名用的scanf,英文名有空格的情况就不适用
刚学,有瑕疵,且作分享,还请多多指教hhh