使用单链表实现一个简单的学生信息管理系统,该系统的功能有:
1、利用单链表建立学生基本信息表
2、浏览每个学生的信息
3、根据学号查询某个学生的基本信息
4、添加学生信息到单链表中
5、删除一个学生的信息
6、利用文件实现学生信息的存取
先创建结点的结构体和学生信息的结构体。如下:
//创建一个学生信息结构体包含 学号,姓名,性别
typedef struct Student
{
int num;
char name[10];
char sex;
}Student;
typedef struct LNode
{
Student data;
struct LNode* next;
}LNode, * LinkLinst;
链表的初始化。如下:
void InitLinst(LinkLinst& L)
{
L = (LinkLinst)malloc(sizeof(LNode));
assert(L);
L->next = NULL;
}
我这里分两种情况创建链表:分别为头插法创建指定长度链表和尾插法创建指定长度链表。
//头插法
void CreateLinst01(LinkLinst& L, int length)
{
int i = 0;
LinkLinst p = L;
Student s;
while (i < length)
{
printf("请输入第%d个学生的学号:", i + 1);
cin >> s.num;
printf("请输入第%d个学生的姓名:", i + 1);
cin >> s.name;
printf("请输入第%d个学生的性别:", i + 1);
cin >> s.sex;
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
temp->next = p->next;
temp->data = s;
p->next = temp;
i++;
}
printf("头插法创建链表成功...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
//尾插法创建指定长度链表
void CreateLinst02(LinkLinst& L, int length)
{
int i = 0;
LinkLinst p = L;
while (p->next)
{
p = p->next;
}
while (i < length)
{
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
printf("请输入第%d个学生的学号:", i + 1);
cin >> temp->data.num;
printf("请输入第%d个学生的姓名:", i + 1);
cin >> temp->data.name;
printf("请输入第%d个学生的性别:", i + 1);
cin >> temp->data.sex;
temp->next = p->next;
p->next = temp;
p = temp;
i++;
}
printf("尾插法创建链表成功...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
创建完链表之后就要写插入和删除的代码。具体代码如下:
//指定位置插入
void InsertLinst(LinkLinst& L, int pos, Student e)
{
LinkLinst p = L;
int i = 0;
while (i < pos - 1 && p != NULL)
{
i++;
p = p->next;
}
if (!p)
printf("插入失败,插入位置错误...\n");
else
{
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
temp->next = p->next;
p->next = temp;
temp->data = e;
printf("插入成功...\n");
}
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
//指定位置删除
int DelateLinst(LinkLinst& L, int pos, Student &e)
{
LinkLinst p = L->next;
LinkLinst temp = L;
int i = 1;
while (i < pos && p != NULL)
{
i++;
p = p->next;
temp = temp->next;
}
//assert(p);
if (!p)
{
printf("输入错误,没有该位置的学生信息...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 0;
}
temp->next = p->next;
e = p->data;
free(p);
p = NULL;
printf("删除成功...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 1;
}
这样链表基本上就形成了,但时要怎么查看又怎么知道它的长度呢呢?就要写代码来遍历打印这个链表和获取链表长度,具体代码如下:
void DisplayLinst(LinkLinst& L)
{
LinkLinst p = L->next;
int i = 1;
if (!p)
printf("链表为空\n");
while (p)
{
cout << "第"<<i++<<"个学生的学号为:" << p->data.num << " 姓名:" << p->data.name << " 性别:" << p->data.sex<<endl;
p = p->next;
}
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
//返回链表长度值
int LengthLinst(LinkLinst& L)
{
int length = 0;
LinkLinst p = L->next;
while (p)
{
length++;
p = p->next;
}
return length;
}
接下来就要写出根据学号查出学生信息并返回的函数和打印该学生的信息的函数,具体代码如下:
//查找指定学号学生信息并返回
int SearchLinst(LinkLinst& L, int num ,Student &e)
{
LinkLinst p = L->next;
while (p)
{
if (p->data.num == num)
{
e = p->data;
printf("成功找到该学号的学生...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 1;
}
p = p->next;
}
printf("没有找到该学号的学生\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 0;
}
//打印查找到的学生信息
void Printf(Student& e)
{
if (e.num == -1)
printf("无该学生信息\n");
else
printf("该学生的学号:%d 姓名:%-10s 性别:%c\n", e.num, e.name, e.sex);
//cout << "该学生的学号:" << e.num << " 姓名:" << e.name << " 性别:" << e.sex;
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
根据以上的代码已经把1-5的要求完成了,那么该怎么做到文件的存取呢?
运用文件保存时分别会有以下三种情况:
1.文件不存在。
2.文件存在但内容为空
3.文件存在且有内容
第一二种情况都好说,直接打开文件对数据进行保存。而第三种情况就需要考虑之前内容是否要保存呢?
因此需要编写一个函数来判断文件之前是否存在,存在的话是否有内容。具体代码如下:
//判断之前文件是否为空
void ifempty()
{
int num,input=2;
string name;
char sex;
ifstream ifs(TEXT, ios::in);
if (ifs.is_open())
{
while (ifs >> num && ifs >> name && ifs >> sex)
x++;//文件有内容的标志位,初始值为0,x的值也代表文件有几个人的信息
}
else
cout << "文件不存在" << endl;
ifs.close();
}
如果文件有内容那就需要判断是否要删除之前的数据,而如果不删除的话,要把文件的数据进行链表的存储。
void Init(LinkLinst&L)
{
LinkLinst p = L;
Student s;
ifstream ifs;
int flag = 2;
cout << "文件已经有数据是否要删除之前的数据" << endl
<< "******* 1.不删除 0.删除*******" << endl
<< "请选择->:" << endl;
while (1)
{
cin >> flag;
if (flag == 0)
{
delate();
break;
}
else if (flag == 1)
{
ifs.open(TEXT, ios::in);
while (ifs >> s.num && ifs >> s.name && ifs >> s.sex)
{
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
temp->data = s;
temp->next = p->next;
p->next = temp;
p = temp;
}
break;
}
else
{
cout << "输入错误,请重新输入:" << endl;
cin >> flag;
}
}
}
之后就要对新的链表进行保存和对之前的文件内容的删除,代码如下:
//对链表进行文件保存
void save(LinkLinst L)
{
LinkLinst p = L->next;
ofstream ofs(TEXT, ios::out);
while (p)
{
ofs << p->data.num << " " << p->data.name << " " << p->data.sex << endl;
p = p->next;
}
ofs.close();
}
//删除之前的文件
void delate()
{
ofstream ofs(TEXT, ios::trunc);
ofs.close();
}
这样就完成了这个小项目。
大致效果如下图:
!](https://img-blog.csdnimg.cn/f7cd2943bc8f45039049ebfe4d655565.png#pic_center)
完整代码如下:
#include <string>
#include "stdio.h"
#include <cassert>
#include "iostream"
#include <fstream>
using namespace std;
#define TEXT "text.txt"
//创建一个学生信息结构体包含 学号,姓名,性别
typedef struct Student
{
int num;
char name[10];
char sex;
}Student;
typedef struct LNode
{
Student data;
struct LNode* next;
}LNode, * LinkLinst;
int x = 0;
void InitLinst(LinkLinst& L)
{
L = (LinkLinst)malloc(sizeof(LNode));
assert(L);
L->next = NULL;
}
void InsertLinst(LinkLinst& L, int pos, Student e)
{
LinkLinst p = L;
int i = 0;
while (i < pos - 1 && p != NULL)
{
i++;
p = p->next;
}
if (!p)
printf("插入失败,插入位置错误...\n");
else
{
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
temp->next = p->next;
p->next = temp;
temp->data = e;
printf("插入成功...\n");
}
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
void DisplayLinst(LinkLinst& L)
{
LinkLinst p = L->next;
int i = 1;
if (!p)
printf("链表为空\n");
while (p)
{
cout << "第" << i++ << "个学生的学号为:" << p->data.num << " 姓名:" << p->data.name << " 性别:" << p->data.sex << endl;
p = p->next;
}
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
int SearchLinst(LinkLinst& L, int num, Student& e)
{
LinkLinst p = L->next;
while (p)
{
if (p->data.num == num)
{
e = p->data;
printf("成功找到该学号的学生...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 1;
}
p = p->next;
}
printf("没有找到该学号的学生\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 0;
}
int DelateLinst(LinkLinst& L, int pos, Student& e)
{
LinkLinst p = L->next;
LinkLinst temp = L;
int i = 1;
while (i < pos && p != NULL)
{
i++;
p = p->next;
temp = temp->next;
}
//assert(p);
if (!p)
{
printf("输入错误,没有该位置的学生信息...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 0;
}
temp->next = p->next;
e = p->data;
free(p);
p = NULL;
printf("删除成功...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
return 1;
}
void Distory(LinkLinst& L)
{
LinkLinst p = L->next;
LinkLinst q;
while (p)
{
q = p->next;
free(p);
p = q;
}
L->next = NULL;
}
//头插法
void CreateLinst01(LinkLinst& L, int length)
{
int i = 0;
LinkLinst p = L;
Student s;
while (i < length)
{
printf("请输入第%d个学生的学号:", i + 1);
cin >> s.num;
printf("请输入第%d个学生的姓名:", i + 1);
cin >> s.name;
printf("请输入第%d个学生的性别:", i + 1);
cin >> s.sex;
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
temp->next = p->next;
temp->data = s;
p->next = temp;
i++;
}
printf("头插法创建链表成功...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
//尾插法创建指定长度链表
void CreateLinst02(LinkLinst& L, int length)
{
int i = 0;
LinkLinst p = L;
while (p->next)
{
p = p->next;
}
while (i < length)
{
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
printf("请输入第%d个学生的学号:", i + 1);
cin >> temp->data.num;
printf("请输入第%d个学生的姓名:", i + 1);
cin >> temp->data.name;
printf("请输入第%d个学生的性别:", i + 1);
cin >> temp->data.sex;
temp->next = p->next;
p->next = temp;
p = temp;
i++;
}
printf("尾插法创建链表成功...\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
int LengthLinst(LinkLinst& L)
{
int length = 0;
LinkLinst p = L->next;
while (p)
{
length++;
p = p->next;
}
return length;
}
void Printf(Student& e)
{
if (e.num == -1)
printf("无该学生信息\n");
else
printf("该学生的学号:%d 姓名:%-10s 性别:%c\n", e.num, e.name, e.sex);
//cout << "该学生的学号:" << e.num << " 姓名:" << e.name << " 性别:" << e.sex;
//按任意键后,清屏回到菜单
system("pause");
system("cls");
}
int ReverseLinst(LinkLinst& L)
{
LinkLinst n1 = L->next;
if (!n1)
return 0;
LinkLinst n2 = n1->next, n0 = NULL;
if (!n2)
return 0;
while (n2)
{
n1->next = n0;
n0 = n1;
n1 = n2;
n2 = n2->next;
}
n1->next = n0;
L->next = n1;
return 1;
}
LinkLinst sum1(LinkLinst& La, LinkLinst& Lb)
{
LinkLinst pa = La->next, pb = Lb->next;
LinkLinst temp = La;
free(Lb);
while (pa && pb)
{
if ((pa->data.num) < (pb->data.num))
{
temp->next = pa;
pa = pa->next;
temp = temp->next;
}
else
{
temp->next = pb;
pb = pb->next;
temp = temp->next;
}
}
temp->next = pa ? pa : pb;
return La;
}
LinkLinst sum2(LinkLinst& La, LinkLinst& Lb)
{
LinkLinst pa = La->next, pb = Lb->next;
La->next = NULL;
free(Lb);
while (pa && pb)
{
if ((pa->data.num) < (pb->data.num))
{
LinkLinst temp = pa->next;
pa->next = La->next;
La->next = pa;
pa = temp;
}
else
{
LinkLinst temp = pb->next;
pb->next = La->next;
La->next = pb;
pb = temp;
}
}
LinkLinst p;
if (pa)
p = pa;
else
p = pb;
while (p)
{
LinkLinst temp = p->next;
p->next = La->next;
La->next = pb;
p = temp;
}
return La;
}
void save(LinkLinst L)
{
LinkLinst p = L->next;
ofstream ofs(TEXT, ios::out);
while (p)
{
ofs << p->data.num << " " << p->data.name << " " << p->data.sex << endl;
p = p->next;
}
ofs.close();
}
//判断之前文件是否为空
void ifempty()
{
int num, input = 2;
string name;
char sex;
ifstream ifs(TEXT, ios::in);
if (ifs.is_open())
{
while (ifs >> num && ifs >> name && ifs >> sex)
x++;
}
else
cout << "文件不存在" << endl;
ifs.close();
}
void delate()
{
ofstream ofs(TEXT, ios::trunc);
ofs.close();
}
void Init(LinkLinst& L)
{
LinkLinst p = L;
Student s;
ifstream ifs;
int flag = 2;
cout << "文件已经有数据是否要删除之前的数据" << endl
<< "******* 1.不删除 0.删除*******" << endl
<< "请选择->:" << endl;
while (1)
{
cin >> flag;
if (flag == 0)
{
delate();
break;
}
else if (flag == 1)
{
ifs.open(TEXT, ios::in);
while (ifs >> s.num && ifs >> s.name && ifs >> s.sex)
{
LinkLinst temp = (LinkLinst)malloc(sizeof(LNode));
assert(temp);
temp->data = s;
temp->next = p->next;
p->next = temp;
p = temp;
}
ifs.close();
break;
}
else
{
cout << "输入错误,请重新输入:" << endl;
cin >> flag;
}
}
}
void menu()
{
printf("*****************************************\n");
printf("*** 1.头插法创建链表 2.尾插创建链表**\n");
printf("*** 3.指定位置插入 4.指定位置删除**\n");
printf("*** 5.遍历打印学生信息 6.获取链表长度**\n");
printf("*** 7.查找指定学号的学生 8.打印查到学号的学生信息**\n");
printf("***************** 0.退出 ****************\n");
}
enum ch
{
tuichu,
Create01,
Create02,
Insert,
Delate,
Display,
Length,
Search,
PRintf
};
void choice()
{
LinkLinst L;
InitLinst(L);
int input = 0,length,pos,num;
Student s,s1;
s1.num = -1;
if (x)
Init(L);
do
{
menu();
printf("请选择:> ");
scanf_s("%d", &input);
switch (input)
{
case tuichu:Distory(L); free(L); break;
case Create01:
printf("输入要创建的单链表的长度:");
scanf_s("%d", &length);
CreateLinst01(L,length);
save(L);//保存在文件中
break;
case Create02:
printf("输入要创建的单链表的长度:");
scanf_s("%d", &length);
CreateLinst02(L, length);
save(L);//保存在文件中
break;
case Insert:
printf("请输入要插入的位置:");
scanf_s("%d", &pos);
printf("请输入插入学生的学号:");
cin >> s.num;
printf("请输入插入学生的姓名:");
cin >> s.name;
printf("请输入插入学生的性别:");
cin >> s.sex;
InsertLinst(L,pos,s);
save(L);//保存在文件中
break;
case Delate:
printf("请输入要删除的位置:");
scanf_s("%d", &pos);
DelateLinst(L, pos, s);
save(L);//保存在文件中
break;
case Display:
DisplayLinst(L);
break;
case Length:
printf("%d\n",LengthLinst(L));
//按任意键后,清屏回到菜单
system("pause");
system("cls");
break;
case Search:
printf("请输入要查找的学生学号");
scanf_s("%d", &num);
SearchLinst(L, num, s1);
break;
case PRintf:
Printf(s1);
break;
default:
printf("输入错误请重新选择\n");
//按任意键后,清屏回到菜单
system("pause");
system("cls");
break;
}
} while (input);
}
int main()
{
ifempty();
choice();
return 0;
}
创作不易,请多多支持。欢迎大家在评论区交流!