链表实现C/C++简单学生学籍管理系统。
//Main.cpp
#include"ManagerStu.h"
int Student::AGE[] = {
0 };
int Student::CLNUM[] = {
0 };
string Student::DEPART[] = {
" " };
int Student::departTypes = 0;
int Student::sizes = 0;
int main()
{
ManagerStu p;
p.start();
return 0;
}
//Student.h
#pragma once
#include
#include
#include
using namespace std;
class Student {
public:
Student();
void setBasic();//录入
void changeStu();//修改人员信息
Student* delMessage(int nums);//删除人员信息
Student* searchStu(int nums);//根据编号查找人员
Student* searchStu(string names);//根据姓名查找人员
Student* searchStuSex(string sex);//根据性别查找人员
Student* searchStuAge(int age);//根据年龄查找人员
Student* searchStuClass(int classNum);//根据班号查找人员
Student* searchStuDepart(string Depart);//根据系别查找人员
void searchAll();//调用上述查找函数
//判断输入是否合法
bool judgeNums(int num);//学号
bool judgeClass(int num);//班号
bool judgeSex(string u);//性别
bool judgeName(string& inStr);//名字
bool judgeAge(int num);//年龄
//容错,分别对应(调用)上面函数
void judge1(int num);//学号
void judge2(int num);//班号
void judge3(string u);//性别
void judge4(string& inStr);//名字
void judge5(int num);//年龄
void statisticsSex();//根据性别统计人数
void statisticsClass();//根据班号统计人数
void statisticsAge();//根据年龄统计人数
void statisticsDepart();//根据系别统计人数
void statisticsAll();//调用上述统计函数
void showMess();//输出学生信息
void showBasic();
void setBasicFile();//批量录入
void writeF(ofstream& ofs);
static int AGE[31];//年龄1-30
static int CLNUM[201];//班号1-200
static string DEPART[15];//系别的名称
static int departTypes;//系别类型个数
static int sizes;//总人数
Student* next = NULL;//指针
private:
int nums;//学号(10位)
string name;//名字
string sex;//性别
int age;//年龄
string department;//系别
string majoy;//专业
int classNum;//班号
};
//Student.cpp
#include"Student.h"
Student::Student() {
nums = 0;
name = " ";
sex = " ";
age = 0;
classNum = 0;
majoy = " ";
department = " ";
}
void Student::setBasic() {
//设置基本信息
cout << "依次输入学生的学号、姓名、性别、年龄、系、专业、班号:\n";
cin >> nums;
judge1(nums);
cin >> name;
judge4(name);
cin >> sex;
judge3(sex);
cin >> age;
judge5(age);
cin >> department >> majoy;
cin>> classNum;
judge2(classNum);
sizes++;
CLNUM[classNum]++;
AGE[age]++;
int i = 0;
while (i < departTypes) {
if (DEPART[i] == department) break;
i++;
}
if (i == departTypes) {
DEPART[i] = department;
departTypes++;
}
}
Student* Student::delMessage(int nums) {
//根据学号nums删除学生
Student* p = this;
Student* pLast = NULL;
while (p != NULL) {
if (p->nums != nums) {
pLast = p;
p = p->next;
}
else break;
}
if (p == NULL) {
cout << "查无此人!无法进行删除。\n";
return NULL;
}
else {
if (p->nums == this->nums) return p->next;//如果是表头,返回表头的next
else {
pLast->next = p->next;
AGE[p->age]--;
CLNUM[p->classNum]--;
delete p;
return this;
}
}
}
void Student::changeStu() {
//修改信息
cout << "输入相应学生的学号,进行修改信息:\n";
int u; cin >> u;
int times = 3;
while (times-- && !judgeNums(u))
cin >> u;
Student* p = this;
while (p != NULL) {
if (p->nums != u) p = p->next;
else break;
}
cout << "输入对应操作数进行修改:\n";
cout << "1.学号 2.姓名 3.性别 4.年龄 5.系别 6.专业 7.班号\n";
int oper;
cin >> oper;
switch (oper) {
case 1:
cout << "输入学号:";
cin >> p->nums;
p->judge1(p->nums);
break;
case 2:
cout << "输入姓名:";
cin >> p->name;
p->judge4(p->name);
break;
case 3:
cout << "输入性别:";
cin >> p->sex;
p->judge3(p->sex);
break;
case 4:
cout << "输入年龄:";
cin >> p->age;
p->judge5(p->age);
break;
case 5:
cout << "输入系别:";
cin >> p->department;
break;
case 6:
cout << "输入专业:";
cin >> p->majoy;
break;
case 7:
cout << "输入班号:";
cin >> p->classNum;
p->judge2(p->classNum);
break;
default:
break;
}
}
Student* Student::searchStu(int nums) {
//根据学号寻找学生
//修改后的:
Student* p = this;//得到已有的链表
Student* u = NULL;//返回的节点
while (p != NULL) {
if (p->nums != nums) p = p->next;
else {
u = new Student;//改的地方
*u = *p;
u->next = NULL;
return u;
}
}
return NULL;
//原来有bug的:
/* Student* p = this;
Student* u = NULL;
while (p != NULL) {
if (p->nums != nums) p = p->next;
else {
u = p;
u->next = NULL;//错在这里
return u;
}
}
return NULL;
*/
}
Student* Student::searchStu(string names) {
//根据名字寻找学生
Student* p = this;
Student* u = NULL;
while (p != NULL) {
if (p->nums != nums) p = p->next;
else {
u = new Student;
*u = *p;
u->next = NULL;
return u;
}
}
return NULL;
/*Student* p = this;
Student* u = new Student;
while (p != NULL) {
if (p->name != names) p = p->next;
else {
u = p;
u->next = NULL;
return u;
}
}
return NULL;*/
}
Student* Student::searchStuSex(string sex) {
//根据性别寻找学生
Student* p = this;
Student* temp = NULL, * head = NULL;
Student* tNext = NULL;
while (p != NULL) {
if (p->sex == sex) {
//找到相同性别,存下来
tNext = new Student;
*tNext = *p;
tNext->next = NULL;
if (head == NULL) {
//头节点为空
temp = tNext;
head = temp;
}
else {
//头节点非空
temp->next = tNext;
temp = temp->next;
}
if(tNext!=NULL)
tNext = tNext->next;
}
p = p->next;
}
if (head != NULL)
return head;
else return NULL;
}
Student* Student::searchStuAge(int age) {
//根据年龄寻找学生
Student* head = NULL;//头节点
Student* p = this;
Student* temp = NULL;
Student* tNext = NULL;
while (p != NULL) {
if (p->age == age) {
//找到相同年龄,存下来
tNext = new Student;
*tNext = *p;
tNext->next = NULL;//只留下此节点
if (head == NULL) {
//头节点为空
temp = tNext;
head = temp;
}
else {
//头节点非空
temp->next = tNext;
temp = temp->next;
}
if (tNext != NULL)
tNext = tNext->next;
}
p = p->next;
}
if (head != NULL)
return head;
else return NULL;
}
Student* Student::searchStuClass(int classNum) {
//根据班号寻找学生
Student* p = this;
Student* temp = NULL, * head = NULL;
Student* tNext = NULL;
while (p != NULL) {
if (p->classNum == classNum) {
tNext = new Student;
*tNext = *p;
tNext->next = NULL;
if (head == NULL) {
temp = tNext;
head = temp;
}
else {
temp->next = tNext;
temp = temp->next;
}
if (tNext != NULL)
tNext = tNext->next;
}
p = p->next;
}
if (head != NULL)
return head;
else return NULL;
}
Student* Student::searchStuDepart(string Depart) {
//根据系别寻找学生
Student* p = this;
Student* temp = NULL, * head = NULL;
Student* tNext = NULL;
while (p != NULL) {
if (p->department == Depart) {
tNext = new Student;
*tNext = *p;
tNext->next = NULL;
if (head == NULL) {
temp = tNext;
head = temp;
}
else {
temp->next = tNext;
temp = temp->next;
}
if (tNext != NULL)
tNext = tNext->next;
}
p = p->next;
}
if (head != NULL)
return head;
else return NULL;
}
void Student::searchAll() {
//控制寻找功能
cout << "1.按学号查询单个学生:\n";
cout << "2.按姓名查询单个学生\n";
cout << "3.按性别查询学生信息\n";
cout << "4.按班号查询学生信息\n";
cout << "请输入相应操作数:";
int u; cin >> u;
int numS;//学号
string nameS;//姓名
string sexX;//性别
int numC;//班号
Student* p = NULL;
switch (u) {
case 1:
cout << "输入学号:";
cin >> numS;
judge1(numS);
p = searchStu(numS);
if (p != NULL)p->showMess();
else cout << "查无此人!请重新操作\n";
break;
case 2:
cout << "输入性名:";
cin >> nameS;
judge4(nameS);
p = searchStu(nameS);
if (p != NULL)p->showMess();
else cout << "查无此人!请重新操作\n";
break;
case 3:
cout << "输入性别:";
cin >> sexX;
judge3(sexX);
p = searchStuSex(sexX);
if (p != NULL)p->showMess();
else cout << "查无此人!请重新操作\n";
break;
case 4:
cout << "输入班号:";
cin >> numC;
judge2(numC);
p = searchStuClass(numC);
if (p != NULL) p->showMess();
else cout << "查无此人!请重新操作\n";
break;
default:
break;
}
}
bool Student::judgeNums(int num) {
//学号为10位,除以10九次,余数在1-9范围内
for (int i = 1; i <= 9; i++)
num /= 10;
if (num == 0 || num > 10) return false;
else return true;
}
bool Student::judgeClass(int num) {
//判断班号是否超界
if (num >= 1 && num <= 200) return true;
else return false;
}
bool Student::judgeSex(string u) {
//判断性别格式是否符合
if (u == "男" || u == "女")return true;
else return false;
}
bool Student::judgeName(string& inStr) {
//判断姓名格式是否符合
unsigned char* str = (unsigned char*)inStr.c_str();
size_t length = inStr.length();
bool t = true;
for (size_t i = 0; i < length; ++i)
{
if (str[i] > 160)
t = true;
if (inStr[i]>=0 && inStr[i]<=127) {
t = false;
break;
}
}
if (t) return true;
else
return false;
}
bool Student::judgeAge(int num) {
if (num <= 30 && num >= 10) return true;
else return false;
}
void Student::judge1(int num) {
//对应judgeNums
int times = 4;
while (!judgeNums(nums) && times > 1) {
cout << "学号格式错误," << "还剩" << (times - 1) << "次输入机会:"; cin >> nums;
times--;
}
if (times == 1) {
cout << "输入学号错误!\n"; system("pause"); exit(0); }
else return;
}
void Student::judge2(int num) {
//对应judgeClass
int times = 4;
while (!judgeClass(classNum) && times>1) {
cout << "班号格式错误," << "还剩" << (times - 1) << "次输入机会:"; cin >> classNum;
times--;
}
if (times == 1) {
cout << "输入班号错误!\n"; system("pause"); exit(0); }
}
void Student::judge3(string u) {
//对应judgeSex
int times = 4;
while (!judgeSex(sex) && times>1) {
cout << "性别格式错误," << "还剩" << (times - 1) << "次输入机会:"; cin >> sex;
times--;
}
if (times == 1) {
cout << "输入性别错误!\n"; system("pause"); exit(0); }
}
void Student::judge4(string& inStr) {
//对应judgeName
int times = 4;
while (!judgeName(name) && times > 1) {
cout << "姓名格式错误," << "还剩" << (times - 1) << "次输入机会:"; cin >> name;
times--;
}
if (times == 1) {
cout << "输入姓名错误!\n"; system("pause"); exit(0); }
}
void Student::judge5(int num) {
//对应judgeAge
int times = 4;
while (!judgeAge(age) && times > 1) {
cout << "年龄输入错误," << "还剩" << (times - 1) << "次输入机会:"; cin >> age;
times--;
}
if (times == 1) {
cout << "输入年龄错误!\n"; system("pause"); exit(0); }
}
void Student::statisticsSex() {
//统计性别
cout << "按性别统计学生人数:" << '\n';
Student* p = searchStuSex("男");
int numS=0;
while (p != NULL) {
p = p->next;
numS++;
}
cout << "男生人数:" << numS << '\n';
cout << "女生人数:" << sizes-numS << '\n';
}
void Student::statisticsClass() {
//统计班号
int numC=0;
Student* p = NULL;
cout << "按班号统计学生人数:" << '\n';
for (int i = 1; i <= 200; i++) {
numC = 0;
if (CLNUM[i] != 0) {
p = searchStuClass(i);
while (p != NULL) {
p = p->next;
numC++;
}
cout << "班号:" << i << '\t' << "人数:" << numC << '\n';
}
else continue;
}
}
void Student::statisticsAge() {
//统计年龄
int numA = 0;
Student* p = NULL;
cout << "按年龄统计学生人数:" << '\n';
for (int i = 1; i <= 30; i++) {
numA = 0;
if (AGE[i] != 0) {
Student* p = searchStuAge(i);
while (p != NULL) {
p = p->next;
numA++;
}
cout << "年龄:" << i << " \t" << "人数:" << numA << '\n';
}
else continue;
}
}
void Student::statisticsDepart() {
//统计系别
int numD = 0;
cout << "按系别统计学生人数:" << '\n';
for (int i = 0; i < departTypes; i++) {
numD = 0;
Student* p = searchStuDepart(DEPART[i]);
while (p != NULL) {
p = p->next;
numD++;
}
cout << "系别:" << DEPART[i] << '\t' << "人数:" << numD << '\n';
}
}
void Student::statisticsAll() {
//控制统计功能
cout << "1.根据性别统计人数:\n";
cout << "2.根据班号统计人数\n";
cout << "3.根据年龄统计人数\n";
cout << "4.根据系别统计人数\n";
cout << "请输入相应操作数:";
int u; cin >> u;
switch (u) {
case 1:
statisticsSex();
break;
case 2:
statisticsClass();
break;
case 3:
statisticsAge();
break;
case 4:
statisticsDepart();
break;
default:
break;
}
}
void Student::showMess() {
//输出
Student* p = this;
cout << setiosflags(ios::left) << "学号:" << "\t\t" << "姓名:" << "\t\t" <<
"性别:" << "\t\t" << "年龄:" << "\t\t" << "系别:" << "\t\t" << "专业:" << "\t\t" << "班号:" << '\n';
while (p != NULL) {
p->showBasic();
p = p->next;
}
}
void Student::showBasic() {
//特定格式输出基本信息
cout << setw(16) << nums;
cout << setw(16) << name;
cout << setw(16) << sex;
cout << setw(16) << age;
cout << setw(16) << department;
cout << setw(16) << majoy;
cout << setw(16) << classNum;
cout<< '\n';
}
void Student::setBasicFile() {
//从文件批量录入
Student* p = this;
Student* pLast = NULL;//防止最后一个节点的next不为NULL
ifstream instuf("学生信息.txt", ios::in);
instuf.seekg(0, ios::beg);//指针指向文件头
instuf.peek();
if (instuf.eof()) cout << "文件为空!\n";
else {
//cout << "依次读入学生的学号、姓名、性别、年龄、系、专业、班号:\n";
while (!instuf.eof()) {
//这里不做容错的判断了
instuf >> p->nums;
if (!judgeNums(p->nums))break;
instuf >> p->name;
instuf >> p->sex;
instuf >> p->age >> p->department >> p->majoy;
instuf >> p->classNum;
sizes++;
CLNUM[p->classNum]++;
AGE[p->age]++;
int i = 0;
while (i < departTypes) {
if (DEPART[i] == p->department) break;
i++;
}
if (i == departTypes) {
DEPART[i] = p->department;
departTypes++;
}
p->next = new Student;
pLast = p;
p = p->next;
}
}
if (pLast != NULL)
pLast->next = NULL;
}
void Student::writeF(ofstream& ofs) {
//输出到文件中
Student* p = this;
if (p == NULL) {
cout << "没有数据! 请重新操作\n"; return; }
ofs << nums << ' ' << name << ' ' << sex << ' ' << age << ' ' << department << ' ' << majoy << ' ' << classNum << '\n';
}
//ManagerStu.h
#pragma once
#include"Student.h"
class ManagerStu {
public:
void start();//总开关
void outScreen();//显示菜单
void out();//退出
void oper();//操作
void writeFile();//保存在文件中
Student* readFile();//从文件中读取
private:
Student* head = NULL;
};
//ManagerStu.cpp
#include"ManagerStu.h"
void ManagerStu::start() {
this->outScreen();
this->oper();
}
void ManagerStu::outScreen() {
cout << "---------------------------------------------------------\n";
cout << "\n\n";
cout << " 学校学籍管理系统\n";
cout << " 实现功能:\n\n";
cout << " 1.录入 2.批量录入\n";
cout << " 3.删除 4.修改 5.查询 \n";
cout << " 6.所有信息分类统计 \n";
cout << " 7.输出所有学生信息\n";
cout << " 8.保存在文件中 \n\n";
cout << " 0.退出 \n";
cout << "\n\n";
cout << "---------------------------------------------------------\n";
}
void ManagerStu::out() {
exit(0);
}
void ManagerStu::oper() {
cout << "输入数字做相应操作:";
char t;//操作数
int u;//无固定用处
Student* p=NULL;
Student* pNext = NULL;//用来防止最后一个节点的next不为NULL
head = p;
Student* temp = head;
while (cin>>t) {
if(!(t <= '9' && t >= '0')){
cout << "无此操作数!请重新输入(退出输入0):\n";
cin >> t;
if (t == '0') out();
}
else {
switch (t) {
case '1':
pNext = new Student;
pNext->setBasic();
if (p == NULL) {
p = pNext;
head = p;
}
else {
p->next = pNext;
p = p->next;
}
pNext = pNext->next;
break;
case '2':
p = readFile();
//下面用来接在已经录入的学生的后面
temp = head;
while (temp != NULL && temp->next != NULL) temp = temp->next;
if (temp == NULL) head = p;
else
temp->next = p;
cout << "信息录入成功!\n";
while (p->next != NULL)p = p->next;
break;
case '3':
head->showMess();
cout << "输入要删除成员的学号:";
cin >> u;
head=head->delMessage(u);
head->sizes--;
cout << "删除后:\n";
head->showMess();
break;
case '4':
head->showMess();
head->changeStu();
cout << "修改后:\n";
head->showMess();
break;
case '5':
head->searchAll();
break;
case '6':
head->statisticsAll();
break;
case '7':
head->showMess();
break;
case '8':
writeFile();
cout << "信息保存成功!\n";
free(head);
head->sizes = 0;
head = NULL;
break;
case '0':
exit(0);
break;
default:
break;
}
}
system("pause");
system("cls");
outScreen();
cout << "输入数字做相应操作,输入0则退出\n";
}
}
void ManagerStu::writeFile() {
ofstream ofs;
Student* p = head;
ofs.open("学生信息.txt", ios::trunc);
while (p != NULL) {
p->writeF(ofs);
p = p->next;
}
ofs.close();
}
Student* ManagerStu::readFile() {
Student* p = new Student;
p->setBasicFile();
return p;
}
在做这玩意时,碰到最大的坑是,在按学号查找学生时原链表丢失了,导致花了好长时间找和改。