目录
主要功能
该管理系统包括了
1.加载所有数据 ,2.创建新数据链 ,3.查找或修改数据,4.删除数据据链,5.排序,6.统计总数 ,7.修改密码,8.theOther,9.退出程序 的功能。
该系统能够将写进去的数据储存到data.txt文件中,该文件放在D盘,后续可将该文件重新读入到系统中。
创新点是加了一个欢迎弹窗,一个进入输入密码的简单程序(密码文件在D:\\data.txt),最后theOther是无聊时玩的小玩意。
添加了的东西单纯对于一个简略的学生管理系统可能会有些无聊。
代码实现
一.包括的头文件和一些函数
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<malloc.h>
#include<time.h>
#include<Windows.h>
#define NULL 0
#define RoadeKey "D:\\key.txt"
#define RoadeDsta "D:\\data.txt"
typedef struct student {
int number;
char name[100];
double Chinese;
double maths;
double English;
double total;
struct student* next;
}student;
void Welcome(); //欢迎界面,显示功能
student* inTurnNumber(student* inTurn1); //无厘头的东西,给学号进行排序
void keyopen(); //登录时输入密码
student* createStudent(); //创建一个链表
int input(student* p1); //为creatsStudent()服务
void output(student* p1); //打印data
void inputData(student* m1,char a[]); //将数据格式化写入data.txt
student* printDataFromFile(); //从文件中读出数据
student* seek(student* p1); //查找数据,目前只能通过number,会成为一个累赘
student* addData(student* m2); //插入newData到传入链表前头,并将新链表打印出
student* deletData(student* p1); //输入nuber,删除结点
void sum(student* p1);
void changeKey();
void end(); //退出系统
void haveFun();
二,欢迎界面
void Welcome() {
printf("\n");
printf("***********************WELCOME!!****************************\n");
printf(" 1.加载所有数据 2.创建新数据链\t\n");
printf(" 3.查找或修改数据 4.删除数据\t\n");
printf(" 5.排序 6.统计总数\t\n");
printf(" 7.修改密码 8.theOther\t\n");
printf(" 9.退出程序 \t\n");
printf("____________________________________________________________\n");
}
三,将文件格式化写入文件并储存
void inputData(student* m1,char a[]) { //将数据格式化写入文件
if (m1 == NULL) return; //牛逼,原来这就是什么都不返回
FILE* fp;
errno_t no = fopen_s(&fp, RoadeDsta,a);
if (no) {
printf("didn't open the data\n");
exit(1);//似乎这个也可以删去了
}
fprintf(fp, "%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", m1->number, m1->name, m1->Chinese, m1->maths, m1->English, m1->total);
while (m1->next != NULL)
{
m1 = m1->next;
fprintf(fp, "%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", m1->number, m1->name, m1->Chinese, m1->maths, m1->English, m1->total);
}
free(m1);
rewind(fp);
fclose(fp); //一开始忘了这个,无法打开第二次
}
四,输入密码的函数,储存到文件中
void keyopen()
{
char a1[11]={0}, a2[11]={0};
int n = 5; char ch;
char a;
FILE* pFile;
errno_t no = fopen_s(&pFile, RoadeKey, "a+");
if (no == 1) exit(1);//打开失败
a=fgetc(pFile);
if (a == -1) { //或者EOF,当fgetc读取失败返回-1,读取成功返回读取的字符
printf("did't find the key,please create new key,must 10 character!\n");
scanf_s("%s", a1, 11); //储存用户创建的key
while ((ch = getchar()) != '\n'); //刷新缓存区
while (strlen(a1) != 10) { //strlen统计字符个数
printf("the key must to be 10 numbers\nplease try again\n");
//printf("%d", strlen(a1)); //检测strlen对于scanf输入
scanf_s("%s", a1, 11); //对于scanf_s这个函数还有没搞明白的;定义的数组为【10】,但是却是11,strlen才有用
while ((ch = getchar()) != '\n');
}
printf("please try again to check your first input!\n");
scanf_s("%s", a2, 11);
if (strcmp(a1,a2) == 0) { //对比两次输入的key是否一致,一致返回0
printf("the key was created!\n");
fputs(a1, pFile); //储存key
}
}
else {
rewind(pFile);
printf("please enter the key\n");
scanf_s("%s", a1, 11);//难道你也要读‘0’???10,打印不出来
while ((ch = getchar()) != '\n');
fgets(a2,11,pFile);//fgets计算字符长度加上结尾的'0'
//printf("%s", a1); 见131行
//printf("\n%d\n", strlen(a1));
//printf("%s", a1); // 测试
while (strcmp(a1, a2) != 0) { //按ascll码比较俩个数的大小
n--;
printf("the key was wrong,you have %d chance to try it\n", n+1);
scanf_s("%s", a1, 11);
while ((ch = getchar()) != '\n');
if (n == 0) {
printf("the progress will close\n");
exit(1);
}
}
printf("the key was right!\n");
}
printf("***********************WELCOME!!****************************\n");
fclose(pFile);
}
五,输入成绩
int input(student* p1) {
printf("please create a Student's data\n(number is 0 to exit.\n");
printf("number: "); scanf_s("%d", &p1->number);
if (p1->number == 0) return 0;
printf("name: "); scanf_s("%s", &p1->name, 100);
printf("Chinese: "); scanf_s("%lf", &p1->Chinese);
printf("maths: "); scanf_s("%lf", &p1->maths);
printf("English: "), scanf_s("%lf", &p1->English);
p1->total = p1->Chinese + p1->maths + p1->English;
return 1;
}
六,打印,将数据显示在屏幕
void output(student* p1) { //打印时一定要注意指针,不要将头指针给送进去,不然你就完了
printf("the list is here:\n");
printf("number\tname\tChinese\tmaths\tEnglish\ttotal\n");
printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", p1->number, p1->name, p1->Chinese, p1->maths, p1->English, p1->total);
while (p1->next!= NULL) { //p1!=NULL会多打一行乱码,why,改了之后好像没事了
p1 = p1->next;
printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", p1->number, p1->name, p1->Chinese, p1->maths, p1->English, p1->total);
}
}
七,从文件读出数据
student* printDataFromFile() {
int n = 0; int n1;
FILE* fp;
student* head1, * m1, * m2, * head;
m2 = m1 = (student*)malloc(sizeof(student));
head=head1 = NULL;
errno_t no = fopen_s(&fp, RoadeDsta, "r");
if (no) { //返回为1,打开失败
printf("didn't open the data or no data!!!\n");return head;
}
fseek(fp, 0L, 2); n1 = ftell(fp); rewind(fp);
if (n1 ==0) {
printf("no data!\n"); return head; //exit(1);一开始加这个,导致没有数据,程序停止运行
}
fscanf_s(fp, "%d", &m1->number);
fscanf_s(fp, "%s", m1->name, 100);
fscanf_s(fp, "%lf", &m1->Chinese);
fscanf_s(fp, "%lf", &m1->maths);
fscanf_s(fp, "%lf", &m1->English);
fscanf_s(fp, "%lf", &m1->total);
while (n1!=ftell(fp)) {
n++;
if (n == 1)head = m1;
else m2->next = m1;
m2 = m1;
m1 = (student*)malloc(sizeof(student));
//对m1->name不必要&,其本身为地址;
fscanf_s(fp, "%d", &m1->number);
fscanf_s(fp, "%s", m1->name, 100);
fscanf_s(fp, "%lf", &m1->Chinese);
fscanf_s(fp, "%lf", &m1->maths);
fscanf_s(fp, "%lf", &m1->English);
fscanf_s(fp, "%lf", &m1->total);
}
m2->next = NULL;
free(m1); //为什么将m1释放会乱码
rewind(fp);
head1 = head;
output(head1);
/*printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", head1->number, head1->name, head1->Chinese, head1->maths, head1->English, head1->total);
while (head1->next != NULL)
{
head1 = head1->next;
printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", head1->number, head1->name, head1->Chinese, head1->maths, head1->English, head1->total);
}*/
fclose(fp);
return head;
}
八,查找并修改数据
student* seek(student* p1) {
int n; int b = 0;
student* m1, * chaker2;
chaker2 = m1 = p1;
printf("please enter the students' number to find the data you want.\n");
scanf_s("%d", &n);
if (m1->number == n) {
chaker2 = m1;
printf("number\tname\tChinese\tmaths\tEnglish\ttotal\n");
printf(" % d\t % s\t % .2lf\t % .2lf\t % .2lf\t % .2lf\t\n", m1->number, m1->name, m1->Chinese, m1->maths, m1->English, m1->total);
printf("Do you want to change the data? \n1to go on and 0 to quit.\n");
scanf_s("%d", &n);
if (n == 0) { return p1; }
else {
input(m1);
m1->next = chaker2->next;
return p1;
}
}
while (m1->next != NULL) {
chaker2 = m1;
m1 = m1->next;
if (m1->number == n) {
b = 1;
printf("number\tname\tChinese\tmaths\tEnglish\ttotal\n");
printf(" % d\t % s\t % .2lf\t % .2lf\t % .2lf\t % .2lf\t\n", m1->number, m1->name, m1->Chinese, m1->maths, m1->English, m1->total);
printf("\n");
printf("Do you want to change the data? \n1to go on and 0 to quit.0 to quit.\n");
scanf_s("%d", &n);
if (n == 0) { return p1; }
else {
input(m1);
chaker2->next = m1;
return p1;
}
}
}
if ((m1->next == NULL) && (b == 0)) {
printf("can't find the number!\n ");
}
return p1;
}
九,添加数据
student* addData(student* m2) {
student* p1, * p2, * head, * head1;
//output(m2);//会打印多一行,why11052050->11061556现在不会了
p1 = p2 = (student*)malloc(sizeof(student));
printf("add students'data,number is 0 to quiz\n");
input(p1);
head = p1; p2 = p1;
while (p1->number != 0) {
p2->next = p1;
p2 = p1;
p1 = (student*)malloc(sizeof(student));
input(p1);
}
free(p1);
head1 = head;
p2->next = m2;
output(head);
printf("the data was added!\n");
return head1;
}
十,删除数据
student* deletData(student* p1) {
student* m1, * m2, * m3, * m4;
m4 = m3 = m1 = p1;
m2 = NULL;
printf("Please enter the student's number that you want to delet\n");
int n; int c=0;
scanf_s("%d", &n);
while ((n != m1->number) && (m1->next != NULL)) {
m2 = m1; m1 = m1->next;
}
if (n == m3->number) {
m3 = m3->next; m4 = m3;
}else if(n == m1->number) m2->next = m1->next; //最后一个数据怎么办11122025
else {
printf("did't find the data.\n");
return p1;
}
printf("the data was deleted!\n");
printf("number\tname\tChinese\tmaths\tEnglish\ttotal\n");
printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", m3->number, m3->name, m3->Chinese, m3->maths, m3->English, m3->total);
while (m3->next != NULL)
{
m3 = m3->next;
printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", m3->number, m3->name, m3->Chinese, m3->maths, m3->English, m3->total);
}
return m4;
}
十一,退出
void end() {
exit(1);
}
十二,排序
student* inTurnNumber(student* inTurn1) {
student* inTurn2 = inTurn1;
student* inTurn3 = inTurn1;
int b, c; int j = 0, i = 1;
double a[2000] = { 0 };//最多容纳2000个数据进行排序
int classify = 0;
printf("to turn by what?enter the serial number.\n1 is number.\t2 is Chinese.\n3 is maths.\t4 is English.\t5 is Total.\n");
scanf_s("%d", &classify);
if(classify==1) a[j] = inTurn2->number;
else if(classify==2) a[j] = inTurn2->Chinese;
else if (classify == 3) a[j] = inTurn2->maths;
else if (classify == 4) a[j] = inTurn2->English;
else if (classify == 5) a[j] = inTurn2->total;
else { printf("There is not the choice!BYB\n"); return inTurn1; }
while (inTurn2->next != NULL) {
j++; //j不表示个数
inTurn2 = inTurn2->next;
if (classify == 1) a[j] = inTurn2->number;
else if (classify == 2) a[j] = inTurn2->Chinese;
else if (classify == 3) a[j] = inTurn2->maths;
else if (classify == 4) a[j] = inTurn2->English;
else if (classify == 5) a[j] = inTurn2->total;
}
inTurn2 = NULL;
/*for (int i = 0; i <=j; i++) {
printf("%lf\n", a[i]);
}*/
printf("\n");
for (int i = 0; i < j ; i++) {
b = a[i]; c = i;
for (int k = (i + 1); k <= j; k++) {
if (b < a[k]) {
b = a[k];
c = k;
}
}
a[c] = a[i];
a[i] = b;
}
printf("\n");
/*for (int i = 0; i <= j; i++) {
printf("%d\t", a[i]);
}
printf("\n");*/
//printf("%d\n", j);
i = 0;
printf("number\tname\tChinese\tmaths\tEnglish\ttotal\n");
while (i != (j+1)) {
if(classify==1) while (a[i] != inTurn3->number) inTurn3 = inTurn3->next;
else if (classify == 2) while (a[i] != inTurn3->Chinese) inTurn3 = inTurn3->next;
else if (classify == 3) while (a[i] != inTurn3->maths) inTurn3 = inTurn3->next;
else if (classify == 4) while (a[i] != inTurn3->English) inTurn3 = inTurn3->next;
else if (classify == 5) while (a[i] != inTurn3->total) inTurn3 = inTurn3->next;
printf("%d\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t\n", inTurn3->number, inTurn3->name, inTurn3->Chinese, inTurn3->maths, inTurn3->English, inTurn3->total);
i++;
inTurn3 = inTurn1;
}
// inTurn2->next = NULL;
return inTurn2;//inTurn2是空的
}
十三,创建新数据链
student* createStudent() { //创建链表
struct student* head, * p1, * p2; //定义一个头指针,两个工作指针,节点数n初始化为0
int n = 0; //将头指针指向空,为p1,p2申请内存
head = NULL;
p2 = p1 = (struct student*)malloc(sizeof(struct student));
int r = input(p1);
if (r == 0) return head;
while (p1->number != 0) //开始循环,以num为0作为结束条件
{
n++; //结点数加一
if (n == 1)head = p1; //将p1给头指针
else p2->next = p1; //将p1链到p2尾部
p2 = p1; //将p1赋给p2
p1 = (struct student*)malloc(sizeof(struct student)); //再次为p1申请内存
input(p1);
}
p2->next = NULL; //循环结束后,将p2的尾部链到空,避免成为野指针
free(p1); //将p1的空间释放
return head;
}
十四,计算总和
void sum(student* p1) {
student* sum = p1; int t = 1, pass1 = 0, pass2 = 0, pass3 = 0, pass4 = 0;
double sum1=0, avg1 = 0, PASS1 = 0, sum2 = 0, avg2 = 0, PASS2 = 0, sum3 = 0, avg3 = 0, PASS3 = 0, sum4 = 0, avg4 = 0, PASS4 = 0;
sum1 = sum->Chinese; sum2 = sum->maths; sum3 = sum->English; sum4 = sum->total;
if (sum->Chinese >= 60) pass1++;
if (sum->maths >= 60) pass2++;
if (sum->English >= 60) pass3++;
if (sum->total >= 60) pass4++;
while (sum->next != NULL) {
sum = sum->next;
sum1 += sum->Chinese; sum2 += sum->maths; sum3 += sum->English; sum4 += sum->total;
t++;
if (sum->Chinese >= 60) pass1++;
if (sum->maths >= 60) pass2++;
if (sum->English >= 60) pass3++;
if (sum->total >= 60) pass4++;
}
avg1 = sum1 / t; avg2 = sum2 / t; avg3 = sum3 / t; avg4 = sum4 / t;
PASS1 = (double)pass1 / t; PASS2 = (double)pass2 / t; PASS3 = (double)pass3 / t;
printf("A total of %d dtudents took the examination,as follows:\n",t);
printf("the sum\t average score\t percent of pass\t\n");
printf("Chinese\t %.2lf\t %.2lf\t\n", avg1, PASS1);
printf("maths\t %.2lf\t %.2lf\t\n", avg2, PASS2);
printf("English\t %.2lf\t %.2lf\t\n", avg3, PASS3);
printf("total\t %.2lf\t NULL\n", avg4);
}
十五,修改密码
void changeKey() {
FILE* fp; char ch;
errno_t no = fopen_s(&fp, RoadeKey, "r");
if (no) { printf("ERRNO!"); return; }
char key1[11] = { 0 }; char key2[11] = { 0 };//why 如果是10,运行时提示周围堆栈已损坏
int i = 0;
fgets(key1, 11, fp);
/*while ((key1[i] = fgetc(fp)) != EOF) i++;*/
/*for (int i = 0; i < 10; i++) {
key1[i] = fgetc(fp);
}*/
fclose(fp);
//printf("%s\n",key1);
printf("Please input the Initial password:\n");
scanf_s("%s", key2, 11);
if (strcmp(key1, key2) != 0) { //相同,返回0
printf("the password was wrong!!GOODBYB!\n");
return;
}
else {
printf("Create your new password:\n");
scanf_s("%s", key2, 11);
while (ch=(getchar()) != '\n');
while (strlen(key2) != 10) {
printf("the key must to be 10 numbers\nplease try again\n");
scanf_s("%s", key2, 11);
while ((ch = getchar()) != '\n');
}
errno_t no = fopen_s(&fp, RoadeKey, "w");
if (no) { printf("ERRNO!"); return; }
fputs(key2, fp);
fclose(fp);
}
}
十六,theOther的函数
void haveFun() {
char color[10] = "color ";
char a1[2], a2[2];
printf("0.黑色\t1.蓝色\t2.绿色\t3.浅绿色\t4.红色\t5.紫色\t6.黄色\t7.白色\t8.灰色\t9.淡蓝色\n ");
printf("A.淡绿色\tB.淡浅绿色\tC. 淡红色\tD.淡紫色\tE.淡黄色\tF.亮白色\n");
printf("输入一个数字或一个字母(背景)\n");
scanf_s("%s", a1,2);
printf("输入第二个数字或字母(前景)\n");
scanf_s("%s",a2,2);
if ((strcmp(a1, a2)) == 0)printf("Nothing happened sometime!");
strcat_s(color, a1); strcat_s(color, a2);
printf("%s",color);
system(color);
}
主函数
int main() {//学生人数统计
int q, q1 = 0; char a[][2] = { "a","r","w"};//a追加,r只读
student* p1, * p2;
MessageBox(NULL,TEXT("HelloWord!This is MessageBox."),TEXT("你好,这里是弹窗。"), MB_OK | MB_ICONASTERISK);//好玩的东东
keyopen();
Welcome();
printf("intut a number to go on:\n");
int i = scanf_s("%d", &q);
/* if (i != 1) { //如何判断输入的东西不合法
printf("input errno!!try again.\n"); scanf_s("%d", &q);
}*/
while (true) {
switch (q)
{
case 1:p1 = printDataFromFile();
break;
case 2: {p1 = createStudent(); inputData(p1, a[0]); }
break;
case 3: {p1 = printDataFromFile(); p1 = seek(p1); inputData(p1, a[2]); }
break;
case 4: {p1 = printDataFromFile(); p1 = deletData(p1); inputData(p1, a[2]); }
break;
case 5: {p1 = printDataFromFile(); p1 = inTurnNumber(p1); }
break;
case 6: {p1 = printDataFromFile(); sum(p1); }
break;
case 7:changeKey();
break;
case 8: {getchar(); haveFun(); }
break;
case 9:end();
break;
default:printf("%d is not a command!!\n", q);
break;
}
printf("Any key to continue_\n");
getchar(); getchar();
Welcome();
printf("输入一个序号\n");
scanf_s("%d", &q);
}
return 0;
}
运行
1,弹窗界面,可在mian中修改。
2, 一个输入密码的判断机制,五次错误后强制退出
3,欢迎界面
注:有些序号如6.统计所有数据,需要在D盘中存有data.txt,然后运行函数将它读出排序倘若D盘中没有txt,则会报错退出程序,原因:没有对其进行错误判断。后续可自行添加。(但有些函数添加了判断,如1,加载所有数据,没有数据则打印出“no data !”)
4,theOther
5,data
存在错误
1,排序的函数过于冗长,但我还没找到更好颁发。
2,有些函数没有错误判断机制,但不多(主要是该程序已经告一段落,不想再改了)