基于C语言的军运会学生志愿者管理系统
关键词:C语言、课程设计、军运会志愿者管理系统
一、背景
- 基本掌握面向过程程序设计的基本思路和方法;
- 达到熟练掌握C语言的基本知识和技能;
- 能够利用所学的基本知识和技能,解决简单的程序设计问题;
- 独立进行程序的编写,为后续学习及课程做好准备。
二、环境
本程序开发所使用的环境为Visual Studio 2010 Community版 + Windows10 Professional操作系统
三、要求
为了迎接武汉市世界军人运动会,请你学习C语言中相关知识,帮助组委会设计一个军运会志愿者信息管理系统,包含以下主要功能(不限于以下):
- 实现对志愿者信息的管理,包括添加志愿者信息(姓名,学号,联系方式等等),查询志愿者信息,删除志愿者信息;
- 实现军运会场馆的管理,包括添加场馆信息,查询场馆信息,删除场馆信息;
- 实现通过文件保存志愿者信息;
- 实现每个场馆对应不同志愿者的分配管理(例如,田径场需要4位志愿者,射击馆需要2位志愿者);
- 实现志愿者和场馆信息的快速查询统计功能,可以根据最后志愿服务时间评选最美志愿者;
- 除以上基本功能外,可根据各位同学自己设定的需求自行添加。
四、数据结构
typedef struct sfield{ //场馆信息结构体
int fieldId; //场馆节点唯一数字id(int)
char fieldName[30]; //场馆名字(char[30])
char startTime[20]; //开始时间(char[20])
int lastTime; //持续时间(int)
int maxVolunteer; //需要志愿者数量(int)
int joinedVolunteer[MAX1]; //保存已加入志愿者信息(int[MAX1]) (MAX1=100)
struct sfield* head; //节点头部指针,指向上一个节点(struct sfield*)
struct sfield* next; //节点尾部指针,指向下一个节点(struct sfield*)
}field;
typedef struct svolunteer{ //志愿者信息结构体
int volunteerId; //志愿者节点唯一数字id(int)
char volunteerName[30]; //志愿者名字(char[30])
char idNum[20]; //志愿者学号(char[20])
char phoneNum[20]; //志愿者手机号(char[20])
int joinedField[MAX2]; //保存志愿者加入场馆唯一id(int[MAX2]) (MAX2=20)
int serviceTime; //志愿服务时长(int)
struct svolunteer* head; //节点头部指针,指向上一个节点(struct svolunteer*)
struct svolunteer* next; //节点尾部指针,指向下一个节点(struct svolunteer*)
}volunteer;
本程序使用两类结构体,分别储存志愿者信息(Volunteer)和场馆信息(Field)。每个结构体准备了指向上一个节点与下一个节点的指针,用于创建动态链表。如果要自行修改为使用数组储存数据,则可以不用这些指针。
五、定义功能函数
void startUp();//初始化函数,将数据链表头结点头尾部初始化,数据部分清零,防止出错
int readFile(); //读取已保存的数据文件,若不存在则建立
int saveFile(); //储存已保存的数据文件,若不存在则建立
void newField();
//新增场馆信息
void newVolunteer(); //新增志愿者信息
void changeField(field*); //修改场馆信息
void changeVolunteer(); //修改志愿者信息
void deleteField(); //删除场馆信息
void deleteVolunteer(); //删除志愿者信息
void bind(); //注册志愿活动
void unbind(); //注销志愿活动
void showMenu(); //显示主菜单
void manageField(); //显示场地管理菜单
void manageVolunteer(); //显示志愿者管理菜单
field* selectFieldById(int); //通过唯一ID查找场馆指针
field* selectFieldByName(char*); //通过场馆名字查找场馆指针
volunteer* selectVolunteerById(int); //通过唯一ID查找志愿者指针
volunteer* selectVolunteerByName(char*); //通过志愿者名字查找志愿者指针
volunteer* selectVolunteerByIdNum(char*); //通过志愿者学号查找志愿者指针
volunteer* selectVolunteerByPhoneNum(char*); //通过志愿者手机号查找志愿者指针
void showField(field*); //显示指定场馆信息
void showVolunteer(volunteer*); //显示指定志愿者信息
void showAllField(); //显示所有场馆信息
void showAllVolunteer(); //显示所有志愿者信息
void findOutTopVolunteer(); //根据志愿服务时长寻找“最美志愿者”
void filePrintMenu(); //显示文件格式化输出菜单
void outPutFile(char*, int); //显示文件格式化输出菜单
六、运行结果截图
1.启动程序
2.添加场馆信息
3.添加志愿者信息
4.修改运动馆信息
5.注册志愿活动
6.注册志愿活动时输入错误数据
7.场馆满员后注册志愿活动
8.查询所有志愿者信息
9.寻找最美志愿者
10.格式化输出文件
附:格式化输出的文件内容:
六、函数模块功能介绍
1.场馆信息管理
进入场馆信息管理模块,显示该模块下可用的操作:新增、修改、删除场馆信息、根据场馆名查询指定场馆信息。
新增场馆信息:调用 newField()
函数,并且显示引导提示菜单,引导用户按格式输入要新增的场馆信息,本程序采用整行输入方式,用指定符号分割不同数据类型,最后将读入的输入字符串通过该指定符号进行分割,分割出几组字符串。首先检查字符串数量是否满足输入要求,如果有错误则会报错并退出该函数。若输入格式正确,下一步会调用 selectFieldByName(char*)
函数寻找是否已有相同名字场馆信息,若返回非NULL值(即确实已经存在同名场馆),则提示用户该错误并退出本函数。上述检查完成后,通过一开始声明的全局变量 _FIELD
找到储存场馆信息链表头结点,归递寻找至链表尾部,同时记录已有的节点数,最后在链表尾部分配新节点并连接上原链表尾,同时新节点的last指针记录原链表尾节点地址。调用 saveFile()
函数,将已有的数据保存至磁盘,最后提示用户保存成功结果。
修改场馆信息:先根据用户输入的场馆名,调用 selectFieldByName(char*)
函数,若返回空值则提示用户未找到对应名字的链表,否则根据该函数返回的 field*
类型指针,调用 changeField(field*)
函数。调用此函数后,会先显示该场馆信息节点中记录的场馆信息,并提示用户输入要修改的数据类型。用户输入后,先检查输入是否有误,有误则报错并返回,无误则提示输入要修改成的数据,输入后第输入数据进行检查,无误则将该节点信息对应数据修改为用户输入,调用 saveFile()
函数保存文件,最后提示修改成功。
删除场馆信息:先根据用户输入的场馆名,调用 selectFieldByName(char*)
函数,若返回空值则提示用户未找到对应名字的链表,否则根据该函数返回的 field*
类型指针,调用 deleteField(field*)
函数。调用该函数后,会先显示该场馆信息节点中记录的场馆信息,并再次向用户确认是否要删除该场馆信息,用户输入否则退出此函数。若确认删除,先根据该节点的next指针判断此节点是否为链表尾,若非节点尾,则根据该节点的head指针找到上一个节点,分别将 head
指针对应的上一个节点中的 next
指针指向该要删除节点的 next
指针指向的下一个节点,将next指针指向的下一个节点中的 head
指针指向该要删除的节点的 head
指针指向的上一个节点的地址,接着遍历该节点中的 joinedVolunteer
数组,寻找对应的已加入志愿者,找到后进入该志愿者节点,将其 joinedField
数组中对应的此要删除节点的id记录删除掉,并将该志愿者的志愿服务时长减去该要删除节点的服务时间长度。待以上操作全部完成后,使用 free(void*)
函数释放掉该要删除节点内存,然后调用 saveFile()
函数将修改后的链表重新保存至文件。最后向用户返回删除成功提示。
查询指定场馆信息:提示用户输入要查询的场馆名,然后调用 selectFieldByName(char*)
函数,若返回空值,则提示未找到对应场馆信息,退出函数。若返回非空值,则根据返回的 field*
类型指针,调用 showField(field*)
函数,打印出对应场馆信息,并遍历该场馆节点中的 joinedVolunteer
数组,通过其中记录的志愿者id,调用 selectVolunteerById(int)
寻找每一个加入志愿者对应节点,然后打印出该志愿者信息。
2.志愿者信息管理
该模块功能其实与场馆信息管理功能基本一致,只不过操作对象由场馆链表变为了志愿者链表,其他基本可以类比,这里不再过多赘述。
3.志愿服务管理
该模块没有对应独立二级菜单,仅有的两个功能(注册志愿活动、注销志愿活动)直接显示在主菜单,可以直接从主菜单进入。
注册志愿活动:提示用户分别输入要注册的志愿活动对应的场馆信息和志愿者信息,与新增场馆/志愿者信息类似,这里采用读入整行字符串,通过特殊字符串来分割这一整行字符串的方式读取用户输入数据,首先检查输入格式是否有误,确认无误后根据输入数据分别寻找对应的场馆与志愿者节点,此处在输入志愿者姓名后还要求输入学号,作为二次校验,防止输入错误导致的绑定错误,如果输入的姓名与学号不对应同一个志愿者信息节点,则返回错误提示。一切输入数据确认无误后,进行绑定,具体流程如下:
- 在寻找到的输入场馆节点中的joinedVolunteer数组中进行查找,如果其中已存在对应输入的志愿者id,则提示不能重复绑定同一人并退出此绑定流程。
- 在寻找到的输入场馆节点检测已加入志愿者是否已达到最大允许加入志愿者数量,若已达到则提示该活动名额已满并退出此绑定流程。
- 在寻找到的输入志愿者节点中检测其已加入场馆数量是否已达到单个志愿者允许加入的最大场馆数量上限,若是则提示该志愿者志愿活动已达到上限。
- 以上检查均没有错误后显示对应场馆信息以及志愿者信息,并向用户确认是否要注册该志愿活动,若否则退出注册流程。
- 在寻找到的输入场馆节点中的joinedVolunteer数组中添加进寻找到的输入志愿者id,在寻找到的输入志愿者节点中的joinedField数组中添加寻找到的输入场馆id,并在寻找到的输入志愿者节点中的serviceTime(服务时间)加上对应场馆志愿活动时间。最后向用户返回注册成功的提示。
4.寻找最美志愿者
调用 findOutTopVolunteer()
函数。先设置几个变量供寻找时临时使用,如设置 longestTime
为0,然后遍历志愿者信息链表(头节点:全局变量 _VOLUNTEERS
),遍历到的节点如果 serviceTime
与 longestTime
相同,则向临时的 volunteer*
型指针数组的第一个无数据位添加进该节点的地址。然后继续向下遍历,如果遍历到的节点 serviceTime
大于 longestTime
,则将该节点 serviceTime
值赋给 longestTime
变量,并用 memset(void*,int,int)
函数将原有的 volunteer*
型指针数组清空,然后将其第一个数据位加入本节点的地址。最后遍历完成之后,最终打印出 volunteer*
型指针数组中非空成员数量,记为“最美志愿者”个数,然后遍历该 volunteer*
型指针数组,分别将节点对应成员信息打印出来作为“最美志愿者”信息,以及临时变量 longestTime
作为“最美志愿者”的志愿服务时长也打印出来。
5.文件的存取
本程序只会在启动时首先自动执行的 startUp()
函数中调用 readFile()
函数对已保存文件进行读取,若数据文件不存在则建立数据文件然后退出 readFile()
函数。先分别建立 field
型与 volunteer
型变量用以储存临时数据,打开“fieldData.txt”文件,使用 fread()
函数按块读入已储存的数据内容,并将其存入 field
型临时变量中,然后分配 field
大小内存作为节点将该变量的值分别赋入节点中对应变量,并将上一个节点的 next
指针指向本新分配节点,将本新分配节点的head指针指向上一个节点,将 next
指针设为NULL。循环 fread()
函数以及后面这一组操作,直到读取到文件尾,最后关闭文件。然后对 volunteer
型数据进行相同的操作,此处类比。
在每一次新增、修改、删除操作(不论是对场馆信息还是志愿者信息)以及注册、注销志愿活动之后,都会调用 saveFile()
函数对数据进行保存。若数据文件存在也会使用“w”模式将数据全部重新覆写,接着类似 readFile()
,先建立临时变量,根据全局变量 _FIELD
找到场馆信息链表头,然后遍历场馆信息链表,将每个节点中的数据部分(即除 head
、next
指针外的部分)拷贝到临时变量,然后调用 fwrite()
函数将数据写入文件,直至链表遍历完毕,最后关闭文件。然后对 volunteer
型数据进行相同的操作,此处类比。
本程序虽然没有使用“wb”类的二进制数据储存法,但是使用的 fwrite()
函数是不会对非字符类型变量进行转换的,所以生成的数据文件虽以文本形式储存,但是其对应非char类型的数据位部分会显示乱码,而且字符串\0后未填满部分也会以“烫”字储存(因为VS编译器对于字符串中空字符默认的特性),所以本程序直接生成的数据文件并不具备有良好的可读性,为了解决这一问题,本程序额外加入了“格式化输出文件”功能(自主添加的额外功能),将数据以人类可阅读的形式格式化输出。
七、源代码
源代码
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX1 100 //设置单场馆最大参加志愿者人数100
#define MAX2 20 //设置个人默认最大参加项目数量20
typedef struct sfield{ //场馆信息结构体
int fieldId; //场馆节点唯一数字ID
char fieldName[30]; //场馆名字
char startTime[20]; //开始时间
int lastTime; //持续时间(分钟)
int maxVolunteer; //需要志愿者数量
int joinedVolunteer[MAX1]; //保存已加入志愿者信息
struct sfield* head; //节点头部指针
struct sfield* next; //节点尾部指针
}field;
typedef struct svolunteer{ //志愿者信息结构体
int volunteerId; //志愿者节点唯一数字ID
char volunteerName[30]; //志愿者名字
char idNum[20]; //志愿者学号
char phoneNum[20]; //志愿者手机号
int joinedField[MAX2]; //志愿者加入场馆唯一ID数组
int serviceTime; //志愿者服务时长
struct svolunteer* head; //节点头部指针
struct svolunteer* next; //节点尾部指针
}volunteer;
//声明函数
void startUp(); //初始化函数
int readFile(); //读取文件
int saveFile(); //储存文件
void newField(); //新增场馆
void newVolunteer(); //新增志愿者
void changeField(field*); //修改场馆
void changeVolunteer(volunteer*); //修改志愿者
void deleteField(field*); //删除场馆
void deleteVolunteer(volunteer*); //删除志愿者
void bind(); //注册志愿活动
void unbind(); //注销志愿活动
void showMenu(); //显示主菜单
void manageField(); //显示场地管理菜单
void manageVolunteer(); //显示志愿者管理菜单
void filePrintMenu(); //显示文件格式化输出菜单
void outputFile(char*,int); //自定义文件输出
field* selectFieldById(int); //通过唯一id查找场馆指针
field* selectFieldByName(char*); //通过场馆名字查找场馆指针
volunteer* selectVolunteerById(int); //通过唯一id查找志愿者指针
volunteer* selectVolunteerByName(char*); //通过志愿者名字查找志愿者指针
volunteer* selectVolunteerByIdNum(char*); //通过志愿者学号查找志愿者指针
volunteer* selectVolunteerByPhoneNum(char*); //通过志愿者手机号查找志愿者指针
void showField(field*); //根据场馆指针显示场馆信息
void showVolunteer(volunteer*); //根据志愿者指针显示志愿者信息
void showAllField(); //显示所有场馆信息
void showAllVolunteer(); //显示所有志愿者信息
void findOutTopVolunteer(); //寻找最美志愿者
//初始化全局变量
field * _FIELD; //分配场馆信息头部节点
volunteer * _VOLUNTEER; //分配志愿者信息头部节点
void startUp(){
system("title 军运会管理系统--by Raoby"); //设置窗口标题
system("color 70");
_FIELD=(field*)malloc(sizeof(field));
_VOLUNTEER=(volunteer*)malloc(sizeof(volunteer));
_FIELD->head=NULL;
_VOLUNTEER->head=NULL;
_FIELD->next=NULL;
_VOLUNTEER->next=NULL;
readFile();
}
//函数定义部分
int saveFile(){
int fieldLength,volunteerLength,i;
FILE* fp1,*fp2;
field _TEMP1;
volunteer _TEMP2;
field* p1=_FIELD->next;
volunteer* p2=_VOLUNTEER->next;
fp1=fopen("fieldData.txt","w");
fclose(fp1);
fp1=fopen("fieldData.txt","a");
for(fieldLength=0;p1;p1=p1->next){
fieldLength++;
}
fp2=fopen("volunteerData.txt","w");
fclose(fp2);
fp2=fopen("volunteerData.txt","a");
for(volunteerLength=0;p2;p2=p2->next){
volunteerLength++;
}
p1=_FIELD->next;
p2=_VOLUNTEER->next;
i=0;
while(i++<fieldLength){ memcpy((void*)&_TEMP1,p1,sizeof(field)-2*sizeof(field*)); if(!fwrite((void*)&_TEMP1,sizeof(field)-2*sizeof(field*),1,fp1)){ fclose(fp1); fp1=fopen("fieldData.txt","w"); fclose(fp1); return EOF; } p1=p1->next;
}
fclose(fp1);
printf("已保存%d个场馆数据\n",i-1);
i=0;
while(i++<volunteerLength){ memcpy((void*)&_TEMP2,p2,sizeof(volunteer)-2*sizeof(volunteer*)); if(!fwrite((void*)&_TEMP2,sizeof(volunteer)-2*sizeof(volunteer*),1,fp2)){ fclose(fp2); fp1=fopen("volunteerData.txt","w"); fclose(fp2); return EOF; } p2=p2->next;
}
fclose(fp2);
printf("已保存%d个志愿者数据\n",i-1);
//system("pause");
return 1;
}
int readFile(){
int fieldLength=0,volunteerLength=0;
FILE* fp1,*fp2;
field _TEMP1;
volunteer _TEMP2;
field* p1=_FIELD;
volunteer* p2=_VOLUNTEER;
if(!(fp1=fopen("fieldData.txt","r"))){
fp1=fopen("fieldData.txt","w");
fclose(fp1);
}else{
for(fieldLength=0;fread((void*)&_TEMP1,sizeof(field)-2*sizeof(field*),1,fp1);fieldLength++){
p1->next=(field*)malloc(sizeof(field));
memcpy(p1->next,&_TEMP1,sizeof(field)-2*sizeof(field*));
p1->next->head=p1;
p1->next->next=NULL;
p1=p1->next;
}
fclose(fp1);
}
if(!(fp2=fopen("volunteerData.txt","r"))){
fp2=fopen("volunteerData.txt","w");
fclose(fp2);
}else{
for(volunteerLength=0;fread((void*)&_TEMP2,sizeof(volunteer)-2*sizeof(volunteer*),1,fp2);volunteerLength++){
p2->next=(volunteer*)malloc(sizeof(volunteer));
memcpy(p2->next,&_TEMP2,sizeof(volunteer)-2*sizeof(volunteer*));
p2->next->head=p2;
p2->next->next=NULL;
p2=p2->next;
}
fclose(fp2);
}
/*printf("共有%d个场馆数据\n",fieldLength);
printf("共有%d个志愿者数据\n",volunteerLength);*/
//system("pause");
return 1;
}
field* selectFieldById(int id){ //通过唯一id查找场馆指针
field* p=_FIELD;
do{
if(p->fieldId==id){
return p;
}
p=p->next;
}while(p);
return NULL;
}
field* selectFieldByName(char* name){ //通过场馆名字查找场馆指针
field* p=_FIELD;
do{
if(!strcmp(p->fieldName,name)){
return p;
}
p=p->next;
}while(p);
return NULL;
}
volunteer* selectVolunteerById(int id){ //通过唯一id查找志愿者指针
volunteer* p=_VOLUNTEER;
do{
if(p->volunteerId==id){
return p;
}
p=p->next;
}while(p);
return NULL;
}
volunteer* selectVolunteerByName(char* name){ //通过志愿者名字查找志愿者指针
volunteer* p=_VOLUNTEER;
do{
if(!strcmp(p->volunteerName,name)){
return p;
}
p=p->next;
}while(p);
return NULL;
}
volunteer* selectVolunteerByIdNum(char* idNum){ //通过志愿者学号查找志愿者指针
volunteer* p=_VOLUNTEER;
do{
if(!strcmp(p->idNum,idNum)){
return p;
}
p=p->next;
}while(p);
return NULL;
}
volunteer* selectVolunteerByPhoneNum(char* phoneNum){ //通过志愿者手机号查找志愿者指针
volunteer* p=_VOLUNTEER;
do{
if(!strcmp(p->phoneNum,phoneNum)){
return p;
}
p=p->next;
}while(p);
return NULL;
}
void manageField(){ //显示场地管理菜单
int tmp,tmp2;
char input[50];
field* _TEMP;
system("cls");
printf("\t\t\t****************************************\t\t\t\n");
printf("\t\t\t\t1.新增场馆\n");
printf("\t\t\t\t2.修改场馆\n");
printf("\t\t\t\t3.删除场馆\n");
printf("\t\t\t\t4.查询指定场馆信息\n");
printf("\t\t\t\t0.返回主菜单\n");
printf("\t\t\t****************************************\t\t\t\n");
printf("\n请选择要执行的操作:");
scanf("%d",&tmp);
switch(tmp){
case 1:newField();break;
case 2:
printf("请输入修改场馆原名\n不输入直接回车返回主菜单\n");
getchar();gets(input);
if(!input[0]){
return;
}
system("cls");
if(_TEMP=selectFieldByName(input)){
changeField(_TEMP);
}else{
printf("抱歉,未能找到名称为\"%s\"的场馆\n",input);
system("pause");
return;
}
break;
case 3:
printf("请输入要删除的场馆原名\n不输入直接回车返回主菜单\n");
getchar();gets(input);
if(!input[0]){
return;
}
system("cls");
if(_TEMP=selectFieldByName(input)){
deleteField(_TEMP);
}else{
printf("抱歉,未能找到名称为\"%s\"的场馆\n",input);
system("pause");
return;
}
break;
case 4:
printf("请输入场馆名字\n不输入直接回车返回主菜单\n");
getchar();gets(input);
if(!input[0]){
return;
}
system("cls");
if(_TEMP=selectFieldByName(input)){
showField(_TEMP);
}else{
printf("抱歉,未能找到名称为\"%s\"的场馆\n",input);
system("pause");
return;
}
break;
}
}
void manageVolunteer(){ //显示志愿者管理菜单
int tmp,tmp2;
char input[50];
volunteer* _TEMP;
system("cls");
printf("\t\t\t****************************************\t\t\t\n");
printf("\t\t\t\t1.新增志愿者\n");
printf("\t\t\t\t2.修改志愿者\n");
printf("\t\t\t\t3.删除志愿者\n");
printf("\t\t\t\t4.查询指定志愿者信息\n");
printf("\t\t\t\t0.返回主菜单\n");
printf("\t\t\t****************************************\t\t\t\n");
printf("\n请选择要执行的操作:");
scanf("%d",&tmp);
switch(tmp){
case 1:newVolunteer();break;
case 2:
printf("请输入修改志愿者学号\n不输入直接回车返回主菜单\n");
getchar();gets(input);
if(!input[0]){
return;
}
system("cls");
if(_TEMP=selectVolunteerByIdNum(input)){
changeVolunteer(_TEMP);
}else{
printf("抱歉,未能找到学号为\"%s\"的志愿者\n",input);
system("pause");
return;
}
break;
case 3:
printf("请输入要删除的志愿者学号\n不输入直接回车返回主菜单\n");
getchar();gets(input);
if(!input[0]){
return;
}
system("cls");
if(_TEMP=selectVolunteerByIdNum(input)){
deleteVolunteer(_TEMP);
}else{
printf("抱歉,未能找到学号为\"%s\"的志愿者\n",input);
system("pause");
return;
}
break;
case 4:
printf("请输入志愿者学号\n不输入直接回车返回主菜单\n");
getchar();gets(input);
if(!input[0]){
return;
}
system("cls");
if(_TEMP=selectVolunteerByIdNum(input)){
showVolunteer(_TEMP);
}else{
printf("抱歉,未能找到学号为\"%s\"的志愿者\n",input);
system("pause");
return;
}
break;
}
}
void newField(){
char input[100];
char temp[10][50];
char* temp2;
int i;
field* p=_FIELD;
printf("请输入要新建场馆的名字,开始时间,持续时间,需要志愿者人数,用英文半角逗号\",\"来隔开\n直接输入0并回车退出新增场馆\n请输入\n\t");
//scanf("%s",input);
getchar();gets(input);
if(input[0]=='0'){
printf("输入完毕!\n");
system("pause");
return ;
}
temp2=strtok(input,",");
if(!temp2){
printf("输入有误!");
system("pause");
return ;
}
strcpy(temp[0],temp2);
for(i=1;i<4;i++){ temp2=strtok(NULL,","); if(!temp2){ printf("输入有误!"); system("pause"); return ; } strcpy(temp[i],temp2); } if(selectFieldByName(temp[0])){ printf("已存在名字为\"%s\"的同名场馆,请重新输入!\n",temp[0]); system("pause"); return ; } i=1; while(p->next){
i++;
p=p->next;
}
p->next=(field*)malloc(sizeof(field));
p->next->head=p;
p->next->next=NULL;
p->next->fieldId=i;
strcpy(p->next->fieldName,temp[0]);
strcpy(p->next->startTime,temp[1]);
memset(p->next->joinedVolunteer,0,sizeof(_FIELD->joinedVolunteer));
p->next->lastTime=atoi(temp[2]);
p->next->maxVolunteer=atoi(temp[3]);
saveFile();
printf("新增场馆成功!\n\n\t场馆名:%s\n\t开始时间:%s\n\t持续时间:%d\n\t需要志愿者人数:%d\n\n",temp[0],temp[1],atoi(temp[2]),atoi(temp[3]));
system("pause");
}
void newVolunteer(){
char input[100];
char temp[10][50];
char* temp2;
int i;
volunteer* p=_VOLUNTEER;
printf("请输入要添加志愿者的名字,学号,手机号,用英文半角逗号\",\"来隔开\n直接输入0并回车退出新增志愿者\n请输入\n\t");
//scanf("%s",input);
getchar();gets(input);
if(input[0]=='0'){
printf("输入完毕!\n");
system("pause");
return ;
}
temp2=strtok(input,",");
if(!temp2){
printf("输入有误!");
system("pause");
return ;
}
strcpy(temp[0],temp2);
for(i=1;i<3;i++){ temp2=strtok(NULL,","); if(!temp2){ printf("输入有误!"); system("pause"); return ; } strcpy(temp[i],temp2); } if((selectVolunteerByIdNum(temp[1]))||(selectVolunteerByPhoneNum(temp[2]))){ printf("已存在学号为\"%s\"或手机号为\"%s\"的志愿者,请重新输入!\n",temp[1],temp[2]); system("pause"); return ; } i=1; while(p->next){
i++;
p=p->next;
}
p->next=(volunteer*)malloc(sizeof(volunteer));
p->next->head=p;
p->next->next=NULL;
p->next->volunteerId=i;
strcpy(p->next->volunteerName,temp[0]);
strcpy(p->next->idNum,temp[1]);
strcpy(p->next->phoneNum,temp[2]);
memset(p->next->joinedField,0,sizeof(_VOLUNTEER->joinedField));
p->next->serviceTime=0;
saveFile();
printf("新增志愿者成功!\n\n\t志愿者名:%s\n\t学号:%s\n\t手机号:%s\n\n",temp[0],temp[1],temp[2]);
system("pause");
}
void changeField(field* p){
int temp;
char input[50];
system("cls");
printf("当前场馆信息:\n");
printf("\t场馆名称:%s\t开始时间:%s\t持续时间:%d\t需求志愿者数量:%d\n",p->fieldName,p->startTime,p->lastTime,p->maxVolunteer);
printf("请选择要修改项目:\n\t1.名称\n\t2.开始时间\n\t3.持续时间\n\t4.需求志愿者数量\n\t0.返回主界面");
scanf("%d",&temp);
switch(temp)
{
case 1:
printf("原数值:%s\n请输入新的值,直接回车取消修改:",p->fieldName);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
if(selectFieldByName(input)){
printf("已存在名称为: %s 的场馆,请更换名称",input);
system("pause");
return;
}
strcpy(p->fieldName,input);
printf("已将场馆名称修改为:%s\n",input);
system("pause");
break;
case 2:
printf("原数值:%s\n请输入新的值,直接回车取消修改:",p->startTime);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
strcpy(p->startTime,input);
printf("已将开始时间修改为:%s\n",input);
system("pause");
break;
case 3:
printf("原数值:%d\n请输入新的值,直接回车取消修改:",p->lastTime);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
p->lastTime=atoi(input);
printf("已将持续时间修改为:%d\n",atoi(input));
system("pause");
break;
case 4:
printf("原数值:%d\n请输入新的值,直接回车取消修改:",p->maxVolunteer);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
p->maxVolunteer=atoi(input);
printf("已将需要志愿者数量修改为:%d\n",atoi(input));
system("pause");
break;
default:return;
}
saveFile();
}
void changeVolunteer(volunteer* p){
int temp;
char input[50];
system("cls");
printf("当前志愿者信息:\n");
printf("\t姓名:%s\t学号:%s\t手机号:%s\n",p->volunteerName,p->idNum,p->phoneNum);
printf("请选择要修改项目:\n\t1.姓名\n\t2.学号\n\t3.手机号\n\t0.返回主界面");
scanf("%d",&temp);
switch(temp)
{
case 1:
printf("原数值:%s\n请输入新的值,直接回车取消修改:",p->volunteerName);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
strcpy(p->volunteerName,input);
printf("已将志愿者姓名修改为:%s\n",input);
system("pause");
break;
case 2:
printf("原数值:%s\n请输入新的值,直接回车取消修改:",p->idNum);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
if(selectVolunteerByIdNum(input)){
printf("已存在学号为: %s 的志愿者,修改失败",input);
system("pause");
return;
}
strcpy(p->idNum,input);
printf("已将学号修改为:%s\n",input);
system("pause");
break;
case 3:
printf("原数值:%s\n请输入新的值,直接回车取消修改:",p->phoneNum);
getchar();gets(input);
if(!input[0]){
printf("取消修改\n");
system("pause");
return;
}
strcpy(p->phoneNum,input);
printf("已将志愿者手机号修改为:%s\n",input);
system("pause");
break;
default:return;
}
saveFile();
}
void deleteField(field* p){ //删除指定场馆
int id,i;
char temp1;
field *p1,*p2;
volunteer *p3;
id=p->fieldId;
system("cls");
printf("当前场馆信息:\n");
printf("\t场馆名称:%s\t开始时间:%s\t持续时间:%d\t需求志愿者数量:%d\n",p->fieldName,p->startTime,p->lastTime,p->maxVolunteer);
printf("请确认是否要删除!(Y/N)");
scanf("%c",&temp1);
if(temp1!='Y'){
printf("取消删除!\n");
system("pause");
return;
}
//删除所有志愿者中此场馆的注册记录并减少相应志愿时长
for(p3=_VOLUNTEER->next;p3;p3=p3->next){
for(i=0;p3->joinedField[i];i++){
if(p3->joinedField[i]==id){
p3->serviceTime-=p->lastTime;
if(!p3->joinedField[i+1]){
p3->joinedField[i]=0;
}else{
for(;p3->joinedField[i+1];i++){
p3->joinedField[i]=p3->joinedField[i+1];
}
p3->joinedField[i]=0;
}
break;
}
}
}
p1=p->head,p2=p->next;
if(p2){
p1->next=p2;
p2->head=p1;
free(p);
}else{
p1->next=NULL;
free(p);
}
saveFile();
printf("删除成功!\n");
system("pause");
return;
}
void deleteVolunteer(volunteer* p){ //删除指定志愿者
int id,i;
char temp1;
volunteer *p1,*p2;
field *p3;
id=p->volunteerId;
system("cls");
printf("当前志愿者信息:\n");
printf("\t姓名:%s\t学号:%s\t手机号:%d\n",p->volunteerName,p->idNum,p->phoneNum);
printf("请确认是否要删除!(Y/N)");
scanf("%c",&temp1);
if(temp1!='Y'){
printf("取消删除!\n");
system("pause");
return;
}
//删除所有场馆中此志愿者的注册记录
for(p3=_FIELD->next;p3;p3=p3->next){
for(i=0;p3->joinedVolunteer[i];i++){
if(p3->joinedVolunteer[i]==id){
if(!p3->joinedVolunteer[i+1]){
p3->joinedVolunteer[i]=0;
}else{
for(;p3->joinedVolunteer[i+1];i++){
p3->joinedVolunteer[i]=p3->joinedVolunteer[i+1];
}
p3->joinedVolunteer[i]=0;
}
break;
}
}
}
p1=p->head,p2=p->next;
if(p2){
p1->next=p2;
p2->head=p1;
free(p);
}else{
p1->next=NULL;
free(p);
}
saveFile();
printf("删除成功!\n");
system("pause");
return;
}
void showField(field* p){ //根据id显示场馆信息
int i;
volunteer* p1;
printf("\n场馆信息:\n");
printf("\n\t场馆id\t场馆名字\t\t开始时间\t持续时间\t最大志愿者人数\n");
printf("\t%d\t%s\t\t\t%s\t\t%d\t\t%d\n",p->fieldId,p->fieldName,p->startTime,p->lastTime,p->maxVolunteer);
printf("\n场馆已加入志愿者名单:\n");
printf("\t志愿者id\t志愿者姓名\t志愿者学号\t志愿者手机号\t\t志愿服务时长\n");
for(i=0;p->joinedVolunteer[i];i++){
p1=selectVolunteerById(p->joinedVolunteer[i]);
printf("\t%d\t\t%s\t\t%s\t%s\t\t%d\n",p1->volunteerId,p1->volunteerName,p1->idNum,p1->phoneNum,p1->serviceTime);
}
printf("\n共%d个已加入志愿者\n",i);
system("pause");
}
void showVolunteer(volunteer* p){ //根据id显示志愿者信息
int i;
field* p1;
printf("\n\t志愿者id\t姓名\t\t学号\t手机号\t志愿服务时长\n");
printf("\t%d\t\t%s\t\t\t%s\t\t%s\t\t%d\n",p->volunteerId,p->volunteerName,p->idNum,p->phoneNum,p->serviceTime);
printf("\n该志愿者已加入的志愿服务场馆:\n");
printf("\t场馆id\t场馆名字\t\t开始时间\t\t持续时间\n");
for(i=0;p->joinedField[i];i++){
p1=selectFieldById(p->joinedField[i]);
printf("\t%d\t%s\t%s\t%s\t\t%d\n",p1->fieldId,p1->fieldName,p1->startTime,p1->lastTime);
}
printf("\n共%d个已加入志愿服务场馆\n",i);
system("pause");
}
void showAllField(){ //显示所有场馆信息
field* p=_FIELD->next;
int i;
printf("\t场地id\t场地名字\t\t开始时间\t持续时间\t最大志愿者人数\n");
for(i=0;p;p=p->next,i++){
printf("\t%d\t%s\t\t\t%s\t\t%d\t\t%d\n",p->fieldId,p->fieldName,p->startTime,p->lastTime,p->maxVolunteer);
}
printf("\n共%d个场馆数据\n",i);
system("pause");
}
void showAllVolunteer(){ //显示所有志愿者信息
volunteer* p=_VOLUNTEER->next;
int i;
printf("\t志愿者id\t志愿者姓名\t志愿者学号\t志愿者手机号\t\t志愿服务时长\t\n");
for(i=0;p;p=p->next,i++){
printf("\t%d\t\t%s\t\t%s\t%s\t\t%d\n",p->volunteerId,p->volunteerName,p->idNum,p->phoneNum,p->serviceTime);
}
printf("\n共%d个志愿者数据\n",i);
system("pause");
}
void bind(){ //注册志愿活动
char temp1;
char input[100];
char temp[10][50];
char* temp2;
int i,j;
field* p1;
volunteer* p2;
system("cls");
printf("\t\t注册志愿活动\n");
printf("\t请分别输入活动场馆名字,志愿者姓名,志愿者学号,用英文半角逗号分隔\n退出注册输入0\n\t");
getchar();gets(input);
if(input[0]=='0'){
return ;
}
temp2=strtok(input,",");
if(!temp2){
printf("输入有误!");
system("pause");
return ;
}
strcpy(temp[0],temp2);
for(i=1;i<3;i++){
temp2=strtok(NULL,",");
if(!temp2){
printf("输入有误!");
system("pause");
return ;
}
strcpy(temp[i],temp2);
}
if(p2=selectVolunteerByIdNum(temp[2])){
if(p2==selectVolunteerByName(temp[1])){
if(p1=selectFieldByName(temp[0])){}else{
printf("未找到名字为%s的场馆信息\n",temp[0]);
system("pause");
return;
}
}else{
printf("学号为%s的志愿者信息与姓名%s不对应\n",temp[2],temp[1]);
system("pause");
return;
}
}else{
printf("未找到学号为%s的志愿者信息\n",temp[2]);
system("pause");
return;
}
for(i=0;imaxVolunteer;i++){
if(p1->joinedVolunteer[i]==p2->volunteerId){
printf("该志愿者已加入该场活动,不能重复添加\n");
system("pause");
return;
}
if(!p1->joinedVolunteer[i]){
break;
}
}
if(!(p1->maxVolunteer-i)){
printf("该场馆服务名额已满!");
system("pause");
return;
}
for(j=0;j<sizeof(_VOLUNTEER->joinedField)/sizeof(int);j++){
if(p2->joinedField[i]==p1->fieldId){
printf("该志愿者已加入该场活动,不能重复添加\n");
system("pause");
return;
}
if(!p2->joinedField[j]){
break;
}
}
if(!(sizeof(_VOLUNTEER->joinedField)/sizeof(int)-j)){
printf("该志愿者已达到志愿服务数量上限!");
system("pause");
return;
}
printf("\n场馆信息:\n\t场馆ID:%d\n\t场馆名字:%s\n\t开始时间:%s\n\t持续时间:%d\n\t剩余志愿者名额:%d\n",p1->fieldId,p1->fieldName,p1->startTime,p1->lastTime,p1->maxVolunteer-i);
printf("\n志愿者信息:\n\t志愿者ID:%d\n\t志愿者姓名:%s\n\t学号:%s\n\t手机号:%s\n\t已进行志愿服务时间:%d\n\t剩余最大志愿服务数量:%d\n",p2->volunteerId,p2->volunteerName,p2->idNum,p2->phoneNum,p2->serviceTime,sizeof(_VOLUNTEER->joinedField)/sizeof(int)-j);
printf("\n\t是否确认要注册该志愿活动?(Y/N)\n");
scanf("%c",&temp1);
if(temp1!='Y'){
printf("取消注册!\n");
system("pause");
return;
}
p1->joinedVolunteer[i]=p2->volunteerId;
p2->joinedField[j]=p1->fieldId;
p2->serviceTime=p2->serviceTime+p1->lastTime;
saveFile();
printf("注册成功!\n");
system("pause");
}
void unbind(){ //注销志愿活动
char temp1;
char input[100];
char temp[10][50];
char* temp2;
int i,j,m,n,q;
field* p1;
volunteer* p2;
system("cls");
printf("\t\t注销志愿活动\n");
printf("\t请分别输入活动场馆名字,志愿者姓名,志愿者学号,用英文半角逗号分隔\n退出注销输入0\n\t");
getchar();gets(input);
if(input[0]=='0'){
return ;
}
temp2=strtok(input,",");
if(!temp2){
printf("输入有误!");
system("pause");
return ;
}
strcpy(temp[0],temp2);
for(i=1;i<3;i++){
temp2=strtok(NULL,",");
if(!temp2){
printf("输入有误!");
system("pause");
return ;
}
strcpy(temp[i],temp2);
}
if(p2=selectVolunteerByIdNum(temp[2])){
if(p2==selectVolunteerByName(temp[1])){
if(!(p1=selectFieldByName(temp[0]))){
printf("未找到名字为%s的场馆信息\n",temp[0]);
system("pause");
return;
}
}else{
printf("学号为%s的志愿者信息与姓名%s不对应\n",temp[2],temp[1]);
system("pause");
return;
}
}else{
printf("未找到学号为%s的志愿者信息\n",temp[2]);
system("pause");
return;
}
for(i=0,m=-1;imaxVolunteer;i++){
if(p2->volunteerId==p1->joinedVolunteer[i]){
m=i;
}
}
if(m<0){
printf("该志愿者未加入该场活动,无法注销\n");
system("pause");
return;
}
for(j=0,n=-1;j<sizeof(_VOLUNTEER->joinedField)/sizeof(int);j++){
if(p1->fieldId==p2->joinedField[j]){
n=j;
}
}
if(n<0){
printf("该志愿者未加入该场活动,无法注销\n");
system("pause");
return;
}
for(;m<i;m++){ p1->joinedVolunteer[m]=p1->joinedVolunteer[m+1];
}
p1->joinedVolunteer[m]=0;
for(;n<j;n++){ p2->joinedField[n]=p2->joinedField[n+1];
}
p2->joinedField[m]=0;
p2->serviceTime=p2->serviceTime-p1->lastTime;
saveFile();
printf("注销成功!");
system("pause");
}
void findOutTopVolunteer(){ //寻找最美志愿者
int longestTime=0;
int i,n;
volunteer *p1;
volunteer *np[10];
memset(np,0,10*sizeof(volunteer*));
system("cls");
for(p1=_VOLUNTEER->next;p1;p1=p1->next){
if(longestTime==p1->serviceTime){
for(i=0;np[i];i++);
np[i]=p1;
}
if(longestTimeserviceTime){
longestTime=p1->serviceTime;
memset(np,0,sizeof(np));
np[0]=p1;
}
}
for(n=0;np[n];n++);
printf("共有%d个“最美志愿者”\n\n志愿服务时长为:%d分钟\n\n",n,longestTime);
for(i=0;i<n;i++){ printf("\t姓名:%s\t学号:%s\t手机号:%s\n",np[i]->volunteerName,np[i]->idNum,np[i]->phoneNum);
}
system("pause");
}
void filePrintMenu(){ //格式化输出文件菜单
int step1=0,step2=0,choose=0,outputType=0,inttmp1;
char outputPath[256],temp[256],input[256];
memset(input,0,sizeof(input));
while(1){
system("cls");
printf("\t\t格式化输出文件\n\n");
printf("\t当前已完成设置项:\n");
if(step1){
printf("\t\t1.输出路径:%s\t√\n",outputPath);
}else{
printf("\t\t1.输出路径\t×\n");
}
if(step2){
printf("\t\t2.输出数据:");
switch(outputType){
case 1:printf("志愿者信息");break;
case 2:printf("场馆信息");break;
case 3:printf("志愿时长排名");break;
}
printf("\t√\n");
}else{
printf("\t\t2.输出数据\t×\n");
}
if((step1+step2)==2){
printf("\n\t3.开始输出\n");
}
printf("\n\n请选择配置项,输入0退出:");
scanf("%d",&choose);
switch(choose){
case 0:
return;
case 1:
printf("请输入文件的输出位置(包含文件名)\n若输入0则直接在程序所在目录输出\"output.txt\"");
getchar();gets(input);
if(input[0]=='0'){
strcpy(input,"output.txt");
}
printf("输出位置:%s\n\t请确认是否设置此地址(Y/N)",input);
if('Y'==getchar()){
strcpy(outputPath,input);
step1=1;
memset(input,0,sizeof(input));
printf("已设置输出地址!\n");
system("pause");
}else{
memset(input,0,sizeof(input));
system("pause");
}
break;
case 2:
printf("请输入要输出的数据:\n\t1.志愿者信息\n\t2.场馆信息\n");
scanf("%d",&inttmp1);
if((inttmp1>=0)&&(inttmp1<=2)){ outputType=inttmp1; step2=1; }else{ printf("输入有误!\n"); system("pause"); } break; case 3: if((step1+step2)==2){ outputFile(outputPath,outputType); printf("输出完成!\n"); system("pause"); return; }else{ printf("您还未完成所有配置,不能输出\n"); } break; default: printf("输入有误!\n");system("pause");continue; } } } void outputFile(char* outputPath,int outputType){ int i; FILE *fp; volunteer *p1; field *p2; if(fp=fopen(outputPath,"r")){ printf("指定的路径已存在文件!覆盖(Y)或取消输出(N)?\n"); getchar();if(getchar()!='Y'){ fclose(fp); printf("取消输出\n"); system("pause"); return; } } fp=fopen(outputPath,"w"); switch(outputType){ case 1: fprintf(fp,"志愿者信息\n%-20s%-40s%-30s%s","姓名","学号","手机号","服务时长(分钟)\n"); for(p1=_VOLUNTEER->next;p1;p1=p1->next){
fprintf(fp,"\n%-20s%-40s%-30s%-10d\n",p1->volunteerName,p1->idNum,p1->phoneNum,p1->serviceTime);
if(p1->joinedField[0]){
fprintf(fp,"\t注册志愿服务的场馆:\n");
for(i=0;p1->joinedField[i];i++){
fprintf(fp,"\t\t\t%s\n",selectFieldById(p1->joinedField[i])->fieldName);
}
}
}
break;
case 2:
fprintf(fp,"场馆信息\n%-20s%-20s%-20s%s","名字","开始时间","持续时间(分钟)","最大志愿者人数\n");
for(p2=_FIELD->next;p2;p2=p2->next){
fprintf(fp,"\n%-20s%-20s%-20d%-10d\n",p2->fieldName,p2->startTime,p2->lastTime,p2->maxVolunteer);
if(p2->joinedVolunteer[0]){
fprintf(fp,"\t注册志愿服务的志愿者(学号):\n");
for(i=0;p2->joinedVolunteer[i];i++){
p1=selectVolunteerById(p2->joinedVolunteer[i]);
fprintf(fp,"\t\t\t%s(%s)\n",p1->volunteerName,p1->idNum);
}
}
}
break;
}
fprintf(fp,"\n\t\t@军运会管理系统");
fclose(fp);
}
void showMenu(){
system("cls");
printf("\t\t\t****************************************\t\t\t\n");
printf("\t\t\t\t1.场馆管理\n");
printf("\t\t\t\t2.志愿者管理\n");
printf("\t\t\t\t3.列出场馆信息\n");
printf("\t\t\t\t4.列出已注册志愿者\n");
printf("\t\t\t\t5.注册志愿活动\n");
printf("\t\t\t\t6.注销志愿活动\n");
printf("\t\t\t\t8.格式化输出文件至指定目录\n");
printf("\t\t\t\t9.寻找最美志愿者\n");
printf("\t\t\t\t0.退出程序\n");
//printf("\t\t\tPS:调试阶段为防止数据错误已关闭自动保存至文件,如需保存在主菜单输入22后即可保存\n");
printf("\t\t\t****************************************\t\t\t\n");
}
//主函数
int main(){
int tmp;
startUp();
while(1){
showMenu();
printf("\t请输入要执行的操作:");
scanf("%d",&tmp);
switch(tmp)
{
case 0:exit(0);break;
case 1:manageField();break;
case 2:manageVolunteer();break;
case 3:showAllField();break;
case 4:showAllVolunteer();break;
case 5:bind();break;
case 6:unbind();break;
case 8:filePrintMenu();break;
case 9:findOutTopVolunteer();break;
/*case 21:readFile();break;
case 22:saveFile();break;*/
default:system("cls");printf("输入有误!");system("pause");
}
}
return 0;
}
看完了还不点个赞评个论分个享打个赏啥的嘛~