可以增删查改,使用链表存储,支持排序以及文件存储及数据读取,基本可以应付期末大作业(狗头)
界面为
源代码为一个main.cpp和三个头文件,具体为
main.cpp
#include
#include //文件操作
#include //int转string
#include //cout格式化输出 setw()
#include
#include "student.h"
#include "node.h"
#include "list.h"
using namespace std;
int main()//入口函数
{
//test();
CList list1;//创建链表对象
Read4File(list1);//将文件数据读取到链表中
int choice = -1;//接收用户选择
while(true)
{
system("cls");//清屏
MainMenu();
cin>>choice;
switch(choice)
{
case 1:
system("cls");//清屏
cout<<"********【所有数据】********"<<endl;
cout<<"序号\t学号 姓名 班级 分数"<<endl;
cout<<"*******【共 "<<list1.DisplayListData()<<" 人】******\n"<<endl;
list1.Compute();
system("pause");//暂停一下
break;
case 2:
Add(list1);//添加操作
break;
case 3:
Find(list1);//查找操作
break;
case 4:
Update(list1);//更新操作(修改)
break;
case 5:
Sort(list1);//排序操作
break;
case 6:
Del(list1);//删除操作
break;
case 7:
ClearFileData();//清空文件数据
list1.Clear();//清空链表数据
break;
case 0://退出程序
return 0;
default:
cout<<"请输入0~7"<<endl;
system("pause");
break;
}
}
return 0;
}
\list.h
#include
#include
#include
#include
#include
#define FILE_PATH "student.txt" //数据文件的路径
using namespace std;
//声明
class CList;
void Save2File(CList& list);//将数据保存到文件
void Read4File(CList& list);//读取文件数据到链表
bool CmpStr(string str1, string str2)//字符串比较函数
{
int len1 = str1.size();//字符串1的长度
int len2 = str2.size();//字符串2的长度
//将两个字符串的长度 添加为一样长(达到右对齐的效果)
for(int i=0; i<len1-len2; i++)//如果字符串str1比str2长,在str2的前面补0
{
str2.insert(0, "0");//在最前面补0
}
for(int i=0; i<len2-len1; i++)//如果字符串str2比str1长,在str1的前面补0
{
str1.insert(0, "0");//在最前面补0
}
return str1>str2;
}
bool SortById(SNode* &p, SNode* &q)//按学号升序排序
{
return ( p->stu.GetId()>q->stu.GetId() );
}
bool SortByName(SNode* &p, SNode* &q)//按姓名升序排序
{
return CmpStr(p->stu.GetName(), q->stu.GetName());
}
bool SortByClass(SNode* &p, SNode* &q)//按班级升序排序
{
return CmpStr(p->stu.GetClass(), q->stu.GetClass());
}
bool SortByScore(SNode* &p, SNode* &q)//按Score升序排序
{
return ( p->stu.GetScore()>q->stu.GetScore() );
}
typedef bool (*FUNCP)(SNode* &p, SNode* &q);//函数指针
FUNCP pFunArr[] = {SortById, SortByName, SortByClass,SortByScore};//排序函数的指针数组
//链表操作类
class CList
{
SNode* m_pListHead;//链表头结点指针
void Init_ListHead();//初始化头结点
public:
CList();//无参构造函数,用来初始化成员,创建对象的时候自动调用
~CList();//析构函数,用来释放格外申请的堆空间,(对象被销毁的时候自动调用)
void AddHead(SNode& node);//头插法 添加数据
void AddTail(SNode& node);//尾插法 添加数据
bool DelData(int id);//根据id删除数据
SNode* FindData(int id);//根据id查找指定数据
bool UpdateData(int id, SNode& update);//根据id修改数据(更新)
int DisplayListData();//显示链表所有数据,返回数据条数
SNode* GetListHead();//外界获取头结点指针的接口(头指针是private权限)
void Clear();//清空链表。释放链表空间
void Sort(int type = 0);//默认按id升序排序
int Size();
void Compute();//获取链表数据的个数
};
//类成员函数的类外实现
CList::CList()//无参构造函数,用来初始化成员
{
Init_ListHead();//初始化链表头结点
}
CList::~CList()//析构函数,用来释放格外申请的堆空间,(对象被销毁的时候自动调用)
{
Clear();//释放链表空间
delete m_pListHead;//释放头结点,
m_pListHead = NULL;//置空,防止重复操作
}
void CList::Compute()//根据id升序排序
{ int a=0,b=0,c=0;
if(m_pListHead == NULL)//空链表直接返回
{
return;
}
SNode* p; //排序辅助指针(以p为基准,q遍历连链表数据,temp在交换的数据时使用,指向需要交换时的较大者)
for(p = m_pListHead->next;p != NULL;p = p->next)
{
if(p->stu.GetScore()<60)a++;
else if(p->stu.GetScore()>=60&&p->stu.GetScore()<=80)b++;
else if(p->stu.GetScore()>80)c++;
}
cout<<"60分以下(不含60分)的人数有:"<<a<<"人"<<endl;
cout<<"60分以上80分以下(含80分)的人数有:"<<b<<"人"<<endl;
cout<<"80分以上的人数有:"<<c<<"人"<<endl;
if((a+b+c)!=0)cout<<"及格率为:"<<(float)(b+c)/(a+b+c)*100<<"%"<<endl;
}
void CList::Init_ListHead()//初始化头结点
{
m_pListHead = new SNode;//初始化头结点
m_pListHead->stu.SetId(0);
m_pListHead->stu.SetName("头结点");
m_pListHead->stu.SetClass("A班");
m_pListHead->stu.SetScore(0);
m_pListHead->next = NULL;
}
void CList::AddHead(SNode& node)//头插法 添加数据
{
SNode* new_node = new SNode(node);
new_node->next = NULL;
if(m_pListHead == NULL)//头结点为空,就初始化头结点
{
Init_ListHead();
}
if(m_pListHead->next == NULL)//如果除头结点外还没有数据节点,直接让头结点指向新的节点,新的节点作为第一个数据节点
{
m_pListHead->next = new_node;
}
else //将新的节点作为第一个数据节点(头结点后面的一个)
{
new_node->next = m_pListHead->next;
m_pListHead->next = new_node;
}
}
void CList::AddTail(SNode& node)//尾插法 添加数据
{
SNode* new_node = new SNode(node);
new_node->next = NULL;
if(m_pListHead == NULL)//头结点为空,就初始化头结点
{
Init_ListHead();
}
SNode* p = m_pListHead;
while(p->next)//遍历到链表最后一个节点,直到p->next为NULL
{
p = p->next;
}
p->next = new_node;//链表最后的节点指向新的节点,新的节点成为尾节点
}
bool CList::DelData(int id)//根据id删除数据
{
if(m_pListHead == NULL)
{
return false;
}
SNode* p = m_pListHead->next;//p遍历节点
SNode* q = m_pListHead;//q为p的前一个节点
while(p != NULL)//遍历链表
{
if(id == p->stu.GetId())//找到要删除的数据节点p
{
q->next = p->next;
delete p;
p = NULL;//置空,防止再次操作造成隐蔽错误
return true;
}
q = p;
p = p->next;
}
return false;
}
SNode* CList::FindData(int id)//根据id查找指定数据
{
if(m_pListHead == NULL)
{
return NULL;
}
SNode* p = m_pListHead->next;//p遍历节点
while(p != NULL)//遍历链表
{
if(id == p->stu.GetId())//找到要删除的数据节点p
{
return p;
}
p = p->next;
}
return NULL;
}
bool CList::UpdateData(int id, SNode& update)//根据id修改数据(更新)
{
if(m_pListHead == NULL)
{
return false;
}
SNode* findNode = NULL;
findNode = FindData(id);
if(findNode != NULL)
{
//memcpy(findNode, &update, sizeof(SNode)-sizeof(SNode*));//更新数据,不更新指针域
findNode->stu.SetId(update.stu.GetId());
findNode->stu.SetName(update.stu.GetName());
findNode->stu.SetClass(update.stu.GetClass());
findNode->stu.SetScore(update.stu.GetScore());
return true;
}
return false;
}
int CList::DisplayListData()//显示链表所有数据
{
if(m_pListHead == NULL)
{
return 0;
}
int count = 0;//记录数据的总条数
SNode* p = m_pListHead->next;
while(p != NULL)//遍历链表
{
count++;
cout<<"["<<count<<"]\t"<<setw(4)<<p->stu.GetId()<<" "<<setw(8)<<p->stu.GetName()<<" "<<setw(8)<<p->stu.GetClass()<<setw(8)<<p->stu.GetScore()<<endl;//(setw(8)输出宽度,默认右对齐)
p = p->next;
}
return count;
}
void CList::Clear()//清空链表。释放链表空间
{
if(m_pListHead == NULL)
{
return;
}
SNode* p = m_pListHead->next;
while(p != NULL)//遍历链表
{
m_pListHead->next = p->next;
delete p;
p = m_pListHead->next;
}
}
void CList::Sort(int type)//排序
{
if(m_pListHead == NULL)//空链表直接返回
{
return;
}
SNode* p, *q, *bigger;//排序辅助指针(以p为基准,q遍历连链表数据,temp在交换的数据时使用,指向需要交换时的较大者)
for(p = m_pListHead->next;p != NULL;p = p->next)
{
bigger = p;
for(q = p->next;q != NULL;q = q->next)
{
if( pFunArr[type](bigger, q) )//前面的比后面的大,就交换
{
bigger = q;//指向需要交换时的较大者
}
}
if(bigger != p)//需要交换
{
SNode temp = *bigger;//指针域不用交换
bigger->stu.SetId(p->stu.GetId());
bigger->stu.SetName(p->stu.GetName());
bigger->stu.SetClass(p->stu.GetClass());
bigger->stu.SetScore(p->stu.GetScore());
p->stu.SetId(temp.stu.GetId());
p->stu.SetName(temp.stu.GetName());
p->stu.SetClass(temp.stu.GetClass());
p->stu.SetScore(temp.stu.GetScore());
}
}
}
SNode* CList::GetListHead()//外界获取头结点指针的接口(头指针是private权限)
{
return this->m_pListHead;
}
int CList::Size()
{
if(m_pListHead == NULL)
{
return 0;
}
int count = 0;//数据的个数
SNode* p = m_pListHead;
while( (p=p->next) != NULL)
{
count++;
}
return count;
}
void AddMenu()//添加 菜单
{
cout<<"┏━━━━━━━━━━┓"<<endl;
cout<<"┃ 添加菜单 ┃"<<endl;
cout<<"┃ 【1】 添加到头部 ┃"<<endl;
cout<<"┃ 【2】 添加到尾部 ┃"<<endl;
cout<<"┃ 【0】 返回 ┃"<<endl;
cout<<"┗━━━━━━━━━━┛"<<endl;
cout<<" ******请输入0~2:";
}
void Add(CList& list)//添加处理
{
int id = -1;//接收用户输入的id
string name = "";//接收用户输入的姓名
string _class = "";//接收用户输入的班级
float score =0;
SNode new_node;//存储输入的合法数据
int choice = -1;//接收用户选择
char save = 'Y';//是否将数据保存到文件
char isAdd = 'N';//用来表识 用户是否有添加过数据,如果有会在返回上级菜单的时候提示用户保存到文件
char isContinue = 'Y';//表识是否继续添加
while(true)
{
system("cls");//清屏
AddMenu();//添加菜单
cin>>choice;//接收用户选择
switch(choice)
{
case 1://头插法
case 2://尾部添加
isContinue = 'Y';
while(isContinue == 'Y' || isContinue == 'y')//循环添加
{
cout<<"请输入学号:";
cin>>id;
if(id<=0)//检查用户输入的id是否合法
{
cout<<"序号应大于0!请重新输入!"<<endl;
}
else if(list.FindData(id) != NULL)//学号大于0但是已经存在
{
cout<<"学号 "<<id<<" 已经存在!请重新输入!"<<endl;
}
else//学号大于0且不存在
{
new_node.stu.SetId(id);//设置新的学号
for(;;)//循环接收用户输入的姓名,直到姓名不为空
{
cout<<"请输入姓名:";
cin>>name;
if(name.empty())//如果姓名为空
{
cout<<"姓名 不能为空!请重新输入!(按0结束输入)"<<endl;
continue;
}
break;
}
if(name == "0")//如果姓名为0,结束添加
{
break;//跳出循环
}
new_node.stu.SetName(name);//设新节点的姓名
for(;;)//循环接收用户输入的班级,直到班级不为空
{
cout<<"请输入班级:";
cin>>_class;
if(_class.empty())//如果班级为空
{
cout<<"班级 不能为空!请重新输入!(按0结束输入)"<<endl;
continue;
}
break;
}
if(_class == "0")//如果班级为0,结束添加
{
break;//跳出循环
}
new_node.stu.SetClass(_class);//设置新节点的班级
for(;;)//循环接收用户输入的score,直到score不为空
{
cout<<"请输入分数:";
cin>>score;
if(score<0)
{
cout<<"分数不能为负!请重新输入!(按0结束输入)"<<endl;
continue;
}
break;
}
if(score==0)//如果分数为0,结束添加
{
break;//跳出循环
}
new_node.stu.SetScore(score);
if(choice == 1)
{
list.AddHead(new_node);//头插法添加到链表
}
else
{
list.AddTail(new_node);//尾插法添加到链表
}
isAdd = 'Y';//表识用户添加了数据
}
cout<<"是否继续添加?(y/n):";
cin>>isContinue;
}
break;
case 0:
if(isAdd == 'Y')//用户添加过数据才提示保存
{
cout<<"是否保存到文件?(y/n)"<<endl;
cin>>save;
if(save == 'Y'|| save == 'y')
{
Save2File(list);//将数据保存到文件
cout<<"保存成功!"<<endl;
system("pause");
}
else//不保存
{
list.Clear();//清除数据
Read4File(list);//重新读取数据
}
}
return;
default:
cout<<"请输入0~2"<<endl;
system("pause");
break;
}
}
}
void DelMenu()//删除菜单
{
cout<<"┏━━━━━━━━━━┓"<<endl;
cout<<"┃ 删除菜单 ┃"<<endl;
cout<<"┃ 【1】 按学号删除 ┃"<<endl;
cout<<"┃ 【0】 返回 ┃"<<endl;
cout<<"┗━━━━━━━━━━┛"<<endl;
cout<<" ******请输入0~1:";
}
void Del(CList& list)//删除操作
{
int id = -1;
char choice = '0';//用户选择
bool isDel = false;//接收删除结果
char isSure = 'N';//提示用户 确认删除
SNode* findNode = NULL;//指向匹配的数据节点
while(true)
{
system("cls");//清屏
DelMenu();
cin>>choice;
if(choice == '1')
{
cout<<"请输入要删除的学号:";
}
else
{
break;
}
cin>>id;
if(id == 0)
{
break;
}
findNode = list.FindData(id);
if(findNode != NULL)//存在目标数据
{
cout<<"学号"<<"\t"<<"姓名"<<"\t"<<"班级"<<"\t"<<"分数"<<endl;
cout<<findNode->stu.GetId()<<"\t"<<findNode->stu.GetName()<<"\t"<<findNode->stu.GetClass()<<endl;
cout<<"已经找到学号为 "<<id<<"的数据,是否删除?(y/n):";
cin>>isSure;
if(isSure == 'Y' || isSure == 'y')//用户确认删除
{
isDel = list.DelData(id);
Save2File(list);//保存到文件
if(isDel)//删除成功
{
cout<<"已成功删除id为"<<id<<"的数据"<<endl;
}
else
{
cout<<"删除id为"<<id<<"的数据 失败!"<<endl;
}
}
}
else
{
cout<<"请检查"<<id<<"是否存在!"<<endl;
}
system("pause");
}
}
void FindMenu()//查找的菜单
{
cout<<"┏━━━━━━━━━━┓"<<endl;
cout<<"┃ 查找菜单 ┃"<<endl;
cout<<"┃ 【1】 按学号查找 ┃"<<endl;
cout<<"┃ 【2】 按姓名查找 ┃"<<endl;
cout<<"┃ 【3】 按班级查找 ┃"<<endl;
cout<<"┃ 【0】 返回 ┃"<<endl;
cout<<"┗━━━━━━━━━━┛"<<endl;
cout<<" ******请输入0~3:";
}
void Find(CList& list)//查找操作
{
int id = -1;//存放要查找的学号
string name_class = "";//存放要查找的姓名(或班级)
int choice = -1;//接收用户的选择
SNode* findNode = NULL;//接收查找结果
while(true)
{
system("cls");//清屏
FindMenu();//查找菜单
cin>>choice;//接收用户选择
switch(choice)
{
case 1://按学号查找,因为学号是唯一的,所以最多只有一个匹配的数据
cout<<"请输入要查找的学号:";
cin>>id;
findNode = list.FindData(id);
if(findNode != NULL)//找到数据
{
cout<<"\n已经找到id为"<<id<<"的数据"<<endl;
cout<<"学号"<<"\t"<<"姓名"<<"\t"<<"班级"<<endl;
cout<<findNode->stu.GetId()<<"\t"<<findNode->stu.GetName()<<"\t"<<findNode->stu.GetClass()<<"\t"<<findNode->stu.GetScore()<<endl;
}
else
{
cout<<"未找到,请检查学号 "<<id<<" 是否存在!"<<endl;
}
break;
case 2://按姓名查找,可能有重名的,所以结果可能包含多个数据
case 3:
{
if(choice == 2)
{
cout<<"请输入要查找的姓名:";
}
else
{
cout<<"请输入要查找的班级:";
}
cin>>name_class;
CList findList;//存放查询的结果
findNode = list.GetListHead();//获取链表头结点
if(findNode != NULL)
{
findNode = findNode->next;
while(findNode != NULL)//遍历数据链表,匹配就添加到结果链表
{
if( ((choice == 2) && name_class == findNode->stu.GetName()) ||
((choice == 3) && name_class == findNode->stu.GetClass()))//姓名(或班级)匹配
{
findList.AddTail(*findNode);//添加到结果链表中
}
findNode = findNode->next;
}
}
int count = findList.Size();//匹配到的数据数目
if( count>0 )//如果结果链表中匹配到有数据
{
if(choice == 2)
{
cout<<"\n已经找到姓名为 "<<name_class<<" 的数据"<<endl;
}
else
{
cout<<"\n已经找到班级为 "<<name_class<<" 的数据"<<endl;
}
cout<<"学号"<<"\t"<<"姓名"<<"\t"<<"班级"<<endl;
findNode = findList.GetListHead()->next;
while(findNode != NULL)
{
cout<<findNode->stu.GetId()<<"\t"<<findNode->stu.GetName()<<"\t"<<findNode->stu.GetClass()<<endl;
findNode = findNode->next;
}
cout<<"*****【共 "<<count<<" 名学生】*****\n"<<endl;
}
else
{
if(choice == 2)
{
cout<<"未找到,请检查姓名 "<<name_class<<" 是否存在!"<<endl;
}
else
{
cout<<"未找到,请检查班级 "<<name_class<<" 是否存在!"<<endl;
}
}
break;
}
case 0://返回
return;
default:
cout<<"请输入0~3"<<endl;
break;
}
system("pause");
}
}
void UpdateMenu()//更新菜单
{
cout<<"┏━━━━━━━━━━┓"<<endl;
cout<<"┃ 更新菜单 ┃"<<endl;
cout<<"┃ 【1】 按学号更新 ┃"<<endl;
cout<<"┃ 【0】 返回 ┃"<<endl;
cout<<"┗━━━━━━━━━━┛"<<endl;
cout<<" ******请输入0~1:";
}
void Update(CList& list)//更新操作
{
int id = -1;
int choice = -1;//用户的选择
bool isUpdate = NULL;//接收修改结果
string name = "";//新的姓名
string _class = "";//新的班级
float score=0;
SNode* findNode = NULL;//指向要更新的节点
SNode update;//新的数据
while(true)
{
system("cls");//清屏
UpdateMenu();//更新菜单
cin>>choice;//接收用户选择
switch(choice)
{
case 1:
cout<<"请输入要更新的学号:";
cin>>id;
findNode = list.FindData(id);
if(findNode == NULL)//不存在目标数据,则重新输入
{
cout<<"不存在此学号!"<<endl;
system("pause");
continue;
}
cout<<"\n已经找到id为"<<id<<"的数据"<<endl;
cout<<"学号"<<"\t"<<"姓名"<<"\t"<<"班级"<<"\t"<<"分数"<<endl;
cout<<findNode->stu.GetId()<<"\t"<<findNode->stu.GetName()<<"\t"<<findNode->stu.GetClass()<<"\t"<<findNode->stu.GetScore()<<endl;
update = *findNode;
cout<<"【输入0,表示不更改】"<<endl;
cout<<"将姓名:"<<findNode->stu.GetName()<<" 改为:";
cin>>name;
if(name != "0")
{
update.stu.SetName(name);
}
cout<<"将分数:"<<findNode->stu.GetScore()<<" 改为:";
cin>>score;
if(score != 0)
{
update.stu.SetScore(score);
}
cout<<"将班级:"<<findNode->stu.GetClass()<<" 改为:";
cin>>_class;
if(_class != "0")
{
update.stu.SetClass(_class);
}
if(name != "0" || _class != "0")//用户有更改
{
isUpdate = list.UpdateData(id, update);
if(isUpdate == true)
{
Save2File(list);//保存到文件
cout<<"更新成功!"<<endl;
}
else
{
cout<<"更新失败!"<<endl;
}
}
else
{
cout<<"未更改!"<<endl;
}
break;
case 0:
return;
default:
cout<<"请输入0~1"<<endl;
break;
}
system("pause");//因为有清屏动作,所以暂停一下,让用户查看输出信息
}
}
void Save2File(CList& list)//将数据保存到文件
{
SNode* listHead = list.GetListHead();//获取到链表头结点
if(listHead == NULL)
{
return;
}
ofstream fout(FILE_PATH,ios_base::binary);//不存在则创建,存在则会清空。
//fout.clear();//清空文件数据
SNode* p = listHead->next;
while(p !=NULL )
{
fout<<p->stu.ToString()<<" ";//以空格分隔数据
p = p->next;
}
fout.close();//关闭流
return;
}
void Read4File(CList& list)//读取文件数据 到链表中
{
SNode node;
int beforeId = -1;//上一个id
int id = -1;//临时存放学号
string name = "";//临时存放姓名
string _class = "";//存放班级
float score=0;
ifstream fin;
fin.open(FILE_PATH, ios_base::in);//打开文件
if(fin == NULL)//文件不存在,直接返回
{
return;
}
while(!fin.eof())//循环读取直到文件末尾
{
fin>>id>>name>>_class>>score;
if(id>0 && id != beforeId)//因为空格的原因 读取读后一个数据两次,这里使用beforeId来避免重复添加
{
node.stu.SetId(id);
node.stu.SetName(name);
node.stu.SetClass(_class);
node.stu.SetScore(score);
list.AddTail(node);//添加
}
beforeId = id;//记录上一次id
}
fin.close();//关闭文件流
return;
}
void ClearFileData()//清空文件数据,方便测试
{
char isSure = 'n';//是否确认清除数据
cout<<"确认清除文件数据?(y/n):";
cin>>isSure;
if(isSure == 'Y' || isSure == 'y')
{
ofstream fout(FILE_PATH);//不存在则创建,存在则会清空
fout.close();
cout<<"清除文件数据成功!"<<endl;
system("pause");
}
}
void SortMenu()//排序菜单
{
cout<<"┏━━━━━━━━━━┓"<<endl;
cout<<"┃ 排序菜单 ┃"<<endl;
cout<<"┃ 【1】 按学号排序 ┃"<<endl;
cout<<"┃ 【2】 按姓名排序 ┃"<<endl;
cout<<"┃ 【3】 按班级排序 ┃"<<endl;
cout<<"┃ 【4】 按分数排序 ┃"<<endl;
cout<<"┃ 【0】 返回 ┃"<<endl;
cout<<"┗━━━━━━━━━━┛"<<endl;
cout<<" ******请输入0~4:";
}
void Sort(CList& list)
{
char isSave = 'n';//是否将排序后的数据更新到文件
int choice = -1;
while(true)
{
system("cls");//清屏
SortMenu();
cin>>choice;
switch(choice)
{
case 1://按学号排序
case 2://按姓名排序
case 3:
case 4://按班级排序
list.Sort(choice-1);
if(choice == 1)
{
cout<<"***按学号升序排序如下:"<<endl;
}
else if(choice == 2)
{
cout<<"***按姓名升序排序如下:"<<endl;
}
else if(choice == 3)
{
cout<<"***按班级升序排序如下:"<<endl;
}
else if(choice == 4)
{
cout<<"***按分数升序排序如下:"<<endl;
}
cout<<"序号\t学号 姓名 班级 分数"<<endl;
list.DisplayListData();//显示
cout<<"是否将排序后的数据更新到文件?(y/n):";
cin>>isSave;
if(isSave == 'Y' || isSave == 'y')//确认保存到文件
{
Save2File(list);//将数据重新写入到文件
cout<<"保存数据成功!"<<endl;
system("pause");
}
else
{
list.Clear();//清空链表数据
Read4File(list);//重新加载数据文件
}
break;
case 0:
return;
break;
default:
cout<<"请输入0~3"<<endl;
system("pause");
break;
}
}
}
void MainMenu()//主菜单
{
cout<<"┏━━━━━━━━┓"<<endl;
cout<<"┃学生信息管理程序┃"<<endl;
cout<<"┃ 【1】 显示 ┃"<<endl;
cout<<"┃ 【2】 添加 ┃"<<endl;
cout<<"┃ 【3】 查找 ┃"<<endl;
cout<<"┃ 【4】 修改 ┃"<<endl;
cout<<"┃ 【5】 排序 ┃"<<endl;
cout<<"┃ 【6】 删除 ┃"<<endl;
cout<<"┃ 【7】 清空 ┃"<<endl;
cout<<"┃ 【0】 退出 ┃"<<endl;
cout<<"┗━━━━━━━━┛"<<endl;
cout<<" *****请输入0~7:";
}
node.h
//链表节点
typedef struct SNode
{
Student stu;//数据域
struct SNode* next;//指针域
SNode()//无参构造函数
{
stu.SetId(0);
next = NULL;
}
SNode(int id)//有参构造函数
{
stu.SetId(id);
next = NULL;
}
}SNode;
student.h
//学生类
#include
using namespace std;//int转string
class Student
{
private:
int m_id;//学号
string m_name;//姓名
string m_class;//班级
float m_score;
public:
Student()//无参构造函数
{
m_id = 0;
m_score=0;
m_name = "0";
m_class = "0";
}
Student(int id, string name, string _class,float score)//有参构造函数,class是关键字,所以不能用作变量名
{
if(id < 0)//确保id不为负数
{
id = 0;
}
this->m_id = id;
if(name.empty())//确保name不为空
{
name = "0";
}
this->m_name = name;
if(_class.empty())//确保_class不为空
{
_class = "0";
}
this->m_class = _class;
if(score<0)//确保_class不为空
{
score = 0;
}
this->m_score = score;
}
void SetId(int id)//设置id
{
if(id < 0 )//确保id>0,id=0为无效
{
id = 0;
}
this->m_id = id;
}
int GetId()//获取id
{
return this->m_id;
}
void SetName(string name)//设置姓名
{
if(name.empty())//确保name不为空
{
name = "0";
}
this->m_name = name;
}
string GetName()//获取姓名
{
return this->m_name;
}
void SetClass(string _class)//设置班级
{
if(_class.empty())//确保_class不为空
{
_class = "0";
}
this->m_class = _class;
}
string GetClass()//获取班级
{
return this->m_class;
}
void SetScore(float score)//设置id
{
if(score < 0 )//确保id>0,id=0为无效
{
score = 0;
}
this->m_score = score;
}
float GetScore()//获取id
{
return this->m_score;
}
string ToString()//将数据转为字符串形式,方便存到文件中
{
stringstream ss;
ss<<m_id<<" "<<m_name<<" "<<m_class<<" "<<m_score;//学号 姓名 班级
return ss.str();
}
};
使用GCC编译。