C语言课设----个人信息管理系统(包含学生成绩和消费记录)

前言

这次写课设时间的时间跨度有点大,最开始设计的程序流程、变量名、函数名等等都有不少问题、不合理的地方,充斥着不少初期留下的烂代码。希望读者明辨是非,别被我的烂代码给带跑了。那为什么我不具体指出哪些地方写得比较糟糕的?哈哈😄,这可是个不小的工程量,还是算了。

程序的总体功能图

在这里插入图片描述

1.head.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#include<stdbool.h>
#include<windows.h>
#include<time.h>

extern int currentColor;//全局文本颜色
extern int welcomeColor;//欢迎界面的颜色,用于个性化设置
extern int lengthOfListGrade; //成绩链表的长度
extern int lengthOfListConRec;//消费记录链表的长度

typedef struct basicInformation {
	char name[30];
	char student_number[15];//学号
	char gender[5];//填男或者女
	char academy[30];
	char major[20];
	char class_[25];
	char birthday[11];// 提示规范写法2000-01-01
	char hobby[10][20];//记得提示最多输入十个
	int hobby_length;
	char phone[12];//提示输入11位标准号码
	char address[20];//输入身份证户籍地,如Guangxi-nanning
	char password[16];//提示密码长度,带有大写字母、小写字母和数字
} BasInfo;

typedef struct grade {
	char subject[25];//科目
	char startTime[10];//学期
	double credit;//该学科的学分
	double usual;//平时成绩
	double midterm;//期中成绩
	double exam;//期末成绩
	double final;//最终成绩,即绩点
	char chongxiu[4];//是否为重修
	struct grade* next;
}GradeNode,* ListGrade;

typedef struct ConsumptionRecord {
	int LogID;//消费记录ID
	char contime[11];//消费时间
	char connote[8];//转账,餐饮,购物,交通,服务,医疗,教育,其他
	double charge;//消费金额
	struct ConsumptionRecord* next;
}ConRecNode,* ListConRec;


void menu(BasInfo basinfo, ListConRec listconrec, ListGrade listgrade);

void welcome();

void alter( BasInfo* basinfo,ListGrade listgrade,ListConRec listconrec);

void sort(ListGrade listgrade, ListConRec listconrec);

void seek(ListGrade listgrade, ListConRec listconrec);

void check(ListGrade listgrade, ListConRec listconrec);

void save(BasInfo basinfo, ListGrade listgrade, ListConRec listconrec);


void InitListGrade(ListGrade* head);
void InitListConRec(ListConRec* head);
struct basicInformation CreateBasInfo();          
struct grade *CreateList2ByFile(ListGrade head);                     
struct grade* CreateList2ByStdin(ListGrade head);
struct ConsumptionRecord *CreateList3ByFile(ListConRec head);               
struct ConsumptionRecord* CreateList3ByStdin(ListConRec head);


//通过位置删除链表1结点
int deleteGradeNode(struct grade* head, int position);  
//通过位置删除链表2结点
int deleteConRecNode( ConRecNode* head, int position);	
//根据学科名和学期删除数据
int deleteBySubAndTime(ListGrade head, char subject[], char startTime[]); 
//根据LogID删除数据
int deleteByLogID(ListConRec head, int LogID);                            


//插入成功返回1,否则返回0(已实现查重)
int insertGradeNode(struct grade* head, int position);	
//插入成功返回1,否则返回0(已实现查重)
int insertConRecNode( ConRecNode* head,int position);				             
struct grade* fileInsertGradeNode(struct grade* head);
ConRecNode* fileInsertConRecNode(ConRecNode* head);


//销毁链表														
void destroy2(struct grade* head);					  
void destroy3( ConRecNode* head);				


//打印单行成绩表的数据外加一条分割线。取消末尾换行!方便输出位置
void printData1(ListGrade p);
//通过输入位置来输出数据(带表头和分割线)
void outputNodeByPosition1(ListGrade head, int position);
//查询并输出重修的科目;已实现循环输入
void selectchongxiu(ListGrade head);
//通过输入学科名来输出单条数据;已实现循环输入
void selectBysubject(ListGrade head);     
/*通过输入学期来获得相关数据以及其他数据;已实现循环输入*/
void selectByStartTime(ListGrade head);
/*自带循环查询,也不用传入成绩作为参数。这里的简化做得还算漂亮!(其他地方可以参考)*/
void selectGrade(ListGrade head);
/*根据学科名和学期一起查询;与删除那个不一样,不用自己传进来参数了,在内部输入学科和学期;已实现循环输入*/
void selectBySubAndTime(ListGrade head);

/*打印单行消费记录表的数据外加一条分割线。取消末尾换行!方便输出位置*/
void printData2(ListConRec p);
/*根据LogID查询;不用传参,函数内部实现输入;内部实现了循环查询*/
void selectByLogID(ListConRec head);
//通过输入位置来输出数据(带表头和分割线)
void outputNodeByPosition2(ListConRec head, int position);
/*根据消费类型查询;不用传参,函数内部实现输入;内部实现了循环查询*/
void selectByConnote(ListConRec head);
/*根据消费时间查询;不用传参,函数内部实现输入;内部实现了循环查询*/
void selectByConTime(ListConRec head);
/*查询消费总额*/
void selectTotalCharge(ListConRec head);
/*根据消费金额查询( 可查 > = <  );不用传参,函数内部实现输入;内部实现了循环查询。里面的if-else语句可以合并变得短一点的,不合并也没关系*/
void selectCharge(ListConRec head);
/*查询某段时间的极值或者全部消费记录的极值;在内部实现了循环输入*/
void selectExtremum(ListConRec head);
/*查询某一时间段的所有消费记录;内部实现了循环查询*/
void selectPeriodData(ListConRec head);


//输出链表1全部数据
void print1( BasInfo head);	
//输出链表2全部数据
void print2(struct grade* head);	
//输出链表3全部数据
void print3( ConRecNode* head);	
//打印成绩表的表头
void outputFormHeadOfListGrade();
//打印消费记录表的表头
void outputFormHeadOfListConRec();


int readin1( BasInfo basinfo);						  
int readin2(struct grade* head);					  
int readin3( ConRecNode* head);						  
int saveAsCSV1(ListGrade head);
int saveAsCSV2(ListConRec head);


/*检查学号*/
bool checkstudent_number(char student_number[]);
/*检查性别格式*/
bool checkGender(char gender[]);
/*检查生日格式*/
bool checkdate(char birthday[]);
/*检查电话号码*/
bool checkPhone(char phone[]);
/*确定输入hobby是否结束( - 1为结束标志)*/
bool checkEnd(char hobby[], int index);
/*检查密码格式*/
bool checkPassword(char password[]);
/*检查重修*/
bool checkYN(char ch[]);
/*检查学年格式*/
bool checkdate2(char date[]);
/*检查是否输入了给定的消费类型*/
bool checkconnote(char connote[]);


/*返回实际长度,包括头节点*/
int getLengthOfListGrade(ListGrade head);
/*返回实际长度,包括头节点*/
int getLengthOfListConRec(ListConRec head);

/*手动输入Gradenode时检查重复, 检查依据是科目和学年。重复返回false,否则返回true*/
bool checkUniqueOfListGrade(ListGrade head, char subject[], char startTime[]);
/*手动输入ConRecNode时检查重复,检查依据是LogID。重复返回false,否则返回true*/
bool checkUniqueOfListConRec(ListConRec head, int LogID);
/*查找相同数据并输出,提供删除功能*/
void findSameNode1(ListGrade head);
/*查找相同数据并输出,提供删除功能*/
void findSameNode2(ListConRec head);
/*对比密码*/
bool comparePassword(BasInfo basinfo, char password[]);


//插入后可选的操作,包括输出数据、查看成绩表数据数量
void afterInsertIntoListGrade(ListGrade listgrade, int numBeforeInsert);
void afterInsertIntoListConRec(ListConRec listconrec, int numBeforeInsert);
//删除后可选的操作,包括输出数据、查看成绩表数据数量
void afterDeletefromListGrade(ListGrade listgrade, int numBeforeDelete);
void afterDeleteFromListConRec(ListConRec listconrec, int numBeforeDelete);
void afterSortListConRec(ListConRec listconrec);
void aboutFileOfListGrade();
void aboutFileOfListConRec();


//解决输入字母死循环的问题以及输入其他数字的问题
int checkNum();
int checkMenu();
int checkNum123();
int checkNum1234();
/*通用于所有数字的检查函数。以上的检查函数都太死了,这个通用的早就该写了(可以输入0)!*/
int checkAllNum(int max);
/*主要用于输入LogID,保证其大于0,并且在输入字符串时程序不至于崩溃*/
int scanfLogID();
/*用于输入一个大于0的double类型数值,并且在输入字符串时程序不至于崩溃*/
double scanfDouble();
//输入并返回一个正确的删除或插入的位置
int checkInsertDeletePosition1(ListGrade listgrade);
//输入返回一个正确的删除或插入的位置
int checkInsertDeletePosition2(ListConRec listconrec);
//用于输入字符串(能赋值)并检查长度,解决字符串过长的问题,
void checkCharsLength(char ch[], int length);

/*当传进来的参数相同时,可以实现隐藏文本,达到加密的目的*/
void setColor(UINT uFore, UINT uBack);
/*设置字体颜色*/
void setTextColor();
/*设置主菜单界面随机变色*/
void setWelcomeColor();


2.main.cpp

这里没有把创建的过程很好地封装起来,导致主函数不够简洁。

#include "head.h"

int main() {
	BasInfo basinfo;
	ListGrade headOfGrade;
	ListConRec headOfConRec;
	basinfo = CreateBasInfo();
	int createway;//创建方式
	int checkinput;//是否要查看信息表
	printf("您是否需要查看已构建好的个人信息表?\n<1>确认查看\t<2>取消查看\n");	
	if(checkNum()==1)
		print1(basinfo);
	//system("pause");
	InitListGrade(&headOfGrade);
	InitListConRec(&headOfConRec);
	printf("\n开始创建学生成绩表,请选择创建方式:\n<1> 文件导入\t <2> 手动输入\n");
	createway = checkNum();
	if (createway == 1) {
		printf("(1)查看文件导入方式使用说明\t(2)我已熟悉,无需说明\n");
		int aboutfile = checkNum();
		if (aboutfile == 1)
			aboutFileOfListGrade();
		headOfGrade = CreateList2ByFile(headOfGrade);
		findSameNode1(headOfGrade);
	}
		
	else if (createway == 2)
		headOfGrade = CreateList2ByStdin(headOfGrade);
	printf("\n学生成绩表创建结束\n");
	printf("您是否需要查看已构建好的学生成绩表?\n<1>确认查看\t<2>取消查看\n");
	checkinput = checkNum();
	if (checkinput == 1)
		print2(headOfGrade);
	//system("pause");

	printf("\n开始创建消费记录表\n请选择创建方式:\n<1> 文件导入\t <2> 手动输入\n");
	createway = checkNum();
	if (createway == 1) {
		printf("(1)查看文件导入方式使用说明\t(2)我已熟悉,无需说明\n");
		int aboutfile = checkNum();
		if (aboutfile == 1)
			aboutFileOfListConRec();
		headOfConRec = CreateList3ByFile(headOfConRec);
		findSameNode2(headOfConRec);
	}		
	else if (createway == 2)
		headOfConRec = CreateList3ByStdin(headOfConRec);
	printf("\n个人消费记录表创建结束\n\n");
	printf("您是否需要查看已构建好的学生成绩表?\n<1>确认查看\t<2>取消查看\n");
	checkinput = checkNum();
	if (checkinput == 1)
		print3(headOfConRec);
	//system("pause");
	menu(basinfo, headOfConRec, headOfGrade);	
	return 0;
}


3.InitList.cpp

创建带头结点的链表,方便进行插入和删除操作

#include "head.h"
 
void InitListGrade(ListGrade* head) {
	if ((*head = (ListGrade)malloc(sizeof(GradeNode))) == NULL) {
		printf("磁盘空间分配出错,创建信息表失败!\n");
		exit(-1);
	}
	(*head)->next = NULL;
}

void InitListConRec(ListConRec* head) {
	if ((*head = (ListConRec)malloc(sizeof(ConRecNode))) == NULL) {
		printf("磁盘空间分配出错,创建信息表失败!\n");
		exit(-1);
	}
	(*head)->next = NULL;
}

4.creat.cpp

每个链表都有两种创建数据的方式:手动输入和文件导入

#include "head.h"

int lengthOfListConRec = 1;
int lengthOfListGrade = 1;

struct basicInformation CreateBasInfo() {
	
	BasInfo basinfo;

	printf("\t\t■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
	printf("\t\t■       \t                                                ■      \n");
	printf("\t\t■       \t     欢迎使用个人信息管理系统                   ■      \n");
	printf("\t\t■       \t                                                ■      \n");
	printf("\t\t■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
	printf("\n\t\t◤欢迎欢迎 (≥◇≤) !初次使用 ~( ̄▽ ̄)~ ,请输入个人基本信息◥\n\n");

	printf("输入您的姓名:");
	checkCharsLength(basinfo.name,sizeof(basinfo.name));
	printf("\n");

	printf("请输入您的学号:");
	checkCharsLength(basinfo.student_number, sizeof(basinfo.student_number));
	while (!checkstudent_number(basinfo.student_number)) 	
		checkCharsLength(basinfo.student_number, sizeof(basinfo.student_number));
	
	printf("\n");

	printf("请输入您的性别:");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(填入男或女)\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	checkCharsLength( basinfo.gender,sizeof(basinfo.gender));
	while (!checkGender(basinfo.gender)) 
		checkCharsLength(basinfo.gender, sizeof(basinfo.gender));
	printf("\n");

	
	printf("请输入您的学院:");
	checkCharsLength(basinfo.academy,sizeof(basinfo.academy));
	printf("\n");

	printf("请输入您的班级:");
	checkCharsLength(basinfo.class_,sizeof(basinfo.class_));
	printf("\n");

	printf("请输入您的专业:");
	checkCharsLength(basinfo.major,sizeof(basinfo.major));
	printf("\n");

	printf("请输入您的生日:");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(格式为××××-××-××,如2022-01-01)\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	checkCharsLength(basinfo.birthday, sizeof(basinfo.birthday));
	while (!checkdate(basinfo.birthday)) 
		checkCharsLength(basinfo.birthday, sizeof(basinfo.birthday));
	
	printf("\n");

	printf("请输入您的爱好");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(最多输入十个!输入-1视为结束输入!):\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	char hobby_1[20];
	basinfo.hobby_length = 0;
	for (int i = 0; i < 10; i++) {
		scanf_s("%s", hobby_1,20);
		bool end = checkEnd(hobby_1, i);
		if (end)
			break;
		else 
			strcpy(basinfo.hobby[i], hobby_1);		
		basinfo.hobby_length++;
	}
	printf("\n");

	printf("请输入您的电话号码:");
	checkCharsLength(basinfo.phone, sizeof(basinfo.phone));
	while (!checkPhone(basinfo.phone)) 		
		checkCharsLength(basinfo.phone, sizeof(basinfo.phone));
	
	printf("\n");

	printf("请输入您的身份证户籍地,");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("格式如: 广西-南宁 \n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	checkCharsLength(basinfo.address, sizeof(basinfo.address));
	printf("\n");

	int inputpassword = 1;
	while (inputpassword == 1) {
		printf("请选择输入密码的方式:\n<1>普通输入\t<2>隐藏输入\n");
		int inputway = checkNum();		
		printf("请设置您的登录密码");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("(最长15位,必须包含大写字母、小写字母、阿拉伯数字)\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		if (inputway == 2) {
			setColor(2, 2);
			checkCharsLength(basinfo.password, sizeof(basinfo.password));
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
			while (!checkPassword(basinfo.password)) {
				setColor(2, 2);
				checkCharsLength(basinfo.password, sizeof(basinfo.password));
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
			}
		}
		else if (inputway == 1) {
			checkCharsLength(basinfo.password, sizeof(basinfo.password));
			while (!checkPassword(basinfo.password))
				checkCharsLength(basinfo.password, sizeof(basinfo.password));
			
		}
		printf("\n<1>重新设置密码\t<2>保存密码\n");
		inputpassword = checkNum();		
	}
	printf("\n");
	return basinfo;
}

struct ConsumptionRecord* CreateList3ByFile(ListConRec head) {
	ListConRec conrecnode, p = head;

	FILE* fp;
	char filename[50];
	printf("请输入存储数据的文件的绝对路径\n");
	checkCharsLength(filename, sizeof(filename));
	while (!(fp = fopen(filename, "r"))) {
		printf("文件找不到,可能路径名有误,请检查文件路径后重新输入!\n");
		checkCharsLength(filename, sizeof(filename));
	}
	printf("\n");
	while (1) {
		conrecnode = (ListConRec)malloc(sizeof(ConRecNode));
		if(EOF==fscanf(fp,"%d%s%s%lf",&conrecnode->LogID,conrecnode->contime,conrecnode->connote,&conrecnode->charge))
			break;
		p->next = conrecnode;
		conrecnode->next = NULL;
		p = conrecnode;
	}
	lengthOfListConRec = getLengthOfListConRec(head)-1;
	fclose(fp);
	return head;
}

struct grade* CreateList2ByFile(ListGrade head) {     
	ListGrade gradenode,p=head;
	char filename[50];
	printf("请输入存储数据的文件的绝对路径\n");
	checkCharsLength(filename, sizeof(filename));
	FILE* fp;
	while (!(fp = fopen(filename, "r"))) {
		printf("文件找不到,可能路径名有误,请检查文件路径后重新输入!\n");
		checkCharsLength(filename, sizeof(filename));
	}
	printf("\n");
	while (1) {
		gradenode = (ListGrade)malloc(sizeof(GradeNode));
		if (EOF == fscanf(fp, "%s %s %lf %lf %lf %lf %lf %s", gradenode->subject, gradenode->startTime,&gradenode->credit ,&gradenode->usual, &gradenode->midterm, &gradenode->exam,&gradenode->final, gradenode->chongxiu))
			break;
		p->next = gradenode;
		gradenode->next = NULL;
		p = gradenode;
	}
	lengthOfListGrade = getLengthOfListGrade(head)-1;
	fclose(fp);
	return head;
}

struct grade* CreateList2ByStdin(ListGrade head) {
	ListGrade p=head, q;
	printf("您将通过手动输入数据创建学生成绩信息表,请按照引导规范输入数据!\n");
	
	int pointer=1;
	while (pointer==1) {
		q = (ListGrade)malloc(sizeof(GradeNode));

		printf("请输入科目:\n");
		char subject[25];
		checkCharsLength(subject, sizeof(subject));
		//不可以这样子直接赋值:q->subject = subject;	

		printf("\n请输入学期");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("(格式为2022-春或2022-夏或2022-秋):\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		char startTime[10];
		checkCharsLength(startTime, sizeof(startTime));
		while (!checkdate2(startTime)) 
			checkCharsLength(startTime, sizeof(startTime));
		
		//开始查重:
		if (!checkUniqueOfListGrade(head,subject,startTime)) 
			continue;
		
		//确认不重复才赋值:
		strcpy(q->subject, subject);
		strcpy(q->startTime, startTime);

		printf("\n请输入该学科的学分:\n");
		double credit=scanfDouble();	
		q->credit = credit;

		printf("\n请输入平时成绩:\n");
		double usual = scanfDouble();
		q->usual = usual;

		printf("\n请输入期中成绩:\n");
		double midterm = scanfDouble();
		q->midterm = midterm;

		printf("\n请输入期末成绩:\n");
		double exam = scanfDouble();
		q->exam = exam;

		printf("\n请输入最终成绩(即加权成绩):\n");
		double final = scanfDouble();
		q->final = final;

		printf("\n该学科是否为重修?");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("(输入是或否)\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		char chongxiu[4];
		checkCharsLength(chongxiu, sizeof(chongxiu));
		//q->chongxiu = chongxiu;
		while (!checkYN(chongxiu)) 
			checkCharsLength(chongxiu, sizeof(chongxiu));		
		strcpy(q->chongxiu, chongxiu);

		q->next = NULL;
		p->next = q;
		p = q;

		printf("\n<1> 继续创建\t <2> 结束创建\n");
		pointer = checkNum();
		lengthOfListGrade++;
	}
	return head;
}

struct ConsumptionRecord* CreateList3ByStdin(ListConRec head) {
	printf("\n您将通过手动输入数据创建消费记录信息表,请按照引导规范输入数据!\n");
	
	ListConRec p = head, q;
	int pointer=1;
	
	while (pointer==1) {
		q = (ListConRec)malloc(sizeof(ConRecNode));

		printf("\n请输入该条消费记录的专属ID");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("(纯数字)\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		int LogID=scanfLogID();
		if (!checkUniqueOfListConRec(head,LogID)) 
			continue;
		
		q->LogID = LogID;

		printf("\n请输入消费时间");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("(格式为××××-××-××,如2022-01-01)\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		char contime[12];
		checkCharsLength(contime, sizeof(contime));
		while (!checkdate(contime)) {
			checkCharsLength(contime, sizeof(contime));
		}
		strcpy(q->contime, contime);

		printf("\n请输入消费类型\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("可选择:\n转账;餐饮,购物,交通,服务,医疗,教育,其他\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		char connote[8];
		checkCharsLength(connote, sizeof(connote));
		while (!checkconnote(connote)) {
			checkCharsLength(connote, sizeof(connote));
		}
		strcpy(q->connote, connote);

		printf("\n请输入消费金额:\n");
		double charge = scanfDouble();
		q->charge = charge;

		q->next = NULL;
		p->next = q;
		p = q;
		
		printf("\n<1> 继续创建\t<2> 结束创建\n");
		pointer = checkNum();
		lengthOfListConRec++;
	}
	return head;
}

5.checkFormat.cpp

用来检查输入的数据,保证用户在输入时按照一定的格式和要求。还有一个封装好的check()函数,供后面的menu()函数直接调用。

#include "head.h"

bool checkstudent_number(char student_number[]) {
	for (int i = 0; i < strlen(student_number); i++) {	
		if (student_number[i] < '0' || student_number[i]>'9') {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("学号只能包含阿拉伯数字,请重新输入学号!\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			return false;
		}	
	}
	return true;
}

bool checkGender(char gender[]){
	if (strcmp(gender, "male") == 0 || strcmp(gender, "female") == 0)
		return true;
	else if (strcmp(gender, "男") == 0 || strcmp(gender, "女") == 0)
		return true;
	else {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("请输入男或女!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		return false;
	}
}

bool checkdate(char birthday[]) {
	if (birthday[4] != '-' || birthday[7] != '-' || strlen(birthday)<10) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("格式错误,请重新输入日期\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
		return false;
	}
	for (int i = 0; i < strlen(birthday); i++) {
		if (i != 4 && i != 7) {
			if (birthday[i] < '0' || birthday[i]>'9') {
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
				printf("格式错误,请重新输入日期\n");
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
				return false;
			}
		}
	}

	int tab[2][13] = {
		{0,31,28,31,30,31,30,31,31,30,31,30,31},
		{0,31,29,31,30,31,30,31,31,30,31,30,31}
	};
	int year = (birthday[0] - '0') * 1000 + (birthday[1] - '0') * 100 + (birthday[2] - '0') * 10 + (birthday[3] - '0');
	int runOrping = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);//判断是闰年还是平年
	int month = (birthday[5] - '0') * 10 + (birthday[6] - '0');
	int day = (birthday[8] - '0') * 10 + (birthday[9] - '0');
	if (month > 12 || day > 31) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("格式错误,请重新输入日期\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return false;
	}
	if (day > tab[runOrping][month]) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("格式错误,请重新输入日期\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return false;
	}
	return true;
}
/*只检查,不输出提示*/
bool justcheckdate(char birthday[]) {
	if (birthday[4] != '-' || birthday[7] != '-' || strlen(birthday) < 10)
		return false;	
	for (int i = 0; i < strlen(birthday); i++) {
		if (i != 4 && i != 7) 
			if (birthday[i] < '0' || birthday[i]>'9') 
				return false;		
	}
	int tab[2][13] = {
		{0,31,28,31,30,31,30,31,31,30,31,30,31},
		{0,31,29,31,30,31,30,31,31,30,31,30,31}
	};
	int year = (birthday[0] - '0') * 1000 + (birthday[1] - '0') * 100 + (birthday[2] - '0') * 10 + (birthday[3] - '0');
	int runOrping = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);//判断是闰年还是平年
	int month = (birthday[5] - '0') * 10 + (birthday[6] - '0');
	int day = (birthday[8] - '0') * 10 + (birthday[9] - '0');
	if (month > 12 || day > 31) 
		return false;	
	if (day > tab[runOrping][month]) 
		return false;	
	return true;
}

bool checkPhone(char phone[]) {
	if (strlen(phone) != 11) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("号码长度有误,请重新输入!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		return false;
	}
	for (int i = 0; i < strlen(phone); i++) {
		if (phone[i] < '0' || phone[i]>'9') {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("格式错误,请重新输入号码\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			return false;
		}
	}
	return true;
}

bool checkEnd(char hobby[], int index) {
	if (strcmp(hobby, "-1") == 0)
		return true;
	return false;
}

bool checkPassword(char password[]) {
	int daxie = 0, xiaoxie=0, digit=0;
	if (strlen(password) > 15) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("长度超出限制,最长15位!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
		return false;
	}
	for (int i = 0; i < strlen(password); i++) {
		if (password[i] >= '0' && password[i] <= '9')
			digit = 1;
		if (password[i] >= 'a' && password[i] <= 'z')
			xiaoxie = 1;
		if (password[i] >= 'A' && password[i] <= 'Z')
			daxie = 1;
		if (digit && xiaoxie && daxie)
			return true;
	}
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
	printf("密码格式有误,请按照正确格式重新输入!\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	return false;
}

bool checkYN(char ch[]) {
	if (strcmp(ch,"是")==0 || strcmp(ch,"否")==0)
		return true;
	else {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("输入错误,请输入 “是” 或者 “否”\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
		return false;
	}
}

bool justcheckYN(char ch[]) {
	if (strcmp(ch, "是") == 0 || strcmp(ch, "否") == 0)
		return true;
	else {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return false;
	}
}

bool checkdate2(char date[]) {

	if (date[4] != '-' || strlen(date)!=7) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("格式错误!请重新输入:\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		return false;
	}
	for (int i = 0; i < 4; i++) {		
		if (date[i] < '0' || date[i]>'9') {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("格式错误!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			return false;
		}		
	}
	char t[3];
	t[0] = date[5];
	t[1] = date[6];
	t[2] = '\0';
	if (strcmp(t, "春") != 0 && strcmp(t, "夏") != 0 && strcmp(t, "秋") != 0) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("格式错误!请重新输入:\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return false;
	}
	return true;
}
/*只检查,不输出提示*/
bool justcheckdate2(char date[]) {
	if (date[4] != '-' || strlen(date) != 7) 
		return false;	
	for (int i = 0; i < 4; i++) {
		if (date[i] < '0' || date[i]>'9') 			
			return false;		
	}
	char t[3];
	t[0] = date[5];
	t[1] = date[6];
	t[2] = '\0';
	if (strcmp(t, "春") != 0 && strcmp(t, "夏") != 0 && strcmp(t, "秋") != 0) 
		return false;	
	return true;
}

bool checkconnote(char connote[]) {
	if (strcmp(connote, "转账") == 0 || strcmp(connote, "餐饮") == 0 || strcmp(connote, "购物") == 0 || strcmp(connote, "交通") == 0 || strcmp(connote, "服务") == 0 || strcmp(connote, "医疗") == 0 || strcmp(connote, "教育") == 0 || strcmp(connote, "其他") == 0)
		return true;
	else {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("请按照给出的消费类型选一个输入!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		return false;
	}
}


int getLengthOfListGrade(ListGrade head) {
	ListGrade p = head;
	int length = 0;
	while (p) {
		length++;
		p = p->next;
	}
	return length;
}
int getLengthOfListConRec(ListConRec head) {
	ListConRec p = head;
	int length = 0;
	while (p) {
		length++;
		p = p->next;
	}
	return length;
}

bool comparePassword(BasInfo basinfo,char password[]) {
	if (strcmp(basinfo.password, password) == 0) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 9);
		printf("密码正确\n\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return true;
	}
	else {	
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("密码错误\n\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return false;
	}
}

int checkNum() {
	int num;
	int checkinput;

	num=scanf("%d", &checkinput);
	char rubbish[128];
	while (checkinput != 1 && checkinput != 2) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入1或2!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num=scanf("%d", &checkinput);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请正确输入1或2!其他数字无效!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
			num=scanf("%d", &checkinput);
		}
	}
	return checkinput;
}

int checkNum123() {
	int num;
	int checkinput;

	num = scanf("%d", &checkinput);
	char rubbish[128];
	while (checkinput < 1 || checkinput>3) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入1、2、3!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &checkinput);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请正确输入1、2、3!其他数字无效!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &checkinput);
		}
	}
	return checkinput;
}

int checkNum1234() {
	int num;
	int checkinput;

	num = scanf("%d", &checkinput);
	char rubbish[128];
	while (checkinput < 1 || checkinput>4) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入1、2、3或4,不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
			num = scanf("%d", &checkinput);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入1、2、3或4,其他数字无效!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &checkinput);
		}
	}
	return checkinput;
}

int checkMenu() {
	int num;
	int menu;
	char rubbish[128];
	num = scanf("%d", &menu);
	while (menu < 0 || menu > 9) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &menu);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入0-9的数字!\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &menu);
		}
	}
	return menu;
}

int checkAllNum(int max) {
	int num;
	int menu;
	char rubbish[128];
	num = scanf("%d", &menu);
	while (menu < 0 || menu > max) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &menu);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入0-%d的数字!\n", max);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &menu);
		}
	}
	return menu;
}

int checkInsertDeletePosition1(ListGrade listgrade) {
	int length = getLengthOfListGrade(listgrade) - 1;
	int num;
	int position;
	char rubbish[128];
	num = scanf("%d", &position);
	while (position<=0 || position>length) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			num = scanf("%d", &position);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入1-%d的数字\n", length);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
			num = scanf("%d", &position);
		}
	}
	return position;
}

int checkInsertDeletePosition2(ListConRec listconrec) {
	int length = getLengthOfListConRec(listconrec) - 1;
	int num;
	int position;
	char rubbish[128];
	num = scanf("%d", &position);
	while (position<=0 || position>length) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &position);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入1-%d的数字\n", length);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			num = scanf("%d", &position);
		}
	}
	return position;
}

