使用c语言单向链表实现简单学生成绩管理系统
现在这个简单系统不能保存数数据,不能退出,本文使用lo操作将链表中维护的数据保存到文件中,即退出保存,重新运行再从文件中提取数据。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//个人信息结构体,各科成绩可自定义添加
typedef struct grade_msg
{
char name[16];
char sex;
int chinese;
int math;
int english;
}grade_msg_t;
//链表结构体
typedef struct student_msg
{
grade_msg_t msg;
struct student_msg * next;
}student_msg_t;
//定义操作类型枚举
enum operate_type
{
INSERT_TYPE = 1,
DELETE_TYPE,
PRINTF_TYPE,
MODIFY_TYPE,
QUIT_TYPE
};
//创建链表头
student_msg_t * create_slist_head()
{
student_msg_t * head;
//申请空间
head = (student_msg_t *)malloc(sizeof(student_msg_t));
if(head == NULL)
{
printf("create slist head fail\n");
return NULL;
}
//初始化
head->next = NULL;
return head;
}
//判断链表中有无数据
//返回1为空,0为非空
int isnull(student_msg_t * head)
{
if(head->next == NULL)
return 1;
else
return 0;
}
//链表头添加数据
int insert_data(student_msg_t * head,grade_msg_t * msg)
{
printf("enter insert msg\n");
student_msg_t * new_node;
new_node = (student_msg_t * )malloc(sizeof(student_msg_t));
if(new_node == NULL)
{
printf("insert,create space fail\n");
return -1;
}
strcpy(new_node->msg.name,msg->name);
new_node->msg.sex = msg->sex;
new_node->msg.chinese = msg->chinese;
new_node->msg.math = msg->math;
new_node->msg.english = msg->english;
new_node->next = head->next;
head->next = new_node;
return 0;
}
//打印所有信息
int printf_list(student_msg_t * head)
{
if(isnull(head))
{
printf("no student msg\n");
return -1;
}
while(head->next != NULL)
{
head = head->next;
printf("name:%-8s,sex:%c,chinese:%d,math:%d,english:%d\n",head->msg.name,head->msg.sex,head->msg.chinese,head->msg.math,head->msg.english);
}
return 0;
}
//保存数据
int save_data(student_msg_t * head,char * buf)
{
char str[64];
if(isnull(head))
{
printf("no student msg\n");
return -1;
}
while(head->next != NULL)
{
head = head->next;
sprintf(str,"name:%s ,sex:%c,chinese:%d,math:%d,english:%d\n",head->msg.name,head->msg.sex,head->msg.chinese,head->msg.math,head->msg.english);
strcat(buf,str);
}
printf("buf:%s\n",buf);
return 0;
}
//链表中删除数据--根据姓名
int delete_data(student_msg_t * head,char * name)
{
if(isnull(head))
{
printf("no student msg\n");
return -1;
}
int flag = 0;
student_msg_t * temp_node;
temp_node = (student_msg_t*)malloc(sizeof(student_msg_t));
if(temp_node == NULL)
{
printf("create temp node fail\n");
return -1;
}
while(head->next != NULL)
{
if(0 == strncmp(head->next->msg.name,name,strlen(name)))
{
//删除此节点
temp_node = head->next;
head->next = temp_node->next;
free(temp_node);
temp_node = NULL;
flag = 1; //判断找到需要删除的信息
break;
}
else
head = head->next;
}
if(flag == 0)
printf("the list do not have the name\n");
else
printf("delete the name msg is success\n");
return 0;
}
//链表中修改数据--根据姓名
int modify_data(student_msg_t * head,grade_msg_t * grade_msg)
{
if(isnull(head))
{
printf("no student msg\n");
return -1;
}
int flag = 0;
while(head->next != NULL)
{
if(0 == strncmp(head->next->msg.name,grade_msg->name,strlen(grade_msg->name)))
{
//修改此节点
head->next->msg.chinese = grade_msg->chinese;
head->next->msg.math = grade_msg->math;
head->next->msg.english = grade_msg->english;
flag = 1; //判断找到需要删除的信息
break;
}
else
{
head = head->next;
}
}
if(flag == 0)
printf("the list do not have the name\n");
else
printf("modify msg success\n");
return 0;
}
int main(int argc, const char *argv[])
{
student_msg_t * msg_head;
char msg_str[64];
char name_str[16];
int flag;
grade_msg_t insert_msg;
int fd;
char buf_str[512];
int ret = 0;
//从文件中读字符串后解析使用
char * in_str = NULL;
char * residue_str = NULL;
char * temp_str = NULL;
//创建链表头
msg_head = create_slist_head();
if(msg_head == NULL)
{
printf("create student msg head fail\n ");
return -1;
}
//创建一个文件描述符
fd = open("./student_msg_file",O_RDWR|O_CREAT);
if(fd < 0)
{
printf("open the file fail\n");
return -1;
}
//从文件中读取数据,添加到链表
memset(buf_str,0,512);
while(0 < (ret = read(fd,buf_str,sizeof(buf_str))))
{
printf("buf_str:%s\n",buf_str);
in_str = strstr(buf_str,"name:");
while(NULL != (in_str = strtok_r(in_str,"\n",&residue_str)))
{
printf("in str:%s\n",in_str);//in str:name:xiaoli ,sex:b,chinese:85,math:75,english:96
sscanf(in_str,"name:%s ,sex:%c,chinese:%d,math:%d,english:%d",insert_msg.name,&insert_msg.sex,&insert_msg.chinese,&insert_msg.math,&insert_msg.english);
printf("n:%s,s:%c,c:%d,m:%d,e:%d\n",insert_msg.name,insert_msg.sex,insert_msg.chinese,insert_msg.math,insert_msg.english);
insert_data(msg_head,&insert_msg);
in_str = NULL;
}
}
while(1)
{
printf("input operate flag \n");
printf("1 INSERT_TYPE\n");
printf("2 DELETE_TYPE\n");
printf("3 PRINTF_TYPE\n");
printf("4 MODIFY_TYPE\n");
printf("5 QUIT_TYPE\n");
scanf("%d",&flag);
getchar();
switch(flag)
{
case INSERT_TYPE:
{
//姓名 字符串 性别 字符类型 语数英 整型
printf("please input 姓名[enter] 性别[enter] 语文[enter] 数学[enter] 英语[enter]\n");
//简化信息输入
printf("------------input start------------\n");
scanf("%s",insert_msg.name);
getchar();
scanf("%c",&insert_msg.sex);
getchar();
scanf("%d",&insert_msg.chinese);
getchar();
scanf("%d",&insert_msg.math);
getchar();
scanf("%d",&insert_msg.english);
getchar();
printf("------------input end------------\n");
//插入数据
insert_data(msg_head,&insert_msg);
}
break;
case PRINTF_TYPE:
{
printf("==========printf start==========\n");
if(msg_head -> next != NULL)
printf_list(msg_head);
else
printf("do not have student msg \n");
printf("==========printf end=========\n");
}
break;
case DELETE_TYPE:
{
printf("<delete>please enter delete name\n");
memset(name_str,0,sizeof(name_str));
scanf("%s",name_str);
getchar();
delete_data(msg_head,name_str);
}
break;
case MODIFY_TYPE:
{
printf("<modify>please input modify name\n");
memset(name_str,0,sizeof(insert_msg.name));
scanf("%s",insert_msg.name);
getchar();
scanf("%d",&insert_msg.chinese);
getchar();
scanf("%d",&insert_msg.math);
getchar();
scanf("%d",&insert_msg.english);
getchar();
modify_data(msg_head,&insert_msg);
}
break;
case QUIT_TYPE:
{
goto out;
}
break;
default:
printf("no have the operate type\n");
}
}
out:
//将链表数据缓存到buf_str中
memset(buf_str,0,512);
save_data(msg_head,buf_str);
write(fd,buf_str,sizeof(buf_str));
close(fd);
return 0;
}
直接编译运行,亲测ok,注意代码中定义了一个buf,为512个字节,所以文件最多保存512个字节,这个大小可修改。