文章目录
前言
这次写课设时间的时间跨度有点大,最开始设计的程序流程、变量名、函数名等等都有不少问题、不合理的地方,充斥着不少初期留下的烂代码。希望读者明辨是非,别被我的烂代码给带跑了。那为什么我不具体指出哪些地方写得比较糟糕的?哈哈😄,这可是个不小的工程量,还是算了。
程序的总体功能图
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
虽然这是个比较糟糕的课设,但是我也花了不少心思在其中,值得纪念一下。