int checkColorNum() {
	int num;
	int color;
	char rubbish[128];
	num = scanf("%d", &color);
	while (color <= 0 || color>15) {
		if (num == 0) {
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &color);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入1-15的数字!\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &color);
		}
	}
	return color;
}

void checkCharsLength(char ch[],int length) {
	char char_Temp[1024];
	scanf_s("%s", char_Temp,1024);
	//这里length减一是为了给'\0'留下一个位置,不然还是会溢出
	while (strlen(char_Temp) > length-1) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("最多输入:%d字节\n", length-1);
		printf("实际输入:%d字节\n", strlen(char_Temp));
		printf("您输入了过多的字符!赋值失败!请重新输入:\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
		scanf_s("%s", char_Temp,1024);
	}
	strcpy(ch, char_Temp);
}

int scanfLogID() {
	int LogID,num;
	num=scanf("%d", &LogID);
	while (LogID <= 0) {
		if (num == 0) {
			char rubbish[128];
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			num = scanf("%d", &LogID);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入大于0的数字\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%d", &LogID);
		}
	}
	return LogID;
}

double scanfDouble() {
	double result;
	int num;
	num = scanf("%lf", &result);
	while (result < 0) {
		if (num == 0) {
			char rubbish[128];
			scanf("%s", rubbish);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("请输入数字!不可以输入其他字符!请重新输入:\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			num = scanf("%lf", &result);
		}
		else {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			printf("数字范围有误!请输入不小于0的数字\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			num = scanf("%lf", &result);
		}
	}
	return result;
}


void check(ListGrade listgrade, ListConRec listconrec) {
	int checkcontinue = 1;
	while (checkcontinue == 1) {
		printf("\n<1>检查重复数据\t<2>检查数据内容格式\t<3>取消检查\n");
		int checktype = checkNum123();
		if (checktype == 1) {
			printf("(1)检查学生成绩表\t(2)检查消费记录表\t(3)取消本次检查\n");
			int listtype = checkNum123();
			if (listtype == 1)
				findSameNode1(listgrade);
			else if (listtype == 2)
				findSameNode2(listconrec);
			else if (listtype == 3)
				printf("您已取消本次检查\n");
		}
		else if (checktype == 2) {
			printf("(1)检查学生成绩表\t(2)检查消费记录表\t(3)取消本次检查\n");
			int listtype = checkNum123();
			if (listtype == 1) {
				ListGrade p = listgrade->next;	
				int errornum = 0;
				for (int i = 1; i <= lengthOfListGrade && p; i++) {
					int flag = 0;
					int error[7];
					if (!justcheckdate2(p->startTime)) {
						flag++;
						errornum++;
						error[0] = 1;
					}						
					if (p->credit < 0) {
						error[1] = 1;
						flag++;
						errornum++;
					}
					if (p->usual < 0 ) {
						error[2] = 1;
						flag++;
						errornum++;
					}
					if (p->midterm < 0) {
						error[3] = 1;
						flag++;
						errornum++;
					}
					if (p->exam < 0) {
						error[4] = 1;
						flag++;
						errornum++;
					}
					if (p->final < 0) {
						error[5] = 1;
						flag++;
						errornum++;
					}
					if (!justcheckYN(p->chongxiu)) {
						error[6] = 1;
						flag++;
						errornum++;
					}	
					if (flag > 0) {
						printf("\n第%d条数据存在以下错误:\n",i);
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
						if (error[0] == 1)
							printf("学期错误!\t");
						if (error[1] == 1)
							printf("学分输入错误!\t");
						if (error[2] == 1)
							printf("平时成绩输入错误!\t");
						if (error[3] == 1)
							printf("期中成绩输入错误!\t");
						if (error[4] == 1)
							printf("期末成绩输入错误!\t");
						if (error[5] == 1)
							printf("加权成绩输入错误!\t");
						if (error[6] == 1)
							printf("是否重修输入错误!\t");
						printf("\n");
						outputNodeByPosition1(listgrade, i);
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
					}
					p = p->next;
				}
				if (errornum == 0)
					printf("无错误\n");
				else
					printf("\n当前学生成绩表中有%d处错误\n\n",errornum);				
			}
			else if (listtype == 2) {
				ListConRec p = listconrec->next;
				int errornum = 0;
				for (int i = 1; i <= lengthOfListConRec && p; i++) {
					int flag = 0;
					int error[4];
					if (p->LogID < 0) {
						error[0] = 1;
						flag++;
						errornum++;
					}
					if (!justcheckdate(p->contime)) {
						error[1] = 1;
						flag++;
						errornum++;
					}
					if (!checkconnote(p->connote)) {
						error[2] = 1;
						flag++;
						errornum++;
					}
					if (p->charge < 0) {
						error[3] = 1;
						flag++;
						errornum++;
					}
					if (flag > 0) {
						printf("\n第%d条数据存在以下错误:\n",i);
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
						if (error[0] == 1)
							printf("LogID错误\t");
						if (error[1] == 1)
							printf("消费时间错误\t");
						if (error[2] == 1)
							printf("消费类型错误\t");
						if (error[3] == 1)
							printf("消费金额错误\t");
						printf("\n");
						outputNodeByPosition2(listconrec, i);
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
					}
					p = p->next;
				}
				if (errornum == 0)
					printf("无错误\n");
				else
					printf("\n当前消费记录表中有%d处错误\n\n",errornum);
			}
			else
				printf("您已取消本次检查\n");
		}
		else if(checktype==3){
			printf("您已取消检查\n");
			break;
		}
		if (checktype != 3) {
			printf("<1>继续检查\t<2>退出检查\n");
			checkcontinue = checkNum();
		}
	}
	
}

6.checkRebundunce.cpp

检查重复数据的函数

#include "head.h"


bool checkUniqueOfListGrade(ListGrade head,char subject[],char startTime[]) {
	ListGrade p = head;
	while (p) {
		if (strcmp(p->subject, subject) == 0 && strcmp(p->startTime, startTime) == 0) {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
			printf("您要输入的同一学期的科目已存在,请勿重复添加!\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			return false;
		}
		p = p->next;
	}
	return true;
}

bool checkUniqueOfListConRec(ListConRec head, int LogID) {
	ListConRec p = head;
	while (p) {
		if (p->LogID == LogID) {
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
			printf("您要输入的LogID已存在,请重新输入!\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			return false;
		}
		p = p->next;
	}
	return true;
}

void findSameNode1(ListGrade head) {
	ListGrade p = head->next,q;
	int outerPosition = 1;
	int rebundance[150];
	int k = 0;
	int j = 1;
	while (p->next) {
		int i = 1;
		int innerPosition = 1;
		q = p->next;
		while (q) {			
			if (p!=q && strcmp(p->startTime, q->startTime) == 0 && strcmp(p->subject, q->subject) == 0) {
				int flag = 0;
				for (int l = 0; l < sizeof(rebundance) / sizeof(rebundance[0]) && rebundance[l] != 0; l++) {
					if (outerPosition == rebundance[l]) {
						flag = 1;
						break;						
					}						
				}
				if (flag != 1) {
					rebundance[k++] = innerPosition+outerPosition;
					if (j == 1) {
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
						printf("判断重复的依据为学期和学科名\n\n");
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);						
						printf("+------------------+---------+-----+--------+--------+--------+--------+----+\n");
						printf("|       科目       |  学期   |学分 |平时成绩|期中成绩|期末成绩|最终成绩|重修|\n");
						printf("+------------------+---------+-----+-------+--------+--------+--------+----+\n");
					}
					
					if (i == 1)
						printf("\n|%-18s|%-9s|%-5.2lf|%-8.2lf|%-8.2lf|%-8.2lf|%-8.2lf|%-4s|\n", p->subject, p->startTime, p->credit, p->usual, p->midterm, p->exam, p->final, p->chongxiu);
					printf("|%-18s|%-9s|%-5.2lf|%-8.2lf|%-8.2lf|%-8.2lf|%-8.2lf|%-4s|", q->subject, q->startTime, q->credit, q->usual, q->midterm, q->exam, q->final, q->chongxiu);
					printf("第 %d 条数据与第 %d 条数据可能重复!\n", outerPosition, outerPosition + innerPosition);
					i++; j++;
				}				
			}
			innerPosition++;
			q = q->next;
		}
		p = p->next;
		outerPosition++;
	}
	if (j > 1) {
		printf("是否立即删除重复数据?\n<1>开始删除\t<2>暂不删除\n");
		int deletenow = checkNum();
		int deleteContinue = 1;
		if (deletenow == 1) {
			while (deleteContinue == 1) {
				int assuredelete = 1;
				printf("请输入要删除的数据的位置:\n");
				int deletePosition = checkInsertDeletePosition1(head);
				printf("数据的顺序可能改变,是否要先查看一下即将删除的数据\n(1)确认查看\t(2)不查看\n");
				int checkData = checkNum();
				if (checkData == 1) {
					outputNodeByPosition1(head, deletePosition);
					printf("(1)确认删除\t(2)取消删除\n");
					assuredelete = checkNum();
				}

				if (assuredelete == 1 && deleteGradeNode(head, deletePosition)) 
					printf("删除成功!\n");			
					
				printf("(1)继续删除\t(2)退出删除\n");
				deleteContinue = checkNum();
			}
		}
	}
	else
		printf("无重复数据\n");
}

void findSameNode2(ListConRec head) {
	ListConRec p = head->next, q;
	int outerPosition = 1;
	int rebundance[950];
	int k = 0;
	int j = 1;
	while (p->next) {
		int i = 1;
		q = p->next;
		int innerPosition = 1;
		while (q) {			
			if (p != q && q->LogID == p->LogID) {
				int flag = 0;
				for (int l = 0; l < sizeof(rebundance) / sizeof(rebundance[0])&& rebundance[l]!=0; l++) {
					if (outerPosition == rebundance[l]) {
						flag = 1;
						break;
					}
				}
				if (flag != 1) {
					rebundance[k++] = innerPosition + outerPosition;
					if (j == 1) {
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
						printf("判断重复的依据为LogID\n\n");
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),currentColor);
						printf("+--------------+------------+--------+----------------+\n");
						printf("|     LogID    |  消费时间  |消费类型|  消费金额      |\n");
						printf("+--------------+------------+--------+----------------+\n");
					}					
					if (i == 1)
						printf("\n|%-14d|%-12s|%-8s|%-16.2lf|\n", p->LogID, p->contime, p->connote, p->charge);
					printf("|%-14d|%-12s|%-8s|%-16.2lf|", q->LogID, q->contime, q->connote, q->charge);
					printf("第 %d 条数据与第 %d 条数据可能重复!\n", outerPosition, outerPosition + innerPosition);
					i++; j++;
				}			
			}
			innerPosition++;
			q = q->next;
		}
		p = p->next;
		outerPosition++;
	}
	if (j > 1) {
		printf("是否立即删除重复数据?\n<1>开始删除\t<2>暂不删除\n");
		int deletenow = checkNum();
		int deleteContinue = 1;
		if (deletenow == 1) {
			while (deleteContinue == 1) {
				int assuredelete = 1;
				printf("请输入要删除的数据的位置:\n");
				int deletePosition = checkInsertDeletePosition2(head);
				printf("数据的顺序可能改变,是否要先查看一下即将删除的数据\n(1)确认查看\t(2)不查看\n");
				int checkData = checkNum();
				if (checkData == 1) {
					outputNodeByPosition2(head, deletePosition);
					printf("(1)确认删除\t(2)取消删除\n");
					assuredelete = checkNum();
				}
				if (assuredelete == 1 && deleteConRecNode(head, deletePosition)) 
					printf("删除成功!\n");
										
				printf("(1)继续删除\t(2)退出删除\n");
				deleteContinue = checkNum();
			}
		}
	}
	else
		printf("无重复数据\n");
}

7.menu.cpp

菜单函数这里,部分模块的功能没有完全封装起来,导致这里代码量过大了。当初也没想到一个模块要写这么多代码,后来才把单个模块的功能完全封装起来,而不只是利用写好的相关函数在菜单函数里把功能实现。
所以你会看到部分模块代码很长,而部分模块只有一两句函数调用语句和break

#include "head.h"

void menu(BasInfo basinfo, ListConRec listconrec, ListGrade listgrade) {
	welcome();
	int functionNum;//用来选择功能
	int chooseList = 0;//用来指示对哪个链表进行操作
	int insertContinue = 1;//是否继续插
	int deleteContinue = 1;//是否继续删除,可实现多次删除和插入,方便使用
	int inputContinue = 1;
	int setContinue = 1;//是否继续设置
	int saveFile=0;
	functionNum = checkMenu();
	while (functionNum>=0 && functionNum<=9) {
		switch (functionNum) {
		case 1: 
			while (insertContinue == 1) {
				printf("请输入您要添加数据的信息表:\n<1>学生成绩信息表\t<2>消费记录信息表\t<3>取消本次添加\n");			
				chooseList = checkNum123();				
				if (chooseList == 1) {
					int insertListGradeContinue = 1;
					while (insertListGradeContinue == 1) {
						int numBeforeInsert = getLengthOfListGrade(listgrade) - 1;
						int insertway;
						printf("请选择增添数据的方式:\n(1)手动添加\t(2)文件导入\t(3)取消本次添加\n");
						insertway = checkNum123();

						if (insertway == 1) {
							printf("当前学生成绩信息表中有%d条记录\n", getLengthOfListGrade(listgrade) - 1);
							printf("请输入您要插入到学生成绩信息表中的位置(应大于0):\n");
							int insertPosition;
							insertPosition = checkInsertDeletePosition1(listgrade);
							int insertResult = insertGradeNode(listgrade, insertPosition);
							if (insertResult == 1)
								printf("添加成功!\n");
							else
								printf("\n很遗憾,暂时添加失败。您可以再次添加\n");
							afterInsertIntoListGrade(listgrade, numBeforeInsert);
						}
						else if (insertway == 2) {						
							printf("(1)查看文件导入方式使用说明\t(2)我已熟悉,无需说明\n");
							int aboutfile = checkNum();
							if (aboutfile == 1)
								aboutFileOfListGrade();
							printf("您已选择通过文件导入的方式来增添数据,请输入文件的绝对路径:\n");
							fileInsertGradeNode(listgrade);
							afterInsertIntoListGrade(listgrade, numBeforeInsert);
							printf("(1)对学生成绩表进行数据查重\t(2)不查重\n");
							int findsamenode = checkNum();
							if (findsamenode == 1)
								findSameNode1(listgrade);
						}
						else if (insertway == 3) {
							printf("你已取消本次增添\n");
							break;
						}
						printf("\n(1)继续增添学生成绩数据\t(2)退出增添学生成绩数据\n");
						insertListGradeContinue = checkNum();
					}										
				}
				else if (chooseList == 2) {
					int insertListConRecContinue = 1;
					while (insertListConRecContinue == 1) {
						int numBeforeInsert = getLengthOfListConRec(listconrec) - 1;
						int insertway;
						printf("请选择增添数据的方式:\n(1)手动添加\t(2)文件导入\t(3)取消本次添加\n");
						insertway = checkNum123();

						if (insertway == 1) {
							printf("当前消费记录信息表中有%d条数据\n", getLengthOfListConRec(listconrec) - 1);
							printf("请输入您要插入到消费记录信息表中的位置(应大于0):\n");
							int insertPosition;
							insertPosition = checkInsertDeletePosition2(listconrec);
							int insertResult = insertConRecNode(listconrec, insertPosition);
							if (insertResult == 1)
								printf("添加成功!\n");
							else
								printf("很遗憾,暂时添加失败。不用灰心,您待会还可以再次添加\n");
							afterInsertIntoListConRec(listconrec, numBeforeInsert);
						}
						else if (insertway == 2) {
							printf("(1)查看文件导入方式使用说明\t(2)我已熟悉,无需说明\n");
							int aboutfile = checkNum();
							if (aboutfile == 1)
								aboutFileOfListConRec();
							printf("您已选择通过文件导入的方式来增添数据,请输入文件的绝对路径:\n");
							fileInsertConRecNode(listconrec);
							afterInsertIntoListConRec(listconrec, numBeforeInsert);
							printf("(1)对消费记录表进行数据查重\t(2)不查重\n");
							int findsamenode = checkNum();
							if(findsamenode==1)
								findSameNode2(listconrec);
						}
						else if (insertway == 3) {
							printf("你已取消本次增添\n");
							break;
						}
						printf("\n(1)继续增添消费记录数据\t(2)退出增添消费记录数据\n");
						insertListConRecContinue = checkNum();
						
					}					
				}
				else 
					printf("你已取消本次增添!\n\n");	
				printf("<1>继续增添 <2>退出增添\n");
				insertContinue = checkNum();
			}
			insertContinue = 1;
			break;	

		case 2: 
			alter(&basinfo, listgrade, listconrec);
			break;

		case 3: 
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
			printf("您将进行删除操作,为保证数据安全,请先输入密码\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
			char password[15];
			checkCharsLength(password, sizeof(password));
			if (comparePassword(basinfo, password)) {
				while (deleteContinue == 1) {
					printf("请输入您要删除数据的信息表:\n<1>学生成绩信息表\t<2>消费记录信息表\t<3>取消本次删除\n");
					chooseList = checkNum123();
					if (chooseList == 1) {
						int deleteListGradeContinue = 1;
						while (deleteListGradeContinue == 1) {
							int deleteway;
							printf("(1)输入删除位置来删除\t(2)查找科目名及学期来删除\t(3)取消本次删除。\n");
							deleteway = checkNum123();
							int numBeforeDelete = getLengthOfListGrade(listgrade) - 1;
							if (deleteway == 1) {
								printf("当前学生成绩信息表中有%d条记录\n", numBeforeDelete);
								if (numBeforeDelete == 0) {
									printf("无数据可以删除,已退出本次删除!\n\n");
									break;
								}
								printf("请输入您要删除的数据的位置(应大于0):\n");
								int deletePosition;
								deletePosition = checkInsertDeletePosition1(listgrade);
								int assuredelete = 1;
								printf("数据的顺序可能改变,是否要先查看一下即将删除的数据\n(1)确认查看\t(2)不查看\n");
								int checkData = checkNum();
								if (checkData == 1) {
									outputNodeByPosition1(listgrade, deletePosition);
									printf("(1)确认删除\t(2)取消删除\n");
									assuredelete = checkNum();
								}
								if (assuredelete==1&&deleteGradeNode(listgrade, deletePosition))
									printf("删除成功!\n");
								afterDeletefromListGrade(listgrade, numBeforeDelete);

							}
							else if (deleteway == 2) {
								printf("请输入科目:\n");
								char subject[25];
								checkCharsLength(subject, sizeof(subject));
								printf("\n请输入学期(格式为2022-春或2022-夏或2022-秋):\n");
								char startTime[10];
								checkCharsLength(startTime, sizeof(startTime));
								while (!checkdate2(startTime))
									checkCharsLength(startTime, sizeof(startTime));

								if (deleteBySubAndTime(listgrade, subject, startTime))
									printf("删除成功!\n");

								afterDeletefromListGrade(listgrade, numBeforeDelete);
							}
							else {
								printf("您已取消本次删除!\n\n");
								break;
							}															
							printf("(1)继续删除学生成绩表中的数据\t(2)结束本次删除\n");
							deleteListGradeContinue = checkNum();						
						}																	
					}
					else if (chooseList == 2) {
						int deleteListConRecContinue = 1;
						while (deleteListConRecContinue == 1) {
							int deleteway;
							printf("(1)输入删除位置来删除\t(2)查找LogID来删除\t(3)取消本次删除\n");
							deleteway = checkNum123();
							int numBeforeDelete = getLengthOfListConRec(listconrec) - 1;
							if (deleteway == 1) {
								printf("当前消费记录信息表中有%d条记录\n", numBeforeDelete);
								if (numBeforeDelete == 0) {
									printf("无数据可以删除,已退出本次删除!\n\n");
									break;
								}
								printf("请输入您要删除的数据的位置(应大于0):\n");
								int deletePosition;
								deletePosition = checkInsertDeletePosition2(listconrec);
								int assuredelete = 1;
								printf("数据的顺序可能改变,是否要先查看一下即将删除的数据\n(1)确认查看\t(2)不查看\n");
								int checkData = checkNum();
								if (checkData == 1) {
									outputNodeByPosition2(listconrec, deletePosition);
									printf("(1)确认删除\t(2)取消删除\n");
									assuredelete = checkNum();
								}
								if (assuredelete == 1&&deleteConRecNode(listconrec, deletePosition))
									printf("删除成功!\n");

								afterDeleteFromListConRec(listconrec, numBeforeDelete);
							}
							else if (deleteway == 2) {
								printf("请输入LogID:\n");
								int LogID;
								LogID = scanfLogID();
								if (deleteByLogID(listconrec, LogID))
									printf("删除成功!\n");

								afterDeleteFromListConRec(listconrec, numBeforeDelete);
							}
							else {
								printf("您已取消本次添加!\n");
								break;
							}															
							printf("(1)继续删除消费记录表中的数据\t(2)结束本次删除\n");
							deleteListConRecContinue = checkNum();						
						}												
					}
					else 
						printf("您选择取消删除数据!\n\n");
					printf("<1>继续删除\t<2>结束删除\n");
					deleteContinue = checkNum();
				}
				deleteContinue = 1;
			}
			else
				printf("已退出删除功能\n\n");
			break;

		case 4:
			seek(listgrade, listconrec);
			break;

		case 5:
			sort(listgrade, listconrec);
			break;

		case 6:
			while (inputContinue == 1) {
				int inputType;
				printf("<1>个人基本信息表\t<2>学生成绩表\t<3>消费记录表\t<4>取消本次输出\n");
				inputType = checkNum1234();
				switch (inputType) {
				case 1:
					print1(basinfo);
					break;
				case 2:
					print2(listgrade);
					break;
				case 3:
					print3(listconrec);
					break;
				default:
					printf("您已选择本次取消输出\n");
				}
				printf("\n<1>继续输出数据\t<2>退出输出数据\n");
				inputContinue = checkNum();
			}
			inputContinue = 1;
			break;

		case 7:
			save(basinfo, listgrade, listconrec);
			saveFile = 1;
			break;

		case 8:			
			while (setContinue == 1) {
				int chooseset;
				printf("<1>设置字体颜色\t<2>设置欢迎界面随机变色\n");
				chooseset = checkNum();
				int setTextColorContinue = 1;
				if (chooseset == 1) {
					while (setTextColorContinue == 1) {
						setTextColor();
						printf("效果字体!\n");
						printf("(1)重新设置字体\t   (2)保存设置\t(3)恢复默认字体\n");
						setTextColorContinue = checkNum123();
						if (setTextColorContinue == 3) {
							SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
							break;
						}
					}					
				}
				else if (chooseset == 2) {
					setWelcomeColor();
				}
				printf("<1>继续设置\t<2>退出设置\n");
				setContinue = checkNum123();
			}
			setContinue = 1;
			break;

		case 9:
			check(listgrade, listconrec);
			break;

		case 0:
			if (!saveFile) {
				printf("您尚未保存文件!如需保存请输入数字1,否则输入2\n");
				printf("<1>保存 \t <2>不保存\n");
				int assuresave;
				assuresave = checkNum();
				if (assuresave == 1)
					save(basinfo, listgrade, listconrec);
				else if (assuresave == 2)
					printf("您已选择取消保存!\n");
			}		
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
			printf("您确定要退出系统吗\n");
			printf("<1>确定退出\t<2>取消退出\n");
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);			
			int assureExit;
			assureExit = checkNum();
			if (assureExit == 1) {
				printf("\n感谢使用,再见!\n");
				system("pause");
				destroy2(listgrade);
				destroy3(listconrec);
				return;
			}
			else if (assureExit == 2) 
				printf("您已取消退出,欢迎继续使用!\n\n");				
			break;

		default:
			printf("输入错误!请输入0-9的数字\n\n");
		}

		welcome();
		functionNum = checkMenu();
	}
}

8.welcome.cpp

弹出菜单功能选项的函数。这里叫welcome感觉不是很好

#include "head.h"

void welcome() {
    if (welcomeColor == 1) {
        srand((unsigned)time(NULL));
        int color = (rand() % 14) + 2;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
    }
    
    printf("\n");
    printf("\t\t■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
    printf("\t\t■       \t                                                ■      \n");
    printf("\t\t■       \t         个人信息管理系统                       ■      \n");
    printf("\t\t■       \t                                                ■      \n");
    printf("\t\t■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
    printf("\t\t■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
    printf("\t\t■       \t                                                ■      \n");
    printf("\t\t■         【1】增添数据         【2】修改数据                  ■\n");
    printf("\t\t■         【3】删除数据         【4】查询数据                  ■\n");
    printf("\t\t■         【5】数据排序         【6】输出数据                  ■\n");
    printf("\t\t■         【7】保存数据         【8】个性设置                  ■\n");
    printf("\t\t■         【9】检查数据         【0】退出系统                  ■\n");
    printf("\t\t■       \t                                                ■      \n");
    printf("\t\t■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n");
    printf("\t\t\t提示:左边数字对应功能选择,请选0-9\n");
    printf("\t    ( ̄︶ ̄)↗   \n");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
}

9.insert.cpp

实现增添数据所需的函数

#include "head.h"

int insertGradeNode(struct grade* head,int position) {
	
	ListGrade p = head,q;
	q = (ListGrade)malloc(sizeof(GradeNode));
	for (int i = 1; i<position; i++) 
		p = p->next;

	printf("\n请输入科目:\n");
	char subject[15];
	checkCharsLength(subject, sizeof(subject));

	printf("\n请输入学期");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(格式为2022-春或2022-夏或2022-秋):\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	char startTime[10];
	checkCharsLength(startTime, sizeof(startTime));
	while (!checkdate2(startTime)) 
		checkCharsLength(startTime, sizeof(startTime));
	
	//开始查重:
	if (!checkUniqueOfListGrade(head,subject,startTime)) 
		return 0;
	
	//确认不重复才赋值:
	strcpy(q->subject, subject);
	strcpy(q->startTime, startTime);

	printf("\n请输入该学科的学分:\n");
	double credit = scanfDouble();
	q->credit = credit;

	printf("\n请输入平时成绩:\n");
	double usual = scanfDouble();
	q->usual = usual;

	printf("\n请输入期中成绩:\n");
	double midterm = scanfDouble();
	q->midterm = midterm;

	printf("\n请输入期末成绩:\n");
	double exam = scanfDouble();
	q->exam = exam;

	printf("\n请输入最终成绩(即加权成绩):\n");
	double final = scanfDouble();
	q->final = final;

	printf("\n该学科是否为重修?");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(输入是或否)\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	char chongxiu[4];
	checkCharsLength(chongxiu, sizeof(chongxiu));
	//q->chongxiu = chongxiu;
	while (!checkYN(chongxiu)) 
		checkCharsLength(chongxiu, sizeof(chongxiu));

	strcpy(q->chongxiu, chongxiu);

	q->next = p->next;
	p->next = q;
	lengthOfListGrade++;
	return 1;
}

int insertConRecNode( ConRecNode* head, int position) {

	ListConRec p = head, q;
	q = (ListConRec)malloc(sizeof(ConRecNode));

	for (int i = 1; i < position; i++)
		p = p->next;

	printf("\n请输入该条消费记录的专属ID");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(纯数字)\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	int LogID=scanfLogID();
	
	if (!checkUniqueOfListConRec(head, LogID)) 
		return 0;
	
	q->LogID = LogID;

	printf("\n请输入消费时间");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(格式为××××-××-××,如2022-01-01)\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	char contime[12];
	checkCharsLength(contime, sizeof(contime));
	while (!checkdate(contime)) 
		checkCharsLength(contime, sizeof(contime));	
	strcpy(q->contime, contime);

	printf("\n请输入消费类型\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("可选择:\n转账;餐饮,购物,交通,服务,医疗,教育,其他\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	char connote[8];
	checkCharsLength(connote, sizeof(connote));
	while (!checkconnote(connote)) 
		checkCharsLength(connote, sizeof(connote));
	strcpy(q->connote, connote);

	printf("\n请输入消费金额:\n");
	double charge = scanfDouble();
	q->charge = charge;

	q->next = p->next;
	p->next = q;
	lengthOfListConRec++;
	return 1;
}

struct grade* fileInsertGradeNode(struct grade* head) {         
	ListGrade gradenode, p = head;

	while (p->next) {
		p = p->next;
	}
	char filename[50];
	FILE* fp;
	printf("请输入文件的绝对路径:\n");
	checkCharsLength(filename, sizeof(filename));
	while (!(fp = fopen(filename, "r"))) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("文件找不到,可能路径名有误,请检查文件路径后重新输入!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		printf("\n(1)继续通过文件导入数据\t(2)取消文件导入数据\n");
		int insertcontinue = checkNum();
		if (insertcontinue == 2)
			return head;
		checkCharsLength(filename, sizeof(filename));
	}

	while (1) {
		gradenode = (ListGrade)malloc(sizeof(GradeNode));
		if (EOF == fscanf(fp, "%s %s %lf %lf %lf %lf %lf %s", gradenode->subject, gradenode->startTime, &gradenode->credit, &gradenode->usual, &gradenode->midterm, &gradenode->exam, &gradenode->final, gradenode->chongxiu))
			break;
		p->next = gradenode;
		gradenode->next = NULL;
		p = gradenode;
	}
	lengthOfListGrade = getLengthOfListGrade(head);
	fclose(fp);
	printf("导入成功!\n");
	return head;
}													  
ConRecNode* fileInsertConRecNode( ConRecNode* head) {		  
	ListConRec conrecnode, p = head;

	while (p->next) {
		p = p->next;
	}
	char filename[50];
	FILE* fp;
	printf("请输入文件的绝对路径:\n");
	checkCharsLength(filename, sizeof(filename));
	while (!(fp = fopen(filename, "r"))) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("文件找不到,可能路径名有误,请检查文件路径后重新输入!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		printf("\n(1)继续通过文件导入数据\t(2)取消文件导入数据\n");
		int insertcontinue = checkNum();
		if (insertcontinue == 2)
			return head;
		checkCharsLength(filename, sizeof(filename));
	}
	while (1) {
		conrecnode = (ListConRec)malloc(sizeof(ConRecNode));
		if (EOF == fscanf(fp, "%d%s%s%lf", &conrecnode->LogID, conrecnode->contime, conrecnode->connote, &conrecnode->charge))
			break;
		p->next = conrecnode;
		conrecnode->next = NULL;
		p = conrecnode;
	}
	fclose(fp);
	printf("导入成功!\n");
	lengthOfListConRec = getLengthOfListConRec(head);
	return head;
}

10.alter.cpp

修改数据的函数
感觉把部分带alter名字的函数改成set会好点,模仿java类成员的set方法

#include "head.h"


int alterName(BasInfo* basinfo) {
	char name[30];
	printf("请重新输入姓名: ");
	checkCharsLength(name, sizeof(name));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(basinfo->name, name);
	else {
		printf("您已取消修改姓名\n");
		return 0;
	}
	return 1;
}

int alterStuNum(BasInfo *basinfo) {
	char stu_num[15];
	printf("请重新输入学号: ");
	checkCharsLength(stu_num, sizeof(stu_num));
	while(!checkstudent_number(stu_num))
		checkCharsLength(stu_num, sizeof(stu_num));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(basinfo->student_number, stu_num);
	else {
		printf("您已取消修改学号\n");
		return 0;
	}
	return 1;
}

int alterGender(BasInfo* basinfo) {
	char gender[5];
	printf("请重新输入性别: ");
	checkCharsLength(gender, sizeof(gender));
	while (!checkGender(gender))
		checkCharsLength(gender, sizeof(gender));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1) 		
		strcpy(basinfo->gender, gender);		
	else {
		printf("您已取消修改性别\n");
		return 0;
	}
	return 1;
}

int alterAcademy(BasInfo* basinfo) {
	char academy[30];
	printf("请重新输入学院: ");
	checkCharsLength(academy, sizeof(academy));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(basinfo->academy, academy);
	else {
		printf("您已取消修改学院\n");
		return 0;
	}
	return 1;
}

int alterMajor(BasInfo* basinfo) {
	char major[20];
	printf("请重新输入专业: ");
	checkCharsLength(major, sizeof(major));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(basinfo->major, major);
	else {
		printf("您已取消修改专业\n");
		return 0;
	}
	return 1;
}

int alterClass_(BasInfo* basinfo) {
	char class_[25];
	printf("请重新输入班级: ");
	checkCharsLength(class_, sizeof(class_));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(basinfo->class_, class_);
	else {
		printf("您已取消修改班级\n");
		return 0;
	}
	return 1;
}

int alterBirthday(BasInfo* basinfo) {
	char birthday[11];
	printf("请重新输入生日: ");
	checkCharsLength(birthday, sizeof(birthday));
	while (!checkdate(birthday))
		checkCharsLength(birthday, sizeof(birthday));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1) 		
		strcpy(basinfo->birthday, birthday);	
	else {
		printf("您已取消修改生日\n");
		return 0;
	}
	return 1;
}

void alterHobby(BasInfo* basinfo) {
	printf("1)添加爱好\t2)重新输入爱好\n");
	int altertype = checkNum();
	for (int i = 0; i < basinfo->hobby_length; i++) 
		printf("您的爱好: %s  ", basinfo->hobby[i]);
	if (altertype == 1) {
		printf("\n当前已有%d个爱好,还可以输入%d个", basinfo->hobby_length, 10 - basinfo->hobby_length);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("(输入-1为结束输入)\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		for (int i = basinfo->hobby_length; i < 10; i++) {
			char hobby[20];
			checkCharsLength(hobby, sizeof(hobby));
			if (!checkEnd(hobby, 1))
				strcpy(basinfo->hobby[i], hobby);
			else
				break;
			if (i == 9) {
				printf("爱好数量达到上限!\n");
				break;
			}
		}
	}
	else if (altertype == 2) {
		printf("请重新输入您的爱好(最多输入十个!,输入-1视为结束输入!):\n");
		char hobby_1[20];
		basinfo->hobby_length = 0;
		for (int i = 0; i < 10; i++) {
			scanf_s("%s", hobby_1, 20);
			bool end = checkEnd(hobby_1, i);
			if (end)
				break;
			else
				strcpy(basinfo->hobby[i], hobby_1);
			basinfo->hobby_length++;
		}
	}
}

int alterPhone(BasInfo* basinfo) {
	char phone[12];
	printf("请重新输入电话号码: ");
	checkCharsLength(phone, sizeof(phone));
	while (!checkPhone(phone))
		checkCharsLength(phone, sizeof(phone));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1) 	
		strcpy(basinfo->phone, phone);
	else {
		printf("您已取消修改电话号码\n");
		return 0;
	}
	return 1;
}

int alterAdress(BasInfo* basinfo) {
	char address[20];
	printf("请重新输入籍贯: ");
	checkCharsLength(address, sizeof(address));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(basinfo->address, address);
	else {
		printf("您已取消修改籍贯\n");
		return 0;
	}
	return 1;
}

void alterpartsInBasinfo(BasInfo* basinfo) {
	/*让用户输入要修改的数据的编号,然后用一个数组来接收这些编号;根据编号来调用不同的修改函数*/
	printf("请输入要修改的内容");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(可多选,输入0为结束输入!)\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	printf("(1)姓名\t(2)学号\t(3)性别\t(4)学院\t     (5)专业\n(6)班级\t(7)生日\t(8)爱好\t(9)电话号码  (10)籍贯\n");
	int alternum[10];
	int altertype;
	for (int i = 0; i < 10; i++) {
		int flag = 1;
		altertype = checkAllNum(10);
		if (altertype==0)
			break;
		for (int j = 0; j < 10 && alternum[j] != 0; j++) {
			if (altertype == alternum[j]) {
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
				printf("请勿多次输入同一个数字编号!\n");
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
				flag = 0;
			}				
		}
		if (flag)
			alternum[i] = altertype;
	}
	for (int i = 0; i < 10 && alternum[i] != 0; i++) {
		switch (alternum[i]) {
		case 1:
			alterName(basinfo);
			break;
		case 2:
			alterStuNum(basinfo);
			break;
		case 3:
			alterGender(basinfo);
			break;
		case 4:
			alterAcademy(basinfo);
			break;
		case 5:
			alterMajor(basinfo);
			break;
		case 6:
			alterClass_(basinfo);
			break;
		case 7:
			alterBirthday(basinfo);
			break;
		case 8:
			alterHobby(basinfo);
			break;
		case 9:
			alterPhone(basinfo);
			break;
		case 10:
			alterAdress(basinfo);
			break;
		}
	}
}

void alterAllInBasinfo(BasInfo* basinfo) {
	alterName(basinfo);
	alterStuNum(basinfo);
	alterGender(basinfo);
	alterAcademy(basinfo);
	alterMajor(basinfo);
	alterClass_(basinfo);
	alterBirthday(basinfo);
	alterHobby(basinfo);
	alterPhone(basinfo);
	alterAdress(basinfo);
}


int alterSubject(ListGrade p) {
	char subject[25];
	printf("请重新输入学科名\n");
	checkCharsLength(subject, sizeof(subject));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(p->subject, subject);
	else {
		printf("您已取消修改学科\n");
		return 0;
	}		
	return 1;
}

int alterStartTime(ListGrade p) {
	char startTime[10];
	printf("请重新输入学期\n");
	checkCharsLength(startTime, sizeof(startTime));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(p->startTime, startTime);
	else {
		printf("您已取消修改学期\n");
		return 0;
	}
	return 1;
}

int alterCredit(ListGrade p) {
	printf("请重新输入学分\n");
	double credit=scanfDouble();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->credit = credit;
	else {
		printf("您已取消修改学分\n");
		return 0;
	}
	return 1;
}

int alterUsual(ListGrade p) {
	printf("请重新输入平时成绩\n");
	double usual = scanfDouble();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->usual = usual;
	else {
		printf("您已取消修改平时成绩\n");
		return 0;
	}
	return 1;
}

int alterMidterm(ListGrade p) {
	printf("请重新输入期中成绩\n");
	double midterm = scanfDouble();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->midterm = midterm;
	else {
		printf("您已取消修改期中成绩\n");
		return 0;
	}
	return 1;
}

int alterExam(ListGrade p) {
	printf("请重新输入期末\n");
	double exam = scanfDouble();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->exam = exam;
	else {
		printf("您已取消修改期末成绩\n");
		return 0;
	}
	return 1;
}

int alterFinal(ListGrade p) {
	printf("请重新输入加权成绩\n");
	double fianl = scanfDouble();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->final = fianl;
	else {
		printf("您已取消修改加权成绩\n");
		return 0;
	}
	return 1;
}

int alterChongxiu(ListGrade p) {
	char chongxiu[4];
	printf("请重新输入是或否\n");
	checkCharsLength(chongxiu, sizeof(chongxiu));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(p->chongxiu, chongxiu);
	else {
		printf("您已取消修改重修情况\n");
		return 0;
	}
	return 1;
}

void alterpartsInListGrade(ListGrade head) {
	printf("请输入您要修改的数据的位置\n");
	int position = checkInsertDeletePosition1(head);
	printf("这是您即将要修改的数据:\n");
	outputNodeByPosition1(head,position);
	ListGrade p = head->next;
	for (int i = 1; i < position; i++)
		p = p->next;
	printf("请输入要修改的内容");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(可多选,输入0为结束输入):\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	printf("(1)学科         (2)学期         (3)学分\n(4)平时成绩\t(5)期中成绩\t(6)期末成绩\n(7)加权成绩\t(8)是否重修\n");
	int alternum[8] = { 0 };
	int altertype;
	
	for (int i = 0; i < 8; i++) {
		int flag = 1;
		altertype = checkAllNum(8);
		if (altertype == 0)
			break;
		for (int j = 0; j < 8 && alternum[j] != 0; j++) {
			if (altertype == alternum[i]) {
				printf("请勿多次输入同一个数字编号!\n");
				flag = 0;
			}
		}
		if (flag)
			alternum[i] = altertype;
	}
	for (int i = 0; i < 10 && alternum[i] != 0; i++) {
		switch (alternum[i]){
		case 1:
			alterSubject(p);
			break;
		case 2:
			alterStartTime(p);
			break;
		case 3:
			alterCredit(p);
			break;
		case 4:
			alterUsual(p);
			break;
		case 5:
			alterMidterm(p);
			break;
		case 6:
			alterExam(p);
			break;
		case 7:
			alterFinal(p);
			break;
		case 8:
			alterChongxiu(p);
			break;
		default:
			printf("未知错误,修改失败!\n");
			break;
		}
	}
}

void alterAllInListGrade(ListGrade head) {
	printf("请输入您要修改的数据的位置\n");
	int position = checkInsertDeletePosition1(head);
	printf("这是您即将要修改的数据:\n");
	outputNodeByPosition1(head, position);
	ListGrade p = head->next;
	for (int i = 1; i < position; i++)
		p = p->next;
	alterSubject(p);
	alterStartTime(p);
	alterCredit(p);
	alterUsual(p);
	alterMidterm(p);
	alterExam(p);
	alterFinal(p);
	alterChongxiu(p);
}

int alterLogID(ListConRec p) {
	printf("请重新输入LogID\n");
	int LogID = scanfLogID();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->LogID = LogID;
	else {
		printf("您已取消修改LogID\n");
		return 0;
	}
	return 1;
}

int alterContime(ListConRec p) {
	char contime[11];
	printf("请重新输入消费时间\n");
	checkCharsLength(contime, sizeof(contime));
	while(!checkdate(contime))
		checkCharsLength(contime, sizeof(contime));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(p->contime, contime);
	else {
		printf("您已取消修改消费时间\n");
		return 0;
	}
	return 1;
}

int alterConnote(ListConRec p) {
	char connote[8];
	printf("请重新输入消费类型\n");
	checkCharsLength(connote, sizeof(connote));
	while(!checkconnote(connote))
		checkCharsLength(connote, sizeof(connote));
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		strcpy(p->connote, connote);
	else {
		printf("您已取消修改消费类型\n");
		return 0;
	}
	return 1;
}

int alterCharge(ListConRec p) {
	printf("请重新输入消费金额\n");
	double charge = scanfDouble();
	printf("1)确认修改\t2)取消修改\n");
	int assurealter = checkNum();
	if (assurealter == 1)
		p->charge = charge;
	else {
		printf("您已取消修改消费金额\n");
		return 0;
	}
	return 1;
}

void alterpartsInListConRec(ListConRec head) {
	printf("请输入您要修改的数据的位置\n");
	int position = checkInsertDeletePosition2(head);
	printf("这是您即将要修改的数据:\n");
	outputNodeByPosition2(head, position);
	ListConRec p = head->next;
	for (int i = 1; i < position; i++)
		p = p->next;
	printf("请输入要修改的内容");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("(可多选,输入0为结束输入):\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	printf("(1)LogID\t(2)消费时间\t(3)消费类型\t(4)消费金额\n");
	int alternum[4]={ 0 };
	int altertype;
	for (int i = 0; i < 4; i++) {
		int flag = 1;
		altertype = checkAllNum(4);
		if (altertype == 0)
			break;
		for (int j = 0; j < 4 && alternum[j] != 0; j++) {
			if (altertype == alternum[i]) {
				printf("请勿多次输入同一个数字编号!\n");
				flag = 0;
			}
		}
		if (flag)
			alternum[i] = altertype;
	}
	for (int i = 0; i < 4 && alternum[i] != 0; i++) {
		switch (alternum[i]){
		case 1:
			alterLogID(p);
			break;
		case 2:
			alterContime(p);
			break;
		case 3:
			alterConnote(p);
			break;
		case 4:
			alterCharge(p);
			break;
		default:
			printf("未知错误,修改失败!\n");
			break;
		}
	}
}

void alterAllInListConRec(ListConRec head) {
	printf("请输入您要修改的数据的位置\n");
	int position = checkInsertDeletePosition2(head);
	printf("这是您即将要修改的数据:\n");
	outputNodeByPosition2(head, position);
	ListConRec p = head->next;
	for (int i = 1; i < position; i++)
		p = p->next;
	alterLogID(p);
	alterContime(p);
	alterConnote(p);
	alterCharge(p);
}

void alter(BasInfo *basinfo, ListGrade listgrade, ListConRec listconrec) {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("您将进行修改操作,为保证数据安全,请先输入密码\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
	char password[15];
	checkCharsLength(password, sizeof(password));
	if (comparePassword(*basinfo, password)) {
		int altercontinue = 1;
		while (altercontinue == 1) {
			printf("<1>修改个人信息表\t<2>修改学生成绩表\t<3>修改消费记录表\t<4>修改密码\t<5>取消本次修改\n");
			int alterType = checkAllNum(5);
			if (alterType == 1) {
				int alterBasinfoContinue = 1;
				while (alterBasinfoContinue == 1) {
					printf("(1)修改部分数据\t(2)修改全部数据\t(3)退出修改个人信息表\n");
					int alteraccount = checkNum123();
					if (alteraccount == 1) {
						alterpartsInBasinfo(basinfo);
					}
					else if (alteraccount == 2) {
						alterAllInBasinfo(basinfo);
					}
					else if (alteraccount == 3) {
						printf("您已退出修改个人信息表\n");
						break;
					}									
						printf("(1)继续修改个人信息表\t(2)退出修改个人信息表\n");
						alterBasinfoContinue = checkNum();				
				}
			}
			else if (alterType == 2) {
				int alterListGradeContinue = 1;
				if (!listgrade->next) {
					printf("当前无消费记录数据!\n\n");
					alterListGradeContinue = 0;
				}
				while (alterListGradeContinue == 1) {
					printf("(1)修改部分数据\t(2)修改全部数据\t(3)退出修改学生成绩表\n");
					int alteraccount = checkNum123();
					if (alteraccount == 1)
						alterpartsInListGrade(listgrade);
					else if (alteraccount == 2)
						alterAllInListGrade(listgrade);
					else if (alteraccount == 3) {
						printf("您已退出修改学生成绩表\n");
						break;
					}
					printf("(1)继续修改学生成绩表\t(2)退出修改学生成绩表\n");
					alterListGradeContinue = checkNum();
				}
			}
			else if (alterType == 3) {
				int alterListConRecContinue = 1;
				if (!listconrec->next) {
					printf("当前无消费记录数据!\n\n");
					alterListConRecContinue = 0;
				}
				while (alterListConRecContinue == 1) {
					printf("(1)修改部分数据\t(2)修改全部数据\t(3)退出修改消费记录表\n");
					int alteraccount = checkNum123();
					if (alteraccount == 1)
						alterpartsInListConRec(listconrec);
					else if (alteraccount == 2)
						alterAllInListConRec(listconrec);
					else if (alteraccount == 3) {
						printf("您已退出修改消费记录表\n");
						break;
					}
					printf("(1)继续修改消费记录表\t(2)退出修改消费记录表\n");
					alterListConRecContinue = checkNum();
				}
			}
			else if (alterType == 4) {
				char password[15];
				printf("请输入原密码\n");
				checkCharsLength(password, sizeof(password));
				int flag = 0;
				for (int i = 1; i < 3; i++) {
					if (comparePassword(*basinfo, password)) {
						flag = 1;
						break;
					}
					else {
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
						printf("还剩%d次输入机会\n", 3 - i);
						SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);						
						checkCharsLength(password, sizeof(password));
					}
				}
				if (flag) {
					int inputpassword = 1;
					while (inputpassword == 1) {
						printf("请选择输入密码的方式:\n<1>普通输入\t<2>隐藏输入\n");
						int inputway = checkNum();
						printf("请设置您的登录密码(最长15位,必须包含大写字母、小写字母、阿拉伯数字)\n");

						if (inputway == 2) {
							setColor(2, 2);
							checkCharsLength((*basinfo).password, sizeof((*basinfo).password));
							SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
							while (!checkPassword((*basinfo).password)) {
								setColor(2, 2);
								checkCharsLength((*basinfo).password, sizeof((*basinfo).password));
								SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
							}
						}
						else if (inputway == 1) {
							checkCharsLength((*basinfo).password, sizeof((*basinfo).password));
							while (!checkPassword((*basinfo).password))
								checkCharsLength((*basinfo).password, sizeof((*basinfo).password));

						}
						printf("\n<1>重新设置密码\t<2>保存密码\n");
						inputpassword = checkNum();
					}
				}
			}
			else
				printf("您已取消本次修改\n");
			printf("(1)继续修改\t(2)退出修改\n");
			altercontinue = checkNum();
		}
	}
	else
		printf("已退出修改功能\n\n");	
}

11.delete.cpp

#include "head.h"

int deleteGradeNode(struct grade* head,int position) {
	if (position > getLengthOfListGrade(head)) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("您输入的删除位置大于信息表的数据数量,无法删除!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		return 0;
	}
	else if (position <= 0) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("删除位置不能小于0!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
		return 0;
	}
	ListGrade p = head, q;
	for (int i = 1; i<position; i++)
		p = p->next;
	q = p->next;
	p->next = q->next;
	free(q);
	lengthOfListGrade--;
	return 1;
}

int deleteConRecNode( ConRecNode* head , int position) {
	if (position > getLengthOfListConRec(head)) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("您输入的删除位置大于信息表的数据数量,无法删除!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		return 0;
	}
	else if (position <= 0) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("删除位置不能小于0!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);	
		return 0;
	}
	ListConRec p = head,q;
	for (int i = 1; i < position; i++)
		p = p->next;
	q = p->next;
	p->next = q->next;
	free(q);
	lengthOfListConRec--;
	return 1;
}

int deleteBySubAndTime(ListGrade head, char subject[], char startTime[]) {
	ListGrade p = head, q;
	int deleteposition = 1;
	while (p->next) {
		if (strcmp(p->next->subject, subject) == 0 && strcmp(p->next->startTime, startTime) == 0)
			break;
		deleteposition++;
		p = p->next;
	}
	if (deleteposition == getLengthOfListGrade(head)) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("您输入的学期下对应的学科不存在!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);		
		return 0;
	}
	q = p->next;
	p->next = q->next;
	free(q);
	lengthOfListGrade--;
	return 1;
}

int deleteByLogID(ListConRec head, int LogID) {
	ListConRec p = head, q;
	int deleteposition = 1;
	while (p->next) {
		if (p->next->LogID == LogID)
			break;
		deleteposition++;
		p = p->next;
	}
	if (deleteposition == getLengthOfListConRec(head)) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("您LogID不存在!\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		
		return 0;
	}
	q = p->next;
	p->next = q->next;
	free(q);
	lengthOfListConRec--;
	return 1;
}

12.seek.cpp

#include "head.h"

void seek(ListGrade listgrade, ListConRec listconrec) {
	int seekcontinue = 1;
	while (seekcontinue == 1) {
		printf("<1>查询学生成绩表\t<2>查询消费记录表\t<3>退出本次查询\n");
		int seektype = checkNum123();
		if (seektype == 1) {
			int selectAgain = 1;
			if (!listgrade->next) {
				printf("当前无消费记录数据!\n\n");
				selectAgain = 0;
			}
			while (selectAgain == 1) {
				printf("\n(1)按学科查询      (2)按学期查询            (3)按分数查询    (4)按学科和学期查询\n(5)查询数据数量    (6)查询指定位置的数据    (0)取消本次查询\n");
				int selecttype = checkAllNum(6);
				switch (selecttype) {
				case 1:
					printf("1)查询单门学科\t2)查询重修学科\n");
					int subtype;
					subtype = checkNum();
					if (subtype == 1) {
						selectBysubject(listgrade);
					}
					else if (subtype == 2)
						selectchongxiu(listgrade);
					break;
				case 2:
					
					selectByStartTime(listgrade);
					break;
				case 3:
					selectGrade(listgrade);
					break;
				case 4:
					selectBySubAndTime(listgrade);
					break;
				case 5:
					printf("当前学生成绩表中有%d条数据\n", lengthOfListGrade);
					break;
				case 6:
					int position;
					printf("请输入数据的位置:\n");
					position = checkInsertDeletePosition1(listgrade);
					outputNodeByPosition1(listgrade, position);
					break;
				case 0:
					printf("您已取消本次查询\n");
					break;
				}
				printf("(1)继续查询学生成绩表\t(2)退出该查询\n");
				selectAgain = checkNum();
			}

		}
		else if (seektype == 2) {
			int selectAgain = 1;
			if (!listconrec->next) {
				printf("当前无消费记录数据!\n\n");
				selectAgain = 0;
			}			
			while (selectAgain == 1) {
				printf("\n(1)按LogID查询       (2)按消费金额查询    (3)按消费时间查询\n(4)按消费类型查询    (5)按数据位置查询    (6)查询某段时间的数据\n(7)查询数据数量      (8)查询消费总额      (9)查询各数据极值\n(0)取消本次查询\n");
				int selecttype = checkAllNum(9);
				switch (selecttype) {
				case 1:
					selectByLogID(listconrec);
					break;
				case 2:
					selectCharge(listconrec);
					break;
				case 3:
					selectByConTime(listconrec);
					break;
				case 4:
					selectByConnote(listconrec);
					break;
				case 5:
					int position;
					printf("请输入要查询的数据的位置:\n");
					position = checkInsertDeletePosition2(listconrec);
					outputNodeByPosition2(listconrec, position);
					break;
				case 6:
					selectPeriodData(listconrec);
					break;
				case 7:
					printf("当前消费记录表有%d条数据\n", lengthOfListConRec);
					break;
				case 8:
					selectTotalCharge(listconrec);
					break;
				case 9:
					selectExtremum(listconrec);
					break;
				case 0:
					printf("您已取消本次查询!\n");
					break;
				}
				printf("(1)继续查询消费记录表\t(2)退出该查询\n");
				selectAgain = checkNum();
			}
		}
		else
			printf("您已取消本次查询!\n");
		printf("<1>继续查询\t<2>退出查询\n");
		seekcontinue = checkNum();
	}
}

void printData1(ListGrade p) {
	printf("|%-20s|%-10s|%-7.2lf|%-10.2lf|%-10.2lf|%-10.2lf|%-10.2lf|%-6s|\n", p->subject, p->startTime, p->credit, p->usual, p->midterm, p->exam, p->final, p->chongxiu);
	printf("+--------------------+----------+-------+----------+----------+----------+----------+------+");
}

void outputNodeByPosition1(ListGrade head,int position) {
	ListGrade p = head->next;
	for (int i = 1; i < position; i++)
		p = p->next;
	outputFormHeadOfListGrade();
	printData1(p);
	printf("\n");
}

void selectBysubject(ListGrade head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListGrade p = head->next;
		int printFormHead = 1;
		char subject[25];
		printf("请输入学科:\n");
		checkCharsLength(subject, sizeof(subject));
		while (p) {
			if (strcmp(p->subject, subject) == 0) {
				if (printFormHead == 1)
					outputFormHeadOfListGrade();
				printData1(p);
				printFormHead++;
				printf(" %d\n", position);
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无相关学科的数据!\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按学科查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}
	
}

void selectchongxiu(ListGrade head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListGrade p = head->next;
		int printFormHead = 1;
		while (p) {
			if (strcmp(p->chongxiu, "是")==0) {
				if (printFormHead == 1)
					outputFormHeadOfListGrade();
				printData1(p);
				printf(" %d\n", position);
				printFormHead++;
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无重修科目\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续查询重修科目\t(2)退出该查询\n");
		selectAgain = checkNum();
	}
	
}

void selectByStartTime(ListGrade head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListGrade p = head->next;
		int printFormHead = 1;
		double GPA = 0;
		double totalCredit = 0;//全部学分
		double getCredit = 0;//已经获得的学分
		double getGPA = 0;//全部绩点总和
		char startTime[10];
		printf("请输入学期:\n");
		checkCharsLength(startTime, sizeof(startTime));
		while (!checkdate2(startTime))
			checkCharsLength(startTime, sizeof(startTime));
		while (p) {
			if (strcmp(p->startTime, startTime) == 0) {
				if (printFormHead == 1)
					outputFormHeadOfListGrade();
				printData1(p);
				printf(" %d\n", position);
				printFormHead++;
				totalCredit += p->credit;
				//是不是重修问题不大,关键在于最终成绩是否高于60,高于才获得学分并加入计算!
				if ((p->final) > 60) {
					getCredit += p->credit;
					getGPA += (p->credit) * (((p->final) - 50) / 10);
				}
			}
			position++;
			p = p->next;
		}

		if (printFormHead == 1)
			printf("无当前输入学期的相关数据\n");
		else {
			printf("该学期已修学分:%.2lf\n获得学分:%.2lf\n学分绩点:%.2lf\n\n", totalCredit, getCredit, getGPA / getCredit);
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		}
			

		printf("(1)继续按学期查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}	
}

void selectGrade(ListGrade head) {
	ListGrade p ;
	int printFormHead;
	int selectAgain = 1;
	while (selectAgain == 1) {
		p = head->next;
		int position = 1;
		printFormHead = 1;
		printf("(1)按平时成绩查询\t(2)按期中成绩查询\t(3)按期末成绩查询\t(4)按加权成绩查询\n");
		int selectType = checkNum1234();
		double grade;
		printf("请输入分数:\n");
		grade = scanfDouble();
		int selectway;
		printf("请输入查询类型:\n1)查询大于输入成绩的数据\t2)查询等于输入成绩的数据\t3)查询小于输入成绩的数据\n");
		selectway = checkNum123();
		while (p) {
			if (selectway == 1) {
				if ((selectType == 1 && p->usual > grade)||(selectType == 2 && p->midterm > grade)||(selectType == 3 && p->exam > grade)||(selectType == 4 && p->final > grade) ){
					if (printFormHead == 1)
						outputFormHeadOfListGrade();
					printData1(p);
					printf(" %d\n", position);
					printFormHead++;
				}
			}
			else if (selectway == 2) {
				if ((selectType == 1 && p->usual == grade) || (selectType == 2 && p->midterm == grade) || (selectType == 3 && p->exam == grade) || (selectType == 4 && p->final == grade)) {
					if (printFormHead == 1)
						outputFormHeadOfListGrade();
					printData1(p);
					printf(" %d\n", position);
					printFormHead++;
				}
			}
			else {
				if ((selectType == 1 && p->usual < grade) || (selectType == 2 && p->midterm < grade) || (selectType == 3 && p->exam < grade) || (selectType == 4 && p->final < grade)) {
					if (printFormHead == 1)
						outputFormHeadOfListGrade();
					printData1(p);
					printf(" %d\n", position);
					printFormHead++;
				}
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无相关数据\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按成绩查询\t(2)退出按成绩查询\n");
		selectAgain = checkNum();
	}
}

void selectBySubAndTime(ListGrade head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		ListGrade p = head->next;
		int position = 1;
		int printFormHead = 1;
		printf("请输入科目:\n");
		char subject[25];
		checkCharsLength(subject, sizeof(subject));
		printf("\n请输入学期(格式为2022-春或2022-夏或2022-秋):\n");
		char startTime[10];
		checkCharsLength(startTime, sizeof(startTime));
		while (!checkdate2(startTime))
			checkCharsLength(startTime, sizeof(startTime));
		while (p) {
			if (strcmp(p->startTime, startTime) == 0 && strcmp(p->subject, subject) == 0) {
				if (printFormHead == 1)
					outputFormHeadOfListGrade();
				printData1(p);
				printf(" %d\n", position);
				printFormHead++;
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("要查询的数据不存在!\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按学科和学期查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}
	
}


void printData2(ListConRec p) {
	printf("|%-14d|%-12s|%-12s|%-16.2lf|\n", p->LogID, p->contime, p->connote, p->charge);
	printf("+--------------+------------+------------+----------------+");
}

void outputNodeByPosition2(ListConRec head, int position) {
	ListConRec p = head->next;
	for (int i = 1; i < position; i++)
		p = p->next;
	outputFormHeadOfListConRec();
	printf("|%-14d|%-12s|%-12s|%-16.2lf|\n", p->LogID, p->contime, p->connote, p->charge);
	printf("+--------------+------------+------------+----------------+\n");
}

void selectByConnote(ListConRec head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListConRec p = head->next;
		int printFormHead = 1;
		printf("\n请输入消费类型,可选择:\n转账;餐饮,购物,交通,服务,医疗,教育,其他\n");
		char connote[8];
		checkCharsLength(connote, sizeof(connote));
		while (!checkconnote(connote)) {
			checkCharsLength(connote, sizeof(connote));
		}
		while (p) {
			if (strcmp(p->connote, connote) == 0) {
				if (printFormHead == 1)
					outputFormHeadOfListConRec();
				printData2(p);
				printf(" %d\n", position);
				printFormHead++;
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无包含该消费类型的数据\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按消费类型查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}
	
}

void selectByConTime(ListConRec head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListConRec p = head->next;
		int printFormHead = 1;
		printf("\n请输入消费时间,格式为××××-××-××,如2022-01-01\n");
		char contime[12];
		checkCharsLength(contime, sizeof(contime));
		while (!checkdate(contime)) {
			checkCharsLength(contime, sizeof(contime));
		}
		while (p) {
			if (strcmp(p->contime, contime) == 0) {
				if (printFormHead == 1)
					outputFormHeadOfListConRec();
				printData2(p);
				printf(" %d\n", position);
				printFormHead++;
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无包含该消费时间的数据\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按消费时间查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}	
}

void selectByLogID(ListConRec head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListConRec p = head->next;
		int printFormHead = 1;
		printf("\n请输入LogID(纯数字)\n");
		int LogID;
		LogID = scanfLogID();
		printf("(1)查询大于输入LogID的数据\t(2)查询等于输入LogID的数据\t(3)查询小于输入LogID的数据\n");
		int selecttype = checkNum123();
		while (p) {
			if ((selecttype==1 && p->LogID > LogID)|| (selecttype == 2 && p->LogID == LogID)|| (selecttype == 3 && p->LogID < LogID)) {
				if (printFormHead == 1)
					outputFormHeadOfListConRec();
				printData2(p);
				printf(" %d\n", position);
				printFormHead++;
			}
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无包含该LogID的数据\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按LogID查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}
}

void selectTotalCharge(ListConRec head) {
	ListConRec p = head->next;
	double totalcharge = 0;
	while (p) {
		totalcharge += p->charge;
		p = p->next;
	}
	printf("消费总额为%.2lf\n\n", totalcharge);
}

void selectCharge(ListConRec head) {
	int selectAgain = 1;
	while (selectAgain == 1) {
		int position = 1;
		ListConRec p = head->next;
		int printFormHead = 1;
		double charge;
		printf("请输入消费金额:\n");
		charge = scanfDouble();
		printf("请输入查询类型:\n(1)查询大于输入金额的数据\t(2)查询等于输入金额的数据\t(3)查询小于输入金额的数据\n");
		int selectway = checkNum123();
		while (p) {
			if ((selectway == 1&& p->charge > charge)|| (selectway == 2 && p->charge == charge)|| (selectway == 3 && p->charge < charge)) {				
				if (printFormHead == 1)
					outputFormHeadOfListConRec();
				printData2(p);
				printf(" %d\n", position);
				printFormHead++;				
			}			
			position++;
			p = p->next;
		}
		if (printFormHead == 1)
			printf("无相关数据\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续按消费金额查询\t(2)退出该查询\n");
		selectAgain = checkNum();
	}	
}

void selectExtremum(ListConRec head) {
	ListConRec p ;
	
	int selectAgain=1;
	while (selectAgain == 1) {
		p = head->next;
		printf("(1)某段时间内的极值\t(2)全部数据的极值\n");
		int selectType = checkNum();

		printf("(1)消费金额极值\t(2)logID极值\n");
		int extrem = checkNum();

		printf("(1)最大值\t(2)最小值\n");
		int extremType = checkNum();

		double extremcharge = p->charge;
		int extremLogID = p->LogID;

		if (selectType == 1) {
			printf("请输入起始时间:\n");
			char startTime[12];
			checkCharsLength(startTime, sizeof(startTime));
			while(!checkdate(startTime))
				checkCharsLength(startTime, sizeof(startTime));
			printf("请输入结束时间:\n");
			char endTime[12];
			checkCharsLength(endTime, sizeof(endTime));
			while (!checkdate(endTime))
				checkCharsLength(endTime, sizeof(endTime));
			while (p) {
				if (strcmp(p->contime, startTime) > 0 && strcmp(p->contime, endTime) < 0) {				
					if ((extrem == 1 && extremType == 1 && p->charge > extremcharge) || (extrem == 1 && extremType == 2 && p->charge < extremcharge))
						extremcharge = p->charge;

					if ((extrem == 2 && extremType == 1 && p->LogID > extremLogID) || (extrem == 2 && extremType == 2 && p->LogID < extremLogID))
						extremLogID = p->LogID;
				}
				p = p->next;
			}
		}
		else if (selectType == 2) {
			while (p) {
				if ((extrem == 1 && extremType == 1 && p->charge > extremcharge) || (extrem == 1 && extremType == 2 && p->charge < extremcharge))
					extremcharge = p->charge;

				if ((extrem == 2 && extremType == 1 && p->LogID > extremLogID) || (extrem == 2 && extremType == 2 && p->LogID < extremLogID))
					extremLogID = p->LogID;

				p = p->next;
			}
		}
		if (extrem == 1 && extremType == 1)
			printf("最大消费金额:%.2lf", extremcharge);
		else if (extrem == 1 && extremType == 2)
			printf("最小消费金额:%.2lf", extremcharge);
		else if (extrem == 2 && extremType == 1)
			printf("最大LogID:%d", extremLogID);
		else
			printf("最小LogID:%d", extremLogID);
		printf("\n(1)继续查询极值\t(2)退出查询极值\n");
		selectAgain = checkNum();
	}
}

void selectPeriodData(ListConRec head) {
	ListConRec p;
	int selectAgain = 1;
	while (selectAgain == 1) {
		p = head->next;
		int position = 1;
		int printFormHead = 1;
		printf("请输入起始时间:\n");
		char startTime[12];
		checkCharsLength(startTime, sizeof(startTime));
		while (!checkdate(startTime)) 
			checkCharsLength(startTime, sizeof(startTime));		
		printf("请输入结束时间:\n");
		char endTime[12];
		checkCharsLength(endTime, sizeof(endTime));
		while (!checkdate(endTime))
			checkCharsLength(endTime, sizeof(endTime));
		while (p) {
			if (strcmp(p->contime, startTime) > 0 && strcmp(p->contime, endTime) < 0) {
				if (printFormHead == 1)
					outputFormHeadOfListConRec();
				printData2(p);
				printf(" %d\n", position);
				printFormHead++;
			}
			p = p->next;
			position++;
		}
		if (printFormHead == 1)
			printf("无处于该段时间的数据\n");
		else
			printf("提示:每行数据右下角的数字代表其在表格中的位置\n\n");
		printf("(1)继续某段时间内的时间\t(2)退出该查询\n");
		selectAgain = checkNum();
	}
	
}

13.sort.cpp

这里的代码写得冗余了,很不简洁

#include "head.h"

void insertSortByGrade(ListGrade head) {
	ListGrade p=head->next,pre,q;
	head->next = NULL;

	printf("您要根据哪个成绩排序?\n(1)平时成绩\t(2)期中成绩\t(3)期末成绩\t(4)加权成绩\n");
	int gradeType = checkNum1234();
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	switch (gradeType) {
	case 1:		
		if (order == 1) {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->usual < p->usual) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		else {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->usual > p->usual) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		break;

	case 2:
		if (order == 1) {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->midterm < p->midterm) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		else {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->midterm > p->midterm) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		break;

	case 3:
		if (order == 1) {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->exam < p->exam) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		else {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->exam > p->exam) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		break;

	case 4:
		if (order == 1) {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->final < p->final) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		else {
			while (p) {
				if (head->next == NULL) {
					head->next = p;
					p = p->next;
					head->next->next = NULL;
				}
				else {
					pre = head;
					q = head->next;
					while (q != NULL && q->final < p->final) {
						pre = q;
						q = q->next;
					}
					q = p->next;//保存p->next,方便后续赋值p=q
					p->next = pre->next;//这句跟下句顺序不可调!
					pre->next = p;
					p = q;//到下一节点
				}
			}
		}
		break;
	}
}

void insertSortByCredit(ListGrade head) {
	ListGrade p = head->next, pre, q;
	head->next = NULL;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && q->credit < p->credit) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
	else {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && q->credit > p->credit) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
}

void insertSortByStartTime(ListGrade head) {
	ListGrade p = head->next, pre, q;
	head->next = NULL;
	int order;
	printf("(1)从低到高排序(相对)\t(2)从高到低排序(相对)\n");
	order = checkNum();
	if (order == 1) {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				char qchars[10]; char pchars[10];
				strcpy(qchars, q->startTime); strcpy(pchars, p->startTime);
				char time1[5]; char time2[5]; char t[3]; char s[3];
				strncpy(time1, qchars, 5);
				strncpy(time2, pchars, 5);
				strncpy(t, qchars + 5, 3);
				strncpy(s, qchars + 5, 3);
				while (q != NULL && (strcmp(q->startTime, p->startTime) < 0) ){
					if (strcmp(time1, time2) == 0) {
						if (strcmp(t, "秋") == 0 && strcmp(s, "夏") == 0)
							break;
					}
					pre = q;
					q = q->next;
				}
				if (strcmp(time1, time2) == 0) {
					if (strcmp(t, "夏") == 0 && strcmp(s, "秋") == 0) {
						pre = q;
						q = q->next;
					}
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
	else {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && strcmp(q->startTime, p->startTime) > 0) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
}

void insertSortByLogID(ListConRec head) {
	ListConRec p = head->next, pre, q;
	head->next = NULL;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && q->LogID < p->LogID) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
	else {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && q->LogID > p->LogID) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
}

void insertSortByCharge(ListConRec head) {
	ListConRec p = head->next, pre, q;
	head->next = NULL;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && q->charge < p->charge) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
	else {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && q->charge > p->charge) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
}

void insertSortByContime(ListConRec head) {
	ListConRec p = head->next, pre, q;
	head->next = NULL;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				
				while (q != NULL && strcmp(q->contime, p->contime) < 0) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
	else {
		while (p) {
			if (head->next == NULL) {
				head->next = p;
				p = p->next;
				head->next->next = NULL;
			}
			else {
				pre = head;
				q = head->next;
				while (q != NULL && strcmp(q->contime, p->contime) > 0) {
					pre = q;
					q = q->next;
				}
				q = p->next;//保存p->next,方便后续赋值p=q
				p->next = pre->next;//这句跟下句顺序不可调!
				pre->next = p;
				p = q;//到下一节点
			}
		}
	}
}


//将链表head一分为二 且第一部分有n个元素 返回第二部分的头节点
ConRecNode* cut(ConRecNode* head, int n) {
	while (--n && head) {
		head = head->next;
	}
	if (!head)
		return head;
	ConRecNode* nxt = head->next;
	head->next = nullptr;
	return nxt;
}

//合并两个有序链表
ConRecNode* mergeByLogID(ConRecNode* l, ConRecNode* r) {
	ConRecNode head;
	head.LogID = 0;
	head.charge = 0;
	head.next = NULL;
	ConRecNode* cur = &head;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (l && r) {
			if (l->LogID <= r->LogID)
				cur->next = l, l = l->next;
			else
				cur->next = r, r = r->next;
			cur = cur->next;
		}
		cur->next = l ? l : r;
		return head.next;
	}
	else {
		while (l && r) {
			if (l->LogID >= r->LogID)
				cur->next = l, l = l->next;
			else
				cur->next = r, r = r->next;
			cur = cur->next;
		}
		cur->next = l ? l : r;
		return head.next;
	}
}

ConRecNode* mergeByCharge(ConRecNode* l, ConRecNode* r) {
	ConRecNode head;
	head.LogID = 0;
	head.charge = 0;
	head.next = NULL;
	ConRecNode* cur = &head;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (l && r) {
			if (l->charge <= r->charge)
				cur->next = l, l = l->next;
			else
				cur->next = r, r = r->next;
			cur = cur->next;
		}
		cur->next = l ? l : r;
		return head.next;
	}
	else {
		while (l && r) {
			if (l->charge >= r->charge)
				cur->next = l, l = l->next;
			else
				cur->next = r, r = r->next;
			cur = cur->next;
		}
		cur->next = l ? l : r;
		return head.next;
	}
}

ConRecNode* mergeByConTime(ConRecNode* l, ConRecNode* r) {
	ConRecNode head;
	head.LogID = 0;
	head.charge = 0;
	head.next = NULL;
	ConRecNode* cur = &head;
	int order;
	printf("(1)从低到高排序\t(2)从高到低排序\n");
	order = checkNum();
	if (order == 1) {
		while (l && r) {
			if (strcmp(l->contime, r->contime) <= 0)
				cur->next = l, l = l->next;
			else
				cur->next = r, r = r->next;
			cur = cur->next;
		}
		cur->next = l ? l : r;
		return head.next;
	}
	else {
		while (l && r) {
			if (strcmp(l->contime, r->contime) >= 0)
				cur->next = l, l = l->next;
			else
				cur->next = r, r = r->next;
			cur = cur->next;
		}
		cur->next = l ? l : r;
		return head.next;
	}
	
}

//封装函数代码比起上面的插入排序简洁了很多(虽然复用但没被封装的地方也不少)
ConRecNode* mergesortList(ConRecNode* head) {
	if (!head)
		return head;
	int len = 0;
	ConRecNode* l = head, * r, * tmp, * res;
	while (l && ++len)
		l = l->next;
	ConRecNode root;
	root.charge = 0;
	root.LogID = 0;
	root.next = head;
	//每次合并2*siz个元素
	for (int siz = 1; siz < len; siz <<= 1) {
		//从头开始
		res = &root;
		tmp = root.next;
		while (tmp) {
			//l是有序链表A r是有序链表B
			l = tmp;
			r = cut(l, siz);
			//注意要断开r与后者的连接(保证r的元素个数<=siz)
			tmp = cut(r, siz);
			//合并l r 并将其串接到前一次结果之后
			int sortType;
			printf("(1)根据LogID排序\t(2)根据消费金额排序\t(3)根据消费时间排序\n");
			sortType = checkNum123();			
			if(sortType==1)
				res->next = mergeByLogID(l, r);
			else if(sortType==2)
				res->next = mergeByCharge(l, r);
			else if(sortType==3)
				res->next = mergeByConTime(l, r);
			//为了保证每次都正确的串接上了 需要遍历到res的最后一个节点
			while (res->next)
				res = res->next;
		}
	}
	return root.next;
}

void sort(ListGrade listgrade, ListConRec listconrec) {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("您确认要排序吗?排序后无法变回原来次序!\n<1>确认排序\t<2>退出排序\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	int assuresort;
	assuresort = checkNum();
	if (assuresort == 1) {
		int sortContinue = 1;
		while (sortContinue==1) {
			printf("<1>对学生成绩表排序\t<2>对消费记录表排序\t<3>取消本次排序\n");
			int listType;
			listType = checkNum123();
			if (listType == 1) {
				if (listgrade->next) {
					printf("(1)根据成绩高低排序\t(2)根据学分高低排序\t(3)根据学期先后排序\t(4)取消本次排序\n");
					int sortType = checkNum1234();
					if (sortType == 1)
						insertSortByGrade(listgrade);
					else if (sortType == 2)
						insertSortByCredit(listgrade);
					else if (sortType == 3)
						insertSortByStartTime(listgrade);
					if (sortType != 4) {
						printf("排序成功!\n");
						printf("(1)查看排序后的学生成绩表\t(2)不查看\n");
						int checkList = checkNum();
						if (checkList == 1)
							print2(listgrade);
					}
				}
				else {
					printf("当前无学生成绩数据\n\n");
				}
				
			}
			else if (listType == 2) {
				if (listconrec->next) {
					if (lengthOfListConRec < 2000) {
						printf("(1)根据LogID排序\t(2)根据消费金额排序\t(3)根据消费时间排序\t(4)取消本次排序\n");
						int sortType = checkNum1234();
						if (sortType == 1)
							insertSortByLogID(listconrec);
						else if (sortType == 2)
							insertSortByCharge(listconrec);
						else if (sortType == 3)
							insertSortByContime(listconrec);
						if (sortType != 4)
							afterSortListConRec(listconrec);
					}
					else {
						mergesortList(listconrec->next);
						afterSortListConRec(listconrec);
					}
				}
				else {
					printf("当前消费记录表\n\n");
				}
					
			}
			else
				printf("您已取消本次排序\n");
			printf("(1)继续排序\t(2)退出排序\n");
			sortContinue = checkNum();
		}
	}
}

14.Diaplay.cpp

我在menu中定义的相关变量名都是input之类的(这明明是个跟输出有关的函数),懒得改了,别笑话我😂😁🤣

#include "head.h"

void print1(BasInfo head) {
	printf("\n             ▓▓▓▓▓▓▓▓▓▓▓\n");
	printf("▓▓▓▓▓▓▓▓▓▓▓▓ 个人基本信息▓▓▓▓▓▓▓▓▓▓▓▓\n");
	printf("             ▓▓▓▓▓▓▓▓▓▓▓\n\n\n");
	printf("姓名:%s\n学号:%s\n性别:%s\n学院:%s\n专业:%s\n班级:%s\n生日:%s\n", head.name, head.student_number, head.gender, head.academy, head.major, head.class_, head.birthday);
	printf("爱好:");
	for (int i = 0; i < head.hobby_length; i++) 
		printf(" %s ", head.hobby[i]);
	printf("\n电话号码:%s\n户籍地:%s\n", head.phone, head.address);
	
}

void print2(struct grade* head) {
	printf("\n\t\t\t\t\t╔════════════╗\n");
	printf("\t\t\t\t\t╬  学生成绩  ╬\n");
	printf("\t\t\t\t\t╚════════════╝\n\n");

	ListGrade p = head->next;
	printf("+--------------------+----------+-------+----------+----------+----------+----------+------+\n");
	printf("|        科目        |   学期   |  学分 | 平时成绩 | 期中成绩 | 期末成绩 | 最终成绩 | 重修 |\n");
	printf("+--------------------+----------+-------+----------+----------+----------+----------+------+\n");
	while (p != NULL) {
		printf("|%-20s|%-10s|%-7.2lf|%-10.2lf|%-10.2lf|%-10.2lf|%-10.2lf|%-6s|\n", p->subject, p->startTime, p->credit, p->usual, p->midterm, p->exam, p->final, p->chongxiu);
		printf("+--------------------+----------+-------+----------+----------+----------+----------+------+\n");
		p = p->next;
	}
}

void print3( ConRecNode* head) {
	printf("\n\t\t\t╔════════════╗\n");
	printf("\t\t\t╬  消费记录  ╬\n");
	printf("\t\t\t╚════════════╝\n");
	ListConRec p = head->next;
	printf("+--------------+------------+------------+----------------+\n");
	printf("|     LogID    |  消费时间  |  消费类型  |  消费金额      |\n");
	printf("+--------------+------------+------------+----------------+\n");
	while (p != NULL) {
		printf("|%-14d|%-12s|%-12s|%-16.2lf|\n", p->LogID, p->contime, p->connote, p->charge);
		printf("+--------------+------------+------------+----------------+\n");
		p = p->next;
	}

}

void outputFormHeadOfListGrade() {
	printf("+--------------------+----------+-------+----------+----------+----------+----------+------+\n");
	printf("|        科目        |   学期   |  学分 | 平时成绩 | 期中成绩 | 期末成绩 | 最终成绩 | 重修 |\n");
	printf("+--------------------+----------+-------+----------+----------+----------+----------+------+\n");
}

void outputFormHeadOfListConRec() {
	printf("+--------------+------------+------------+----------------+\n");
	printf("|     LogID    |  消费时间  |  消费类型  |  消费金额      |\n");
	printf("+--------------+------------+------------+----------------+\n");
}

15.save.cpp

保存数据。本来当初试着多加一个保存为csv文件的选项,这样的话这些保存好的数据就可以通过exceld打开,会好看很多。但是效果并不好,就取消了这个打算。

#include "head.h"

void save(BasInfo basinfo, ListGrade listgrade, ListConRec listconrec) {
	int saveway;

	printf("\n开始保存个人基本信息表\n");
	if (readin1(basinfo))
		printf("个人基本信息表保存成功!\n");

	printf("\n开始保存学生成绩表\n");
	if (readin2(listgrade))
		printf("学生成绩表已保存成功!\n");

	printf("\n开始保存消费记录表\n");
	if (readin3(listconrec))
		printf("消费记录表已保存成功!\n");
}


int readin1(BasInfo basinfo) {
	FILE* fp;
	char fileName[50];
	printf("请输入文件名:\n");
	checkCharsLength(fileName, sizeof(fileName));
	fp = fopen(fileName, "w");
	while (NULL==fp) {
		int savecontinue;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("文件保存失败。\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		printf("<1>继续保存\t<2>取消保存\n");
		savecontinue = checkNum();
		if (savecontinue == 1) {
			checkCharsLength(fileName, sizeof(fileName));
			fp = fopen(fileName, "w");
		}
		else if (savecontinue == 2) 
			return 0;				
	}
	fprintf(fp, "姓名:%s\n学号:%s\n性别:%s\n学院:%s\n专业:%s\n班级:%s\n生日:%s\n电话号码:%s\n户籍地:%s\n密码:%s\n", basinfo.name, basinfo.student_number, basinfo.gender, basinfo.academy, basinfo.major, basinfo.class_, basinfo.birthday, basinfo.phone, basinfo.address, basinfo.password);
	fclose(fp);
	return 1;
}

int readin2(struct grade* head) {
	ListGrade p = head->next;
	FILE* fp;
	char fileName[50];
	printf("请输入文件名:\n");
	checkCharsLength(fileName, sizeof(fileName));
	fp = fopen(fileName, "w");
	while (NULL == fp) {
		int savecontinue;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("文件保存失败。\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		printf("<1>继续保存\t<2>取消保存\n");
		savecontinue = checkNum();
		if (savecontinue == 1) {
			checkCharsLength(fileName, sizeof(fileName));
			fp = fopen(fileName, "w");
		}
		else if (savecontinue == 2)
			return 0;
	}
	while (p) {
		fprintf(fp, "%s %s %.2lf %.2lf %.2lf %.2lf %s\n", p->subject, p->startTime, p->usual, p->midterm, p->exam, p->final, p->chongxiu);
		p = p->next;
	}
	fclose(fp);
	return 1;
}

int readin3(ConRecNode* head) {
	ListConRec p = head->next;
	FILE* fp;
	char fileName[50];
	printf("请输入文件名:\n");
	checkCharsLength(fileName, sizeof(fileName));
	fp = fopen(fileName, "w");
	while (NULL == fp) {
		int savecontinue;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("文件保存失败。\n");
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
		printf("<1>继续保存\t<2>取消保存\n");
		savecontinue = checkNum();
		if (savecontinue == 1) {
			checkCharsLength(fileName, sizeof(fileName));
			fp = fopen(fileName, "w");
		}
		else if (savecontinue == 2)
			return 0;
	}
	while (p) {
		fprintf(fp, "%d %s %s %.2lf\n", p->LogID, p->contime, p->connote, p->charge);
		p = p->next;
	}
	fclose(fp);
	return 1;
}

16.style_setting.cpp

设置字体颜色和主菜单界面的随机变色

#include "head.h"
int currentColor = 7;
int welcomeColor = 1;
void setColor(UINT uFore, UINT uBack) {
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, uFore + uBack * 0x10);
}

void printTextColor() {
    printf("\n请选择您喜欢的字体颜色:\n");

    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 1);
    printf("<1>蓝色           ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
    printf("<2>绿色         ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
    printf("<3>浅蓝色      ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
    printf("<4>红色         ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 5);
    printf("<5>紫色\n");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 6);
    printf("<6>黄色           ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    printf("<7>白色         ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 8);
    printf("<8>灰色        ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 9);
    printf("<9>淡蓝色       ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
    printf("<10>浅绿色\n");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
    printf("<11>淡浅绿色      ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
    printf("<12>淡红色      ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 13);
    printf("<13>淡紫色     ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
    printf("<14>淡黄色      ");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
    printf("<15>亮白色\n");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);

}

void setTextColor() {
    printTextColor();
	char rubbish[128];
	int num;
	int textColor=7;
	num = scanf("%d", &textColor);
	while (textColor < 1 || textColor>15) {
		if (num == 0) {
			scanf("%s", rubbish);
			printf("请输入1-15的数字!不可以输入其他字符!请重新输入:\n");
			num = scanf("%d", &textColor);
		}
		else {
			printf("请正确输入1-15的数字!其他数字无效!请重新输入:\n");
			num = scanf("%d", &textColor);
		}
	}
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), textColor);
    currentColor = textColor;
    printf("\n");
}

void setWelcomeColor() {
    printf("(1)打开欢迎界面随机变色\t(2)关闭欢迎界面随机变色\n");
    welcomeColor = checkNum();
    printf("设置成功!\n");
}

17.destroy.cpp

销毁链表

#include "head.h"

void destroy2(struct grade* head) {
	ListGrade p=head, q=p->next;
	while (q) {
		free(p);
		p = q;
		q = p->next;
	}
	free(q);
}
void destroy3( ConRecNode* head) {
	ListConRec p = head, q = p->next;
	while (q) {
		free(p);
		p = q;
		q = p->next;
	}
	free(q);
}

18.others.cpp

#include "head.h"

void afterInsertIntoListGrade(ListGrade listgrade,int numBeforeInsert) {
	int checklength;
	printf("\n(1)输出成绩表\t(2)查看成绩表数据数量\t(3)取消查看\n");
	checklength = checkNum123();
	if (checklength == 2) {
		int numAfterInsert = getLengthOfListGrade(listgrade) - 1;
		printf("当前学生成绩信息表中有%d条记录\n", numAfterInsert);
		if (numBeforeInsert == numAfterInsert)
			printf("很遗憾,数据数量没变,删除失败,您可以尝试再次添加\n");
	}
	else if (checklength == 1) {
		printf("\n");
		print2(listgrade);
	}
}

void afterInsertIntoListConRec(ListConRec listconrec, int numBeforeInsert) {
	int checklength;
	printf("\n(1)查看消费记录表\t(2)查看数据数量\t(3)取消查看\n");
	checklength = checkNum123();
	if (checklength == 2) {
		int numAfterInsert = getLengthOfListConRec(listconrec) - 1;
		printf("当前消费记录表中有%d条记录\n", numAfterInsert);
		if (numBeforeInsert == numAfterInsert)
			printf("很遗憾,数据数量没变,删除失败,您可以尝试再次删除\n");
	}
	else if (checklength == 1) {
		printf("\n");
		print3(listconrec);
	}
}

void afterDeletefromListGrade(ListGrade listgrade, int numBeforeDelete) {
	int checklength;
	printf("\n(1)输出成绩表\t(2)查看成绩表数据数量\t(3)取消查看\n");
	checklength = checkNum123();
	if (checklength == 2) {
		int numAfterDelete = getLengthOfListGrade(listgrade) - 1;
		printf("当前学生成绩信息表中有%d条记录\n", numAfterDelete);
		if (numBeforeDelete == numAfterDelete)
			printf("很遗憾,数据数量没变,删除失败,您可以尝试再次删除\n");
	}
	else if (checklength == 1) {
		printf("\n");
		print2(listgrade);
	}
}

void afterDeleteFromListConRec(ListConRec listconrec, int numBeforeDelete) {
	int checklength;
	printf("\n(1)查看消费记录表\t(2)查看数据数量\t(3)取消查看\n");
	checklength = checkNum123();
	if (checklength == 2) {
		int numAfterDelete = getLengthOfListConRec(listconrec) - 1;
		printf("当前消费记录表中有%d条记录\n", numAfterDelete);
		if (numBeforeDelete == numAfterDelete)
			printf("很遗憾,数据数量没变,删除失败,您可以尝试再次删除\n");
	}
	else if (checklength == 1) {
		printf("\n");
		print3(listconrec);
	}
}

void afterSortListConRec(ListConRec listconrec) {
	printf("排序成功!\n");
	printf("(1)查看排序后的消费记录表\t(2)不查看\n");
	int checkList = checkNum();
	if (checkList == 1)
		print3(listconrec);
}

void aboutFileOfListGrade() {
	printf("\n仅支持导入.txt文件中的数据。且数据要按照如下格式排列(注意顺序和数据间的空格):\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("学科 学期 学分 平时成绩 期中成绩 期末成绩 加权成绩 是否重修\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	printf("以下是样例:\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("高等数学 2021-春 3.0 78.0 79.0 90.0 78.0 是\n大学物理 2022-夏 2.5 76.0 52.0 86.0 85.0 否\n\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
}

void aboutFileOfListConRec() {
	printf("\n仅支持导入.txt文件中的数据。且数据要按照如下格式排列(注意顺序和数据间的空格):\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("LogID 消费时间 消费类型 消费金额\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
	printf("以下是样例:\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	printf("1 2022-12-15 购物 212\n2 2021-11-23 教育 2320\n3 2021-10-20 服务 2000\n\n");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), currentColor);
}

测试数据

艾伦野鸽
000000000

调查兵团
新兵104期
驱逐巨人
2000-01-01


rap
篮球
music
鸡你太美
-1
12312312312
吸干希纳区
1
Buyaoya000

以下数据可以保存到.txt文件中用来测试文件导入

数学 2021-春 3.0 78.0 79.0 90.0 78.0 是
大物 2052-夏 2.5 76.0 52.0 86.0 85.0 否
组成原理 2052-夏 2.5 76.0 52.0 86.0 85.0 否
大物 2052-秋 2.5 76.0 52.0 86.0 85.0 否
思修 2120-春 3.0 34.5 54.5 25 95 是
思修 2120-夏 3.0 34.5 54.5 25 95 是
离散数学 2052-秋 2.5 76.0 52.0 86.0 85.0 否
近代史 2120-夏 3.0 34.5 54.5 25 95 是
思修 2120-秋 3.0 34.5 54.5 25 95 是
体育 2222-冬 -1 0 0 0 0 非
数学 2021-春 3.0 78.0 79.0 90.0 78.0 是
大物 2052-夏 2.5 76.0 52.0 86.0 85.0 否
组成原理 2052-夏 2.5 76.0 52.0 86.0 85.0 否
大物 2052-秋 2.5 76.0 52.0 86.0 85.0 否
组成原理 2052-夏 2.5 76.0 52.0 86.0 85.0 否
思修 2120-春 3.0 34.5 54.5 25 95 是
编译原理 2120-秋 3.0 34.5 54.5 25 95 是
计算机网络原理 2020-春 2.5 23 45 56 78 是
大英三 1922-秋 3.0 36.5 39.5 89.5 21.5 是

1 2022-12-15 购物 212
2 2021-11-23 教育 2320
3 2021-10-20 服务 2000
9 2023-12-05 其他 2356846
9 2023-12-05 其他 2356846
10 2021-10-12 教育 45467465645
11 2022-10-10 其他 56455
9 2023-12-05 其他 2356846
4 2025-12-23 医疗 800.0
5 1999-02-01 餐饮 120.5
6 2525-12-10 服务 25646.5
6 2525-12-10 服务 25646.5
7 2028-09-02 交通 135465
8 2120-04-14 其他 2646
9 2023-12-05 其他 2356846
10 2021-10-12 教育 45467465645
11 2022-10-10 其他 56455
6 2525-12-10 服务 25646.5
7 2028-09-02 交通 135465
1111111 2222-22-22 其他 22222222

虽然这是个比较糟糕的课设,但是我也花了不少心思在其中,值得纪念一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值