数据结构 study 4: 学生信息管理
学生信息包括:
姓名
学号
性别
年龄
班级
健康状况
每个学生的学生信息,整体作为一个元素,插入一个线性单链表中
之前的 线性单链表中的元素是 一个整形的数据,
现在线性单链表中的元素 是一个结构体。
同时可以将线性单链表中的所有元素,保存到一个文件中去。
(参考高一凡 数据结构)
删除信息 和修改信息,比较重要。
修改信息的时候,因为信息修改了,涉及到重新排序的问题。
问题描述
page48
#define NAMELEN 8 /* 姓名最大长度 */
#define CLASSLEN 4 /* 班级名最大长度 */
struct stud /* 记录的结构 */
{
char name[NAMELEN+1]; //姓名
long num;
char sex;
int age;
char Class[CLASSLEN+1];//班级名称
int health;
};
struct stud student[N]={{"王小林",790631,'m',18,"计91",0},
{"陈红",790632,'f',20,"计91",1},
{"刘建平",790633,'m',21,"计91",0},
{"张立立",790634,'m',17,"计91",2}}; /* 表的初始记录 */
char sta[3][9]={"健康 ","一般 ","神经衰弱"}; /* 健康状况(3类) */
简单的例子:
/* c1.h (程序名) */
#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include <sys/io.h> /* eof() */
#include<math.h> /* floor(),ceil(),abs() */
#include<pthread.h> /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
#define NAMELEN 16 /* 姓名最大长度 */ //8
#define CLASSLEN 16 /* 班级名最大长度 */ //4
struct stud /* 记录的结构 */
{
char name[NAMELEN];
long num;
char sex;
int age;
char Class[CLASSLEN];
int health;
};
//{"张立立",790634,'m',17,"计91",2}
typedef struct stud ElemType; /* 链表结点元素类型为结构体 */
typedef struct LNode {
ElemType data;
struct LNode *next ;
}LNode, *LinkList,*LinkNode ;
int create_list(LinkList *L)
{
*L = (LinkList)malloc(sizeof(struct LNode));
if(!(*L)){
exit(1);
}
(*L)->next = NULL ;
return 0 ;
}
/*
i 从1这个位置开始
*/
int insert_list(LinkList L,int i ,ElemType e)
{
LinkNode p ;
LinkNode s ;
int j =0 ;
p = L ;
if(i <1){
return -1 ;
}
while(p &&(j<i-1))
{
p = p->next ;
j++ ;
}
if((!p)||(j<(i-1))){
return -1 ;
}
s = (LinkNode)malloc(sizeof(struct LNode));
if(!s){
printf("malloc error\n");
exit(1);
}
s->next = NULL;
s->data = e ;
s->next = p->next ;
p->next = s;
return OK ;
}
void visit(ElemType data)
{
printf("%s \n", data.name);
}
int traverse_list(LinkList L,void (*visit)(ElemType ))
{
LinkNode p = L->next ;
while(p){
visit(p->data);
p = p->next;
}
printf("\n");
return OK ;
}
#define N 4 /* student记录的个数 */
int main()
{
LinkList L;
int i ;
ElemType data ;
struct stud student[N]={{"王小林",790631,'m',18,"计91",0},
{"陈红",790632,'f',20,"计91",1},
{"刘建平",790633,'m',21,"计91",0},
{"张立立",790634,'m',17,"计91",2}}; /* 表的初始记录 */
printf("sizeof(\"刘建平\") = %d\n",strlen("刘建平"));
printf("sizeof(\"计91\") = %d\n",strlen("计91"));
printf("Hello World NULL = %d\n",NULL);
create_list(&L);
for(i=1;i <= N; i++){
insert_list(L,i,student[i-1]);
}
traverse_list(L, visit);
}
运行效果:
sizeof("刘建平") = 9
sizeof("计91") = 5
Hello World NULL = 0
王小林
陈红
刘建平
张立立
学生信息 存放到文件中去
/* c1.h (程序名) */
#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include <sys/io.h> /* eof() */
#include<math.h> /* floor(),ceil(),abs() */
#include<pthread.h> /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
#define NAMELEN 16 /* 姓名最大长度 */ //8
#define CLASSLEN 16 /* 班级名最大长度 */ //4
struct stud /* 记录的结构 */
{
char name[NAMELEN];
long num;
char sex;
int age;
char Class[CLASSLEN];
int health;
};
//{"张立立",790634,'m',17,"计91",2}
FILE *fp;
char sta[3][13]={"健康 ","一般 ","神经衰弱"}; /* 健康状况(3类) */
typedef struct stud ElemType; /* 链表结点元素类型为结构体 */
typedef struct LNode {
ElemType data;
struct LNode *next ;
}LNode, *LinkList,*LinkNode ;
int create_list(LinkList *L)
{
*L = (LinkList)malloc(sizeof(struct LNode));
if(!(*L)){
exit(1);
}
(*L)->next = NULL ;
return 0 ;
}
/*
i 从1这个位置开始
*/
int insert_list(LinkList L,int i ,ElemType e)
{
LinkNode p ;
LinkNode s ;
int j =0 ;
p = L ;
if(i <1){
return -1 ;
}
while(p &&(j<i-1))
{
p = p->next ;
j++ ;
}
if((!p)||(j<(i-1))){
return -1 ;
}
s = (LinkNode)malloc(sizeof(struct LNode));
if(!s){
printf("malloc error\n");
exit(1);
}
s->next = NULL;
s->data = e ;
s->next = p->next ;
p->next = s;
return OK ;
}
void InsertAscend(LinkList L,ElemType e) /* 此函数是由bo2-9.c中的同名函数改写 */
{ /* 按学号非降序插入 */
LinkList q=L,p=L->next;
while(p&&e.num>p->data.num)
{
q=p;
p=p->next;
}
q->next=(LinkList)malloc(sizeof(struct LNode)); /* 插在q后 */
q->next->data=e;
q->next->next=p;
}
Status ReadFromFile(struct stud *e)
{ /* 由fp指定的文件读取结点信息到e */
int i;
i=fread(e,sizeof(struct stud),1,fp);
if(i==1) /* 读取文件成功 */
return OK;
else
return ERROR;
}
void WriteToFile(struct stud e)
{ /* 将结点信息写入fp指定的文件 */
fwrite(&e,sizeof(struct stud),1,fp);
}
void Print(struct stud e)
{ /* 显示记录e的内容 */
printf("%-8s %6ld",e.name,e.num);
if(e.sex=='m')
printf(" 男");
else
printf(" 女");
printf("%5d %-4s",e.age,e.Class);
printf("%13s\n",sta[e.health]);
}
void visit(ElemType data)
{
printf("%s \n", data.name);
}
int traverse_list(LinkList L,void (*visit)(ElemType ))
{
LinkNode p = L->next ;
while(p){
visit(p->data);
p = p->next;
}
printf("\n");
return OK ;
}
#define N 4 /* student记录的个数 */
int main()
{
LinkList L;
int i ;
ElemType data ;
int flag =1;
ElemType e;
char filename[13] ="table.txt";
struct stud student[N]={{"王小林",790631,'m',18,"计91",0},
{"陈红",790632,'f',20,"计91",1},
{"刘建平",790633,'m',21,"计91",0},
{"张立立",790634,'m',17,"计91",2}}; /* 表的初始记录 */
printf("sizeof(\"刘建平\") = %d\n",strlen("刘建平"));
printf("sizeof(\"计91\") = %d\n",strlen("计91"));
printf("Hello World NULL = %d\n",NULL);
printf("sizeof(\"神经衰弱\") = %d\n", sizeof("神经衰弱"));
create_list(&L);
for(i=1;i <= N; i++){
insert_list(L,i,student[i-1]);
}
traverse_list(L, visit);
while(flag)
{
printf("\n");
/*
30(黑色)、31(红色)、32(绿色)、 33(黄色)、
34(蓝色)、35(洋红)、36(青色)、37(白色)
*/
printf("\033[0;36;40m");
printf("1:将结构体数组student中的记录按学号非降序插入链表\n");
printf("2:将文件中的记录按学号非降序插入链表\n");
printf("3:键盘输入新记录,并将其按学号非降序插入链表\n");
printf("4:删除链表中第一个有给定学号的记录\n");
printf("5:删除链表中第一个有给定姓名的记录\n");
printf("6:修改链表中第一个有给定学号的记录\n");
printf("7:修改链表中第一个有给定姓名的记录\n");
printf("8:查找链表中第一个有给定学号的记录\n");
printf("9:查找链表中第一个有给定姓名的记录\n");
printf("10:显示所有记录 \n");
printf("11:将链表中的所有记录存入文件\n");
printf("12:结束\n");
printf("\033[0m");
printf("\n");
printf("请选择操作命令: ");
scanf("%d",&i);
switch(i){
case 2:
if((fp=fopen(filename,"rb"))==NULL)
{
printf("打开文件失败!\n");
}
else
{
while(ReadFromFile(&e)){
InsertAscend(L,e);
}
fclose(fp);
}
break;
case 10:
printf("姓名 学号 性别 年龄 班级 健康状况\n");
traverse_list(L,Print);
break;
case 11:
if((fp=fopen(filename,"wb"))==NULL){
printf("打开文件失败!\n");
}
else{
traverse_list(L,WriteToFile);
}
fclose(fp);
break;
case 12:
flag = 0 ;
break ;
}
}
}
运行效果: