目录
(六)计算余额模块Suan_Qian(int dif,int k);
(3)调用建立新档案函数,如图所示输入学号、姓名、密码、班级、金额
第1部分 实训题目与要求
1. 问题提出
为了便于管理,需要对机房的上机收费进行计算机管理,所需要的功能为:建立学生的上机档案、对于毕业的学生能够删除其档案、根据上机和下机时间计算出本次所需费用、能够续钱。
2. 功能要求
循环显示如图6所示的主菜单。
在主菜单中选择1:建立名为duli16.3.dat的文件,并在其中添加若干学生的上机档案,信息包括学号、姓名、金额,要求学号是唯一的。
在主菜单中选择2:添加新档案,这时要求新学号和已有的学号不能重号。
在主菜单中选择3:注销旧档案。
在主菜单中选择4:要求用户输入学号,然后系统显示该学生档案,并自动开始计时(计时方法采用下述方法),如果原来余额不足6元,则不能上机,而且显示“余额不够,请续钱!”。
计时方法:分别用系统提供的库函数time记录开始和结束的时间,比如start=time(NULL)和end=time(NULL),其中start和end是系统已声明的名为time_t的结构体类型,在程序中使用变量start和end前必须用“time_t start, end;”定义。difftime(end, start)函数返回以秒为单位的两个时间差,其返回类型是double型。可用dif=(int)difftime(end, start)使得整形变量dif得到时间差,再用dif/3600、dif%3600/60、dif%60分别计算时、分、秒。使用time_t类型或调用time和difftime函数时需要加命令行“#include <time.h>”,调用time函数时还需要加命令行“#include <stdio.h>”。
在主菜单中选择5:停止对该学生计时,同时根据用户输入的学号,计算该学生上机时间,并按1小时2元收费(30分钟以内按半小时处理,60分钟以内按1小时处理),然后显示上机前后的金额。
在主菜单中选择6:要求用户输入学号和续钱额,续钱完成后分别显示续钱前后的金额。
在主菜单中选择7:此项功能学生自由发挥,根据本组爱好增加与本题目相关的新功能。
在主菜单中选择0:显示结束信息(如“感谢使用本软件!已正常退出,按任意键结束。”),按任意键后,退出本功能。
……………………………
.请输入选项编号(0 ~7):.
……………………………
. 1——建立上机档案 .
. 2——添加新档案 .
. 3——注销旧档案 .
. 4——开始上机 .
. 5——离开机房 .
. 6——续钱 .
. 7——创新功能(可选) .
. 0——退出系统 .
……………………………
图6 机房收费管理主菜单
3. 任务分工
负责编写:
建立上机档案函数create();
添加新档案函数add();
注销旧档案函数cancel();
上机函数up();
结算金额函数Suan_Qian(int dif,int k);
续钱函数top_up();
创新功能函数innovate();
创新功能:查询余额函数inquiry();
创新功能:修改密码函数mod();
创新功能:显示所有学生函数XianShi();
主函数Main();
第2部分 设计实训题目功能
1. 总体设计
建立上机档案create(); 添加新档案add(); 注销旧档案cancel();
开始上机up(); 计算余额Suan_Qian(int dif,int k); 续钱top_up();
创新功能innovate();
查询余额inquiry(); 修改密码mod(); 显示所有学生XianShi();
2. 算法设计
(一)主函数模块
(二)建立新档案模块create();
(三)新增档案模块add();
(四)注销旧档案模块cancel();
(五)上机模块up();
(六)计算余额模块Suan_Qian(int dif,int k);
(七)续钱模块top_up();
(八)创新功能模块innovate();
3. 数据结构
struct student
{
char num[15]; /*学号*/
char name[20]; /*姓名*/
char mima[15];/*密码*/
char clas[20]; /*班级*/
int money;//余额
} stu[50],st[50]; //先定义50名,后续可修改数据
4. 程序代码设计
(一)主函数
用于主要代码组成
int main(){
char chose='\0',yes_no='\0';
int flag=0;
int y=1;
int dif=0,k;
time_t start_t,end_t;
do{
menu();
printf("请选择输入选项编号\n");
scanf("%c",&chose);
getchar();
switch(chose){
case '1':
create();
break;
case '2':
add();
getchar();
break;
case '3':
cancel();
break;
case '4':
flag=up();
getchar();
if(flag!=0){
time(&start_t);
}
break;
case '5':
if(flag!=0&&y==1){
time(&end_t);
printf("下机成功!!!下机时间为:%s祝您愉快!\n",ctime(&end_t));
k=flag-1;
dif=(int)difftime(end_t,start_t);
Suan_Qian(dif,k);
flag=0;
}
else printf("您还没上机呢?\n");
break;
case '6':
top_up();
getchar();
break;
case '7':
innovate();
break;
case '0':
printf("感谢使用本软件!已正常退出,按任意键结束。");
getchar();
exit(0);
default :printf("输入错误,%c不在选项中\n",chose);
}
printf("\n");
for(;;){
printf("是否返回主菜单?(Y/N)\n");
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("输入错误!%c不是Y/N,请重新输入......\n",yes_no);
}
}while(yes_no=='Y'||yes_no=='y');
return 0;
}
(二)建立新档案函数
用于创建新档案
void create(){
int i=1,k=-1,a=1;
FILE *fp=NULL;
char yes_no='\0';
system("cls");
fp=fopen("d:\\duli16.3.txt","w");
if(fp==NULL){
printf("\n打开文件失败!按任意键继续......\n");
getchar();
return;
}
else {
do{
printf("\n请输入第%d个记录:\n\n",i);
printf("学号:\n");
scanf("%s",stu[i].num);
for(a=1;a<i;a++){
if(strcmp(stu[a].num,stu[i].num)==0){
k=a;
printf("学号重复!!!\n按任意键继续......");
break;
}
}
if(k!=-1)return;
printf("姓名:\n");
scanf("%s",stu[i].name);
printf("密码:\n");
scanf("%s",stu[i].mima);
printf("班级:\n");
scanf("%s",stu[i].clas);
printf("金额:\n");
scanf("%d",&stu[i].money);
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
i++;
printf("\n请问还要再创建上机档案吗?Y/N\n");
getchar();
for(;;){
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("您输入信息有误!请问是否继续创建上机档案!Y/N\n");
}
}while(yes_no=='Y'||yes_no=='y');
fclose(fp);
}
}
(三)添加新档案函数
用于添加新档案,添加学号、姓名、密码、班级、金额
void add(){
int i=1,o=0,k=-1,a=0,b=0;
FILE *fp=NULL;
char yes_no='\0',s[15];
system("cls");
fp=fopen("d:\\duli16.3.txt","r");
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",st[a].num,st[a].name,st[a].mima,st[a].clas,&st[a].money);
a++;
}
fclose(fp);
fp=fopen("d:\\duli16.3.txt","a");
if(fp==NULL){
printf("\n文件丢失!按任意键继续......\n");
getchar();
return;
}
else {
do{
printf("\n请输入第%d个要添加的新档案\n",i);
printf("学号:");
scanf("%s",stu[i].num);
for(b=1;b<i;b++){
if(strcmp(stu[b].num,stu[i].num)==0){
k=b;
printf("新学号与已有学号重复!按任意键继续......\n");
break;
}
}
if(k!=-1)return;
for(b=0;b<a;b++){
if(strcmp(stu[i].num,st[b].num)==0){
k=b;
printf("新学号与已有学号重复!按任意键继续......\n");
break;
}
}
if(k!=-1)return;
printf("姓名:");
scanf("%s",stu[i].name);
printf("密码:");
scanf("%s",stu[i].mima);
printf("班级:");
scanf("%s",stu[i].clas);
printf("金额:");
scanf("%d",&stu[i].money);
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
i++;
getchar();
for(;;){
printf("请问还要继续添加吗?Y/N\n");
scanf("%c",&yes_no);
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
}
}while(yes_no=='Y'||yes_no=='y');
}
fclose(fp);
}
(四)删除旧档案
用于删除旧档案,删除已经毕业学生的档案,删除旧学号、姓名、密码、班级、金额。
void cancel(){
char s[15];
int o=0,k=-1,i=0;
char yes_no='\0';
FILE *fp=NULL;
do{
o=0;
k=-1;
printf("\n请输入要删除档案的学号:\n");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
if(k==-1){
system("cls");
printf("\n查无此人!请重新输入......\n");
cancel();
}
else{
for(i=k;i<o-1;i++){
strcpy(stu[i].name,stu[i+1].name);
strcpy(stu[i].clas,stu[i+1].clas);
strcpy(stu[i].mima,stu[i+1].mima);
strcpy(stu[i].num,stu[i+1].num);
stu[i].money=stu[i+1].money;
}
fp=fopen("d:\\duli16.3.txt","w");
for(i=0;i<o-2;i++){
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
}
fclose(fp);
printf("删除成功!\n");
}
getchar();
for(;;){
printf("是否继续删除?Y/N\n");
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("%c不是Y/N,是否继续删除?\n");
}
}while(yes_no=='Y'||yes_no=='y');
}
(五)上机函数
用于上机记录,显示时间等
int up(){
time_t start;
struct tm *t;
int flag=0;
int o=0,k=-1,i=0,j=-1;
char s[15],m[15];
char yes_no='\0';
FILE *fp=NULL;
printf("请输入上机学号\n");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!!!");
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
fclose(fp);
if(k==-1){
system("cls");
printf("查无此人!请重新输入......\n");
up();
}
else{
printf("请输入密码:\n");
scanf("%s",m);
if(strcmp(stu[k].mima,m)==0){
if(stu[k].money>=6){
printf("上机成功!欢迎使用!\n");
start=time(NULL);
t=localtime(&start);
printf("上机成功时间为:%s\n",asctime(t));
flag=k;
printf("学号:%s\t姓名:%s\t班级:%s\t余额:%d\n",stu[k].num,stu[k].name,stu[k].clas,stu[k].money);
}
else {
printf("\n您的余额不足!如需充值?请返回主菜单选择充值......\n");
}
}
else{
system("cls");
printf("密码错误!请重新输入上机学号:\n");
up();
}
return flag+1;
}
}
(六)计算余额函数
用于下机显示时间,计算余额,结算等
void Suan_Qian(int dif,int k){
int hour,min;
int money;
int o=0,i=0;
hour=dif/3600;
min=dif%3600/60;
if(min>30){
hour++;
min=0;
}
money=2*hour+min;
FILE *fp=NULL;
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("上机前余额为:%d\n",stu[k].money);
stu[k].money=stu[k].money+money;
printf("上机后余额为:%d\n",stu[k].money);
fp=fopen("d:\\duli16.3.txt","w");
for(i=0;i<o;i++){
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
i++;
}
fclose(fp);
}
(七)续钱函数
用于充钱,显示前后余额
void top_up(){
int o=0,k=-1,i=0,j=0,cmoney=0;
char s[15];
char yes_no='\0';
FILE *fp=NULL;
printf("请输入要充值的学号:");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[i].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
if(k==-1){
system("cls");
printf("查无此人!请重新输入......");
top_up();
}
else{
printf("请输入充值金额:");
scanf("%d",&cmoney);
fp=fopen("d:\\duli16.3.txt","r");
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d\n",stu[j].num,stu[j].name,stu[j].mima,stu[j].clas,&stu[j].money);
j++;
}
fclose(fp);
printf("续钱钱的金额为:%d\n",stu[k].money);
stu[k].money=stu[k].money+cmoney;
printf("续钱后的金额为:%d\n",stu[k].money);
printf("学号:%s\t姓名:%s\t班级:%s\t余额:%d\n",stu[k].num,stu[k].name,stu[k].clas,stu[k].money);
fp=fopen("d:\\duli16.3.txt","w");
for(k=0;k<j;k++){
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[k].num,stu[k].name,stu[k].mima,stu[k].clas,stu[k].money);
}
fclose(fp);
}
}
(八)创新功能函数
用于新功能设计
void innovate(){
char chose='\0',yes_no='\0';
do{
system("cls");
printf("---------------------\n");
printf("请输入选项编号(0~3)\n");
printf("---------------------\n");
printf("1——查询余额\n");
printf("2——修改密码\n");
printf("3——显示所有学生\n");
printf("0——返回主菜单\n");
printf("---------------------\n");
printf("\n");
scanf("%c",&chose);
getchar();
switch(chose){
case '1':
inquiry();
break;
case '2':
mod();
break;
case '3':
XianShi();
break;
case '0':
printf("返回主菜单!\n");
return;
default :printf("\n%c为非法字符!\n",chose);
}
for(;;){
printf("\n是否返回菜单?Y/N\n");
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("输入错误!请重新输入......\n");
}
}while(yes_no=='Y'||yes_no=='y');
}
完整程序请参见附录A
5. 测试与调试
(1)主菜单出现如图所示
(2)输入错误编号出现如图所示
表1 主函数测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 输入正确编号
| 调用相应函数 | 调用相应函数 |
…… | …… | …… | |
非法数据 | 输入错误编号 | 提示“输入错误,不在选项中” | 提示“输入错误,不在选项中” |
…… | …… | …… |
(3)调用建立新档案函数,如图所示输入学号、姓名、密码、班级、金额
输入学号重复就会提示学号重复
表2 建立新档案测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 学号:11111 姓名:zhou 密码:11111 班级:1 金额:1111 | 输入的数据会存到指定文件中 | 输入的数据保存在指定文件中 |
…… | …… | …… | |
非法数据 | 学号输入重复 | 提示“学号重复!!!” | 提示“学号重复!!!” |
…… | …… | …… |
(4)调用添加新档案函数
如图所示输入学号不能与已有学号重复
表3 新增档案测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 学号:22222 姓名:wen 密码:22222 班级:2 金额:2222
| 输入相关数据储存到指定文件中 | 输入相关数据储存到指定文件中 |
…… | …… | …… | |
非法数据 | 输入学号与已有学号重复 | 提示“新学号与已有学号重复” | 提示“新学号与已有学号重复” |
…… | …… | …… |
(5)调用删除函数
若无此人,如图所示文件中没有此人
表4 注销旧档案测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 输入要删除的档案
| 旧档案被删除 | 旧档案被删除 |
…… | …… | …… | |
非法数据 | 输入的学号不在文件中 | 提示“查无此人” | 提示“查无此人” |
…… | …… | …… |
(6)调用上机函数
如图所示查无此人,文件中没有此学号
如图所示密码错误情况
如图所示余额不足情况图像
表5 上机测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 输入正确学号以及密码
| 提示“上机成功” 显示时间、学号姓名班级余额 | 提示“上机成功” 显示时间、学号姓名班级余额 |
…… | …… | …… | |
非法数据 | 输入学号和密码错误 | 提示“查无此人”及“密码错误” | 提示“查无此人”及“密码错误” |
…… | …… | …… |
(7)下机
如图所示没有上机就下机的图像
表6 下机测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 在已上机的前提下,下机
| 显示下机时间 上下机前后金额 | 显示下机时间 上下机前后金额 |
…… | …… | …… | |
非法数据 | 没有上机就下机 | 提示“您还没上机呢” | 提示“您还没上机呢” |
…… | …… | …… |
(8)调用续钱函数
文件中没有此人时,如图所示文件中没有此人图像
表7 充值测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 输入要充值的正确学号
| 修改文件中指定学号的金额信息 显示充值前后金额 显示学号、姓名、班级、余额 | 修改文件中指定学号的金额信息 显示充值前后金额 显示学号、姓名、班级、余额 |
…… | …… | …… | |
非法数据 | 输入学号错误 | 提示“查无此人!请重新输入” | 提示“查无此人!请重新输入” |
…… | …… | …… |
(9)调用创新功能函数
创新功能主菜单如图所示
调用查询函数如图所示
查询学号在文件中没有的情况图像
调用修改密码函数
要修改密码的学号不存在文件中的图像
调用显示全部学生信息函数图像
表8 创新功能测试用例
测试数据类型 | 测试数据 | 预期结果 | 实测结果 |
合法数据 | 输入正确的学号
| 按照输入编号 1、显示查询学号余额 2、修改密码成功 3、显示全部学生信息 | 按照输入编号 1、显示查询学号余额 2、修改密码成功 3、显示全部学生信息 |
…… | …… | …… | |
非法数据 | 输入错误学号 | 提示“查无此人” | 提示“查无此人” |
…… | …… | …… |
第3部分 实训总结
1. 个人总结
为期一学期一周两节课的C语言实训课已经到了尾声,给我的影响非常大,通过这次实训,使我明白C语言这门课程光仅仅听课是远远不够的,上机训练也不容忽视。
通过上机训练,我明白自己知识的不足,经历这次实训,使我更加深刻的理解C语言中的知识点。通过实训,我找到许多知识漏点,学到了很多以前不懂的知识,使知识更加牢固、深刻。
遇到自己当时不懂如何编写的题目时,经过自己的学习和同学的交流后,试遍、改代码、更正,最后也是很不容易的编写出来,虽然过程很艰辛,但带来的成就感也是增加对C语言的兴趣和学好C语言的信心。
下列总结C语言实训的几个重要作用:
1、加深对课堂讲授内容的理解
在课堂,C语言理论知识总是枯燥无味的,不容易记住,当然死记硬背也不是我们所提倡的,要真正去检验C语言的知识成果,实践是最好、最快的检验方法。通过多次上机练习,对于语法知识有了更深的理解,在理解的基础上就会自然而然地掌握C语言的语法规定。对于课堂上觉得已经听懂得知识,在实践实训中却错漏百出,这也是对自我的一次检测。
2、熟悉程序开发环境、学习计算机系统的操作方法
C语言程序从编写,到编译,最后到运行,都是在一定的外部操作环境下才能进行,所谓的“环境”就是所用的计算机系统硬件、软件系统,只有熟悉使用这些环境,才能进行程序开发工作。通过上机实践,熟悉掌握C语言开发环境,为以后编写更多计算机程序打下坚实的基础。
3、熟练上机调试程序
完成程序的编写,并不会一定编译成功,你以为万无一失的程序,最终还是会打一巴掌给你脸上,很少有人,却不排除有人可以一次写代码就成功的,实际上机运行操作会出现一堆错误、报错,经过多次修改,最终顺利运行。此次实训也学会、熟悉了上机调试程序,巩固学习知识面,具有不可替代的作用。
2. 结束语
此次实训工程非常感谢老师和同学们的热心指导,也感谢学校提供上机机会,同时也感谢其他各组给我的宝贵意见和不同的思考方式!时间过得很快,一学期也快过去,这段时间不仅巩固知识,也学会了以前不懂的知识,增强了信心,让我C语言学习更加信心。
附录A 程序清单
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#define N 200
void create(); //创建新档案函数
void add(); //添加新档案函数
void cancel(); //注销旧档案函数
int up(); //上机函数
void Suan_Qian(int dif,int k); //下机计算余额函数
void top_up(); //续钱函数
void innovate(); //创新功能函数
void inquiry(); //查询余额函数
void mod(); //修改密码函数
void XianShi(); //显示所有学生函数
struct student //定义结构体
{
char num[15]; /*学号*/
char name[20]; /*姓名*/
char mima[15];/*密码*/
char clas[20]; /*班级*/
int money;//余额
} stu[50],st[50]; //先定义50名,后续可修改数据
void menu(){ //主菜单目录
printf(" ……………………………\n");
printf(".请输入选项编号(0~7):.\n");
printf(" ……………………………\n");
printf(". 1——建立上机档案 .\n");
printf(". 2——添加新档案 .\n");
printf(". 3——注销旧档案 .\n");
printf(". 4——开始上机 .\n");
printf(". 5——离开机房 .\n");
printf(". 6——续钱 .\n");
printf(". 7——创新功能(可选) .\n");
printf(". 0——退出系统 .\n");
printf(" ……………………………\n");
}
void create(){ //创建新档案
int i=1,k=-1,a=1;
FILE *fp=NULL;
char yes_no='\0';
system("cls"); //清屏
fp=fopen("d:\\duli16.3.txt","w"); //打开文件
if(fp==NULL){
printf("\n打开文件失败!按任意键继续......\n");
getchar(); //吸收字符
return;
}
else {
do{
printf("\n请输入第%d个记录:\n\n",i);
printf("学号:\n");
scanf("%s",stu[i].num);
for(a=1;a<i;a++){
if(strcmp(stu[a].num,stu[i].num)==0){
k=a;
printf("学号重复!!!\n按任意键继续......");
getchar();
break;
}
}
if(k!=-1)return;
printf("姓名:\n");
scanf("%s",stu[i].name);
printf("密码:\n");
scanf("%s",stu[i].mima);
printf("班级:\n");
scanf("%s",stu[i].clas);
printf("金额:\n");
scanf("%d",&stu[i].money);
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
i++;
printf("\n请问还要再创建上机档案吗?Y/N\n");
getchar();
for(;;){ //确认是否继续
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("您输入信息有误!请问是否继续创建上机档案!Y/N\n");
}
}while(yes_no=='Y'||yes_no=='y');
fclose(fp); //关闭文件
}
}
void add(){ //添加新档案
int i=1,o=0,k=-1,a=0,b=0;
FILE *fp=NULL;
char yes_no='\0',s[15];
system("cls");
fp=fopen("d:\\duli16.3.txt","r");
while(feof(fp)==0){ //导入文件内容
fscanf(fp,"%s%s%s%s%d",st[a].num,st[a].name,st[a].mima,st[a].clas,&st[a].money);
a++;
}
fclose(fp);
fp=fopen("d:\\duli16.3.txt","a");
if(fp==NULL){
printf("\n文件丢失!按任意键继续......\n");
getchar();
return;
}
else {
do{
printf("\n请输入第%d个要添加的新档案\n",i);
printf("学号:");
scanf("%s",stu[i].num);
for(b=1;b<i;b++){
if(strcmp(stu[b].num,stu[i].num)==0){
k=b;
printf("新学号与已有学号重复!按任意键继续......\n");
getchar();
break;
}
}
if(k!=-1)return; //判断学号重复
for(b=0;b<a;b++){
if(strcmp(stu[i].num,st[b].num)==0){
k=b;
printf("新学号与已有学号重复!按任意键继续......\n");
getchar();
break;
}
}
if(k!=-1)return; //判断学号重复
printf("姓名:");
scanf("%s",stu[i].name);
printf("密码:");
scanf("%s",stu[i].mima);
printf("班级:");
scanf("%s",stu[i].clas);
printf("金额:");
scanf("%d",&stu[i].money);
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
i++;
getchar();
for(;;){ //判断是否继续
printf("请问还要继续添加吗?Y/N\n");
scanf("%c",&yes_no);
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
}
}while(yes_no=='Y'||yes_no=='y');
}
fclose(fp);
}
void cancel(){ //注销旧档案
char s[15];
int o=0,k=-1,i=0;
char yes_no='\0';
FILE *fp=NULL;
do{
o=0;
k=-1;
printf("\n请输入要删除档案的学号:\n");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!\n");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
if(k==-1){
system("cls");
printf("\n查无此人!请重新输入......\n");
cancel(); //查无此人,再次输入
}
else{
for(i=k;i<o-1;i++){ //删除环节,前一名被后一名覆盖
strcpy(stu[i].name,stu[i+1].name);
strcpy(stu[i].clas,stu[i+1].clas);
strcpy(stu[i].mima,stu[i+1].mima);
strcpy(stu[i].num,stu[i+1].num);
stu[i].money=stu[i+1].money;
}
fp=fopen("d:\\duli16.3.txt","w");
for(i=0;i<o-2;i++){ fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
}
fclose(fp);
printf("删除成功!\n");
}
getchar();
for(;;){ //判断是否继续
printf("是否继续删除?Y/N\n");
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("%c不是Y/N,是否继续删除?\n");
}
}while(yes_no=='Y'||yes_no=='y');
}
int up(){ //上机
time_t start;
struct tm *t;
int flag=0;
int o=0,k=-1,i=0,j=-1;
char s[15],m[15];
char yes_no='\0';
FILE *fp=NULL;
printf("请输入上机学号\n");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!!!\n");
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
fclose(fp);
if(k==-1){ //判断是否有此人
system("cls");
printf("查无此人!请重新输入......\n");
up();
}
else{
printf("请输入密码:\n");
scanf("%s",m);
if(strcmp(stu[k].mima,m)==0){ //判断密码是否正确
if(stu[k].money>=6){ //判断余额是否大于6块钱
printf("上机成功!欢迎使用!\n");
start=time(NULL); //定义时间
t=localtime(&start);
printf("上机成功时间为:%s\n",asctime(t));
flag=k;
printf("学号:%s\t姓名:%s\t班级:%s\t余额:%d\n",stu[k].num,stu[k].name,stu[k].clas,stu[k].money);
}
else {
printf("\n您的余额不足!如需充值?请返回主菜单选择充值......\n");
}
}
else{
system("cls");
printf("密码错误!请重新输入上机学号:\n");
up();
}
return flag+1; //返回值,用于上机记录
}
}
void Suan_Qian(int dif,int k){ //计算余额
int hour,min;
int money;
int o=0,i=0;
hour=dif/3600; //小时
min=dif%3600/60; //分钟
if(min>30){
hour++;
min=0;
}
money=2*hour+min;
FILE *fp=NULL;
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!\n");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("上机前余额为:%d\n",stu[k].money);
stu[k].money=stu[k].money+money;
printf("上机后余额为:%d\n",stu[k].money);
fp=fopen("d:\\duli16.3.txt","w");
for(i=0;i<o;i++){
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[i].num,stu[i].name,stu[i].mima,stu[i].clas,stu[i].money);
i++;
}
fclose(fp);
}
void top_up(){ //续费
int o=0,k=-1,i=0,j=0,cmoney=0;
char s[15];
char yes_no='\0';
FILE *fp=NULL;
printf("请输入要充值的学号:\n");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!\n");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[i].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
if(k==-1){ //判断是否有此人
system("cls");
printf("查无此人!请重新输入......\n");
top_up();
}
else{
printf("请输入充值金额:");
scanf("%d",&cmoney);
fp=fopen("d:\\duli16.3.txt","r");
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d\n",stu[j].num,stu[j].name,stu[j].mima,stu[j].clas,&stu[j].money);
j++;
}
fclose(fp);
printf("续钱钱的金额为:%d\n",stu[k].money);
stu[k].money=stu[k].money+cmoney;
printf("续钱后的金额为:%d\n",stu[k].money);
printf("学号:%s\t姓名:%s\t班级:%s\t余额:%d\n",stu[k].num,stu[k].name,stu[k].clas,stu[k].money);
fp=fopen("d:\\duli16.3.txt","w");
for(k=0;k<j;k++){
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[k].num,stu[k].name,stu[k].mima,stu[k].clas,stu[k].money);
}
fclose(fp);
}
}
void innovate(){ //创新功能
char chose='\0',yes_no='\0';
do{
system("cls");
printf("---------------------\n");
printf("请输入选项编号(0~3)\n");
printf("---------------------\n");
printf("1——查询余额\n");
printf("2——修改密码\n");
printf("3——显示所有学生\n");
printf("0——返回主菜单\n");
printf("---------------------\n");
printf("\n");
scanf("%c",&chose);
getchar();
switch(chose){
case '1':
inquiry();
break;
case '2':
mod();
break;
case '3':
XianShi();
break;
case '0':
printf("返回主菜单!\n");
return;
default :printf("\n%c为非法字符!\n",chose);
}
for(;;){
printf("\n是否返回菜单?Y/N\n");
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("输入错误!请重新输入......\n");
}
}while(yes_no=='Y'||yes_no=='y');
}
void inquiry(){ //查询信息
int o=0,k=-1,i=0;
char s[15];
char yea_no='\0';
FILE *fp=NULL;
printf("请输入要查询的学号:\n");
scanf("%s",s);
getchar();
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!\n");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
printf("\n");
for(i=0;i<o;i++){ //查找有无此人
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
if(k==-1){ //判断是否有此人
system("cls");
printf("查无此人!请重新输入......\n");
inquiry();
}
else printf("%s同学!您的余额为:%d\n",stu[k].name,stu[k].money);
}
void mod(){ //修改密码
int o=0,k=-1,i=0,j=0;
char s[15],m[15];
char yes_no='\0';
FILE *fp=NULL;
printf("请输入要修改密码的学号:\n");
scanf("%s",s);
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!\n");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
printf("\n");
for(i=0;i<o;i++){
if(strcmp(stu[i].num,s)==0){
k=i;
break;
}
}
if(k==-1){
system("cls");
printf("\n查无此人!请重新输入......\n");
mod();
}
printf("输入修改后的密码:\n");
scanf("%s",m);
getchar();
fp=fopen("d:\\duli16.3.txt","r");
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[j].num,stu[j].name,stu[j].mima,stu[j].clas,&stu[j].money);
j++;
}
fclose(fp);
strcpy(stu[k].mima,m);
printf("学号:%s\t姓名:%s\t班级:%s\t余额:%d\n",stu[k].num,stu[k].name,stu[k].clas,stu[k].money);
fp=fopen("d:\\duli16.3.txt","w");
for(k=0;k<j-1;k++)
fprintf(fp,"%s\t%s\t%s\t%s\t%d\n",stu[k].num,stu[k].name,stu[k].mima,stu[k].clas,stu[k].money);
fclose(fp);
}
void XianShi(){ //显示所有学生信息
int o=0,i=0;
FILE *fp=NULL;
fp=fopen("d:\\duli16.3.txt","r");
if(fp==NULL){
printf("文件打开失败!\n");
return;
}
while(feof(fp)==0){
fscanf(fp,"%s%s%s%s%d",stu[o].num,stu[o].name,stu[o].mima,stu[o].clas,&stu[o].money);
o++;
}
fclose(fp);
system("cls");
printf("学号\t\t姓名\t\t班级\t\t余额\n");
for(i=0;i<o-1;i++){
printf("%s\t\t%s\t\t%s\t\t%d\n",stu[i].num,stu[i].name,stu[i].clas,stu[i].money);
}
}
int main(){ //主函数
char chose='\0',yes_no='\0';
int flag=0;
int y=1;
int dif=0,k;
time_t start_t,end_t;
do{
menu();
printf("请选择输入选项编号\n");
scanf("%c",&chose);
getchar();
switch(chose){
case '1':
create();
getchar();
break;
case '2':
add();
getchar();
break;
case '3':
cancel();
getchar();
break;
case '4':
flag=up();
getchar();
if(flag!=0){
time(&start_t);
}
break;
case '5':
if(flag!=0&&y==1){
time(&end_t);
printf("下机成功!!!下机时间为:%s祝您愉快!\n",ctime(&end_t));
k=flag-1;
dif=(int)difftime(end_t,start_t);
Suan_Qian(dif,k);
flag=0;
}
else printf("您还没上机呢?\n");
break;
case '6':
top_up();
getchar();
break;
case '7':
innovate();
break;
case '0':
printf("感谢使用本软件!已正常退出,按任意键结束。\n");
getchar();
exit(0);
default :printf("输入错误,%c不在选项中\n",chose);
}
printf("\n");
for(;;){ //判断是否继续
printf("是否返回主菜单?(Y/N)\n");
scanf("%c",&yes_no);
getchar();
if(yes_no=='Y'||yes_no=='y'||yes_no=='N'||yes_no=='n')break;
printf("输入错误!%c不是Y/N,请重新输入......\n",yes_no);
}
}while(yes_no=='Y'||yes_no=='y');
return 0;
}
附录B 用户使用说明书
硬件要求:有输入工具,输出工具,如键盘鼠标屏幕等
软件要求:C语言编译器等
使用方法:运行程序
打印目录
1、建立新档案
2、添加新档案
3、注销旧档案
4、开始上机
5、离开机房
6、续钱
7、创新功能
打印目录
1、查询余额
2、修改密码
3、显示所有学生信息
0、返回主菜单
0、退出软件
注意事项:不要点太快,输入值时不要输太快,求稳不求快,否则程序会出错,会达不到预期效果,望周知!
参考文献
[1]何钦铭,颜晖.C语言程序设计(第四版)(教材)[M].版次.北京:高等教育出版社,2020.9