简介:一个简单的学生信息管理系统,用纯C语言实现,数据结构是用单链表,可以进自动进行数据的磁盘存储和读取(数据存储是二进制格式)。存储的数据只有姓名、学号、成绩。此程序包含了C语言一般链表使用的(增、删、改、查)所有动作和C语言文件存储的一般形式,可作为C语言初学者练习链表和文件知识的不错例子。
程序运行后自动从磁盘读取数据,把历史数据存储在链表里,然后再程序里可以对链表进行操作,程序正常退出时,会把数据自动存储到磁盘,以二进制文本形式。
下面是程序的全部源代码:
程序使用了三个文件:
1)list.h文件:功能函数接口
#pragma once
#ifndef LIST_H_
#define LIST_H_
#include<stdbool.h>
typedef struct {
char name[10]; //姓名
float grade; //成绩
int number; //学号
}Item;
//链表节点
typedef struct node {
Item item;
struct node*next;
}Node;
typedef Node * List;
void menu(void);
void InitializeList(List*plist); //初始化链表
bool ListIsEmpty(const List*plist);
bool ListIsFull(const List*plist);
void ReadList(List*plist);//从文件读入数据
void WriteList(const List*plist);//写进文件
void ListItemCount(const List*plist); //统计数量
void ListSearch(const List*plist);//查找
void ListInsertItem(List*plist);//插入项目
void ListUpdate(const List*plist);//修改
void ListDeleteItem(List*plist);//删除
void show(const List *plist); //输出
void EmptyTheList(List*plist); //清空
#endif // !LIST_H_
2)list.c文件:接口函数具体实现
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include"list.h"
void menu(void)
{
printf("\n\n\n\n\n\n");
puts("\t\t|-------------学生管理里系统------------|");
puts("\t\t|\t 1.输入成绩. |");
puts("\t\t|\t 2.修改成绩. |");
puts("\t\t|\t 3.删除信息. |");
puts("\t\t|\t 4.输出信息. |");
puts("\t\t|\t 5.查询信息. |");
puts("\t\t|\t 6.显示学生数量. |");
puts("\t\t|\t other number is quit. |");
puts("\t\t|---------------------------------------|");
puts("\t\t\t\tchose(1-6):");
}
void InitializeList(List*plist) //初试化链表
{
*plist = NULL;
}
bool ListIsEmpty(const List*plist) //查看链表是否是空的
{
if (*plist == NULL)return true;
else return false;
}
bool ListIsFull(const List*plist) //查看能链表是否满了
{
List pt;
bool full;
pt = (List)malloc(sizeof(Node));
if (pt == NULL)full = true;
else full=false;
free(pt);
return full;
}
void ReadList(List*plist) //从文件中读取历史数据 方案1
{
puts("正在获取历史数据...");
List current;
List pre;
FILE* fp;
while ((fp = fopen("student.dat", "rb")) == NULL)
{
fprintf(stderr, "Can't open students.dat file");
exit(1);
}
rewind(fp);
while (!feof(fp))
{
current = (List)malloc(sizeof(Node));
if (current == NULL)
{
puts("No memory!");
exit(EXIT_FAILURE);
}
current->next = NULL;
fread(&(current->item), sizeof(Item), 1, fp);
if (feof(fp)) { free(current);break; }
if (*plist == NULL)
*plist= current;
else pre->next = current;
pre = current;
}
fclose(fp);
puts("历史数据已经获取.");
}
//void ReadList(List*plist) //从文件中读取历史数据 方案2
//{
// puts("正在获取历史数据...");
// List current;
// List pre = NULL;
// FILE* fp;
// while ((fp = fopen("student.dat", "rb")) == NULL)
// {
// fprintf(stderr, "Can't open students.dat file");
// exit(1);
// }
// rewind(fp);
// while (1)
// {
// current = (List)malloc(sizeof(Node));
// if (current == NULL)
// {
// puts("No memory!");
// exit(EXIT_FAILURE);
// }
// if (!fread(&(current->item), sizeof(Item), 1, fp))
// {
// free(current);
// break;
// }
// if (*plist == NULL)
// *plist = current;
// else
// pre->next = current;
// current->next = NULL;
// pre = current;
// }
// fclose(fp);
// puts("历史数据已经获取.");
//}
void WriteList(const List*plist) //存储数据
{
List ptr=*plist;
puts("正在存储数据...");
FILE*fp;
while ((fp = fopen("student.dat", "wb")) == NULL)
{
fprintf(stderr, "Can't open students.dat file");
exit(2);
}
while (ptr != NULL)
{
fwrite(&(ptr->item), sizeof(Item), 1, fp);
ptr = ptr->next;
}
puts("存储数据成功!");
fclose(fp);
}
void ListItemCount(const List*plist) //学生数目
{
List pt = *plist;
unsigned int n=0;
while (pt != NULL)
{
n++;
pt = pt->next;
}
printf("This list have %d students.", n);
}
void ListSearch(const List*plist) //查找
{
List pt = *plist;
int number;
int flag=1; //标记
puts("Please enter this sudent's number:");
scanf("%d", &number);
while (pt != NULL&&flag)
{
if (pt->item.number == number)
{
printf("This student name is %s\n,number is %d\n,grade is %f.\n",
pt->item.name, pt->item.number, pt->item.grade);
flag = 0; //找到标记为0
}
else
pt = pt->next;
}
if (flag)printf("No found!");
}
void ListInsertItem(List*plist) //输入信息
{
List pt=*plist;
List pre;
List r;
int number;
if (ListIsFull(plist))
{
puts("This list is full.");
return;
}
puts("Please enter number:");
scanf("%d", &number);
while (pt != NULL)
{
if (pt->item.number == number)
{
puts("This list have this number,please inpit other number.");
return;
}
else { pre = pt; pt = pt->next;}
}
r = (List)malloc(sizeof(Node));
if (r == NULL) {
puts("NO memory!");
exit(3);
}
r->next = NULL;
if (*plist == NULL)
*plist = r;
else
pre->next = r;
(r->item).number = number;
puts("Please enter this student's name:");
while (getchar() != '\n')continue;
gets((r->item).name);
puts("Please enter this student's grade:");
scanf("%f", &(r->item.grade));
}
void ListUpdate(const List*plist) //修改
{
List pt = *plist;
int number;
int flag = 1;
puts("Please enter this student's number:");
scanf("%d", &number);
while (pt != NULL&&flag)
{
if (pt->item.number == number)
{
puts("Please enter name:");
gets(pt->item.name);
puts("Please enter grade:");
scanf("%f", &pt->item.grade);
flag = 0;
}
else pt = pt->next;
}
if (flag)puts("Don't find this number!");
}
void ListDeleteItem(List*plist) //删除
{
List pt = *plist;
List pr = *plist;
int number;
int flag=1;
puts("Please enter this student's number:");
scanf("%d", &number);
while (pt != NULL&&flag)
{
if (pt->item.number == number)
{
if (pt == *plist)
{
*plist = pt->next;
free(pt);
}
else
{
pr->next = pt->next;
free(pt);
}
flag = 0;
}
else
{
pr = pt;
pt = pt->next;
}
}
if (flag)puts("No find this student!");
}
void show(const List *plist) //输出
{
List pt = *plist;
if (pt == NULL)puts("This list is empty!");
else
while (pt != NULL)
{
puts("Here is the students list:");
printf("Name is :%s\nNumber is :%d\nGrade is :%f\n",
pt->item.name,pt->item.number,pt->item.grade);
pt = pt->next;
}
}
void EmptyTheList(List*plist) //清空链表
{
List pt = *plist;
while (*plist != NULL)
{
pt =(*plist)->next;
free(*plist);
*plist = pt;
}
}
3)student.c函数:主函数
#include<stdio.h>
#include<stdlib.h>
#include"list.h"
int main(void)
{
List students;
int n;
InitializeList(&students);
if (ListIsFull(&students))
{
fprintf(stderr, "NO memory!");
exit(1);
}
ReadList(&students);
menu(); //菜单列表
while (scanf("%d", &n)==1)
{
while (getchar() != '\n')continue;
switch (n)
{
case 1:ListInsertItem(&students);break; //插入
case 2:ListUpdate(&students);break; //修改
case 3:ListDeleteItem(&students);break; //删除
case 4:show(&students);break; //输出
case 5:ListSearch(&students);break; //查询
case 6:ListItemCount(&students);break; //显示学生数量
default:puts("Bye!");WriteList(&students);EmptyTheList(&students);exit(1); //退出
}
menu();
}
getchar();
return 0;
}
注意:要存储数据必须正常退出,不然不能存储数据。
作者:Wnlife 2018.5.24