一、程序概述
1.开发环境
开发程序的工具MicrosoftVisual C++ 6.0,(简称Visual C++ 6.0、VC++ 6.0或VC 6.0)是Microsoft公司推出的以C++语言为基础的开发Windows环境程序,面向对象的可视化集成编程系统。它不但具有程序框架自动生成、灵活方便的类管理、代码编写和界面设计集成交互操作、可开发多种程序等优点。
2.开发目的
班费收支管理系统,方便班级生活委员管理和统计班费。班级收支一目了然,在总结中打开程序即可告知每一位同学近期的班费使用情况。
3.开发功能
注册登录、UI界面、添加班费收支信息、浏览所有班费收支信息、删除班费收支信息、查询班费收支信息、修改班费收支信息、修改账户和密码、清空所有收支信息、自动求和。
二、程序概要
1.程序流程图
2.函数功能关系
每一个函数实现一个功能,模块化编写程序。主要由十个函数完成程序功能连接,充分利用Menu函数作为过渡到其它函数。Welcome函数实现注册登录、Menu函数实现主菜单、Outlook函数实现外观显示、Insert函数实现添加班费收支信息、Output函数实现浏览所有班费收支信息并自动求和、Delete函数实现删除班费收支信息、Search函数实现查询版费收支信息、Modify函数实现修改班费收支信息、Change函数实现修改账户和密码、Clean函数实现清空所有班费收支信息。
三、程序详细设计
1.关键代码分析
main函数中system("color 50");设置背景颜色与文字区分,当运行完一个功能利用system("cls");清屏,给用户最佳视觉和体验。
Welcome函数中fflush(stdin);清空输入缓冲区,确保不影响后面数据读取,创建两个数组储存用户名和密码,以二进制rb+储存管理员信息,指针fp1本地数据储存判断用户名和密码的正确与否。
Menu函数中switch{case:break;}选择相应需要的功能,调用相应的函数。
Outlook函数相当于一个UI界面,我的能力范围用printf输出内容让用户看明白对应的功能,这个函数全部都是printf出来的,应该还有更好地方法,没有学习到。
Insert函数中用指针fp2以二进制ab+储存每条班费收支信息,用txt文件储存,同样修改txt文件可导入收入和支持信息到程序中。储存内容包括日期、项目、收支、经办人。这四个内容为一个结构体,以数组的形式储存。用if语句判断收支是正还是付,讲收支储存在不同的文件中。
Output函数中用指针fp2查看用Insert函数储存的所有班费收支信息,并用while循环一条一条循环输出,和统计班费总收入、班费总支出、班费余额。
Delete函数中通过日期查看相对应的收支信息并打印出所有符合的收支信息,再选择需要删除的记录。
Search函数与Delete函数相似,通过日期查询相对应的收支信息并打印出,比Delete函数缺少的是删除的代码fprintf(fp2,"%10s%25s%20s%30s","","","","");储存空的字符串相当于删除,还可以通过其他字段进行排序浏览。
Modify函数与Delete函数相似,同样通过日期查询对应的收支信息并打印出来,与Delete函数的区别在于Delete函数中代码fprintf(fp2,"%10s%25s%20s%30s","","","","");在Modify中重新修改结构体中的数组中的元素并储存到相应的收支信息中得以修改班费收支信息代码为fprintf(fp2,"%10s%25s%20s%30s",timekey,one.xiangmu,one.money,one.name);
Change函数与Modify函数类似,通过指针fp1查询对应用户名的密码,并修改密码数组得以修改密码。
Clean函数中利用代码remove("软工三班班费收支管理系统.txt")相当于Delete函数的一键操作,方便又快捷。
2.疑难问题解决
刚开始拿到C语言大作业题目的时候整个人都是蒙的,感觉无从下手,似乎需要实现的功能都是在课堂中没有接触到了。随着时间流逝,自己也对这个作业紧张起来,开始认真着手做。
在项目开始时只能想到printf、scanf、循环结构初步实现了输入班费收支信息的输入与输出但是不知道如何保存下来,于是百度以二进制储存文件得知使用使用fopen、fprinft、fclose、、FILE、指针成功把班费收支信息储存到txt的文件中,但是理解不透以二进制存储是什么意思,因为我打开文件看到的不是0和1储存的信息。我在代码中也百度到二进制是用rb、wb、ab,所以这个问题让我进度停止了一会。
算是初步完成要求中的基本功能添加班费收支信息,紧接着得心应手完成了浏览所有班费收支信息的代码,但是在运行中却难以切换两个功能,使用起来非常不方便。后来百度没有查到好的方法,接着完成了查询班费收支信息和修改班费收支信息,就把大作业闲置下来,开始准备计算机二级考试。就是这么巧在我考二级的过程中,让我想起了switch{case:break;}语句建立了Menu函数完成了各个功能的切换。
但是运行起来还是非常奇怪,除了我自己编译的软件自己会用,一般用户使用都有点摸不着头脑。而我在星空学习IOS用的编译器Xcode是有拖控件完成UI界面的,对于C语言如何做UI界面在课堂中没有学习过,百度到C语言要实现windows图形界面需要加一个头文件#include<windows.h>然后一大串代码,太多的不懂,无奈最后全部用printf出来,给用户一个选择的提示,虽然有点小儿科,但也算完成了这一难关。
看似已经差不多完美的程序还有有点不满意,我便用与储存班费收支信息的相似的方法写了登录和注册的函数,再利用了一个指针。完美的结合了十个功能函数和main函数。很难受的是在使用过程中,一次一次切换功能产生printf堆积大量信息,界面非常难看,很快我又百度到system("cls");代码用于清屏,整个程序自然就美观多了。
#include<stdio.h>
#include<stdlib.h>#include<string.h> //使用到字符数组时需要使用
#include<conio.h> //定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作
#include<windows.h> //windows图形界面相关
FILE *fp1; //指向 "管理员信息" 文件的指针
FILE *fp2; //指向 "数据库" 的指针
char administor[40],passward[50];//储存账户名和密码
struct note //定义一条记录
{
char time[9]; //记录创建时间
char xiangmu[20]; //记录项目
char money[16]; //收支情况
char name[25]; //经办人姓名
};
//主要功能函数声明
int Welcome(); //1.注册登录界面
int Menu(); //2.主菜单
int Outlook(); //3.外观显示
int Insert(); //4.添加班费收支信息
int Output(); //5.浏览所有班费收支信息
int Delete(); //6.删除班费收支信息
int Search(); //7.查询班费收支信息
int Modify(); //8.修改班费收支信息
int Change(); //9.修改账户和密码
int Clean(); //10.清空数据库
//主函数
int main()
{
system("color 50"); //软件颜色
if(Welcome())
{
while(1)
{
system("cls"); //用于清屏
Menu();
}
}
return 0;
}
//主要功能函数
//1.注册登录
int Welcome()
{
fflush(stdin); //清空输入缓冲区,通常是为了确保不影响后面的数据读取
int i=0;
int num=3; //统计输入次数
int sign=2; //标记错误类型
char F_administor[40],F_passward[50];//读取文件中储存的账户和密码
printf("\t\t\t欢迎使用软工三班班费收支管理系统 \n\n");
printf("------------------------------用户登陆界面-----------------------------------\n\n");
if((fp1=fopen("管理员信息.txt","rb+"))==NULL) //账户和密码输入界面,当第一次运行此程序时需注册一个新账户
{
printf("\t这是您第一次使用该系统,请注册一个管理员账户\n\n");
printf("\t\t请输入管理员姓名:");
scanf("%s",administor);
getchar();
printf("\n\t\t请输入密码:");
while((passward[i]=getch())!='\r')
{
if(i==0&&passward[i]=='\b')
{
}
else if(passward[i]=='\b')
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
else
{
printf("*");
i++;
}
}
passward[i]='\0';
if((fp1=fopen("管理员信息.txt","wb+"))==NULL)
{
printf("\n注册失败!!!请稍后重试\n");
return 0;
}
else
{
fprintf(fp1,"%40s%50s",administor,passward);//将管理员账户和密码存入文件
fclose(fp1);
printf("\n\n\t注册成功,请按任意键继续...");
getch();
}
return 1;
}
fclose(fp1);
if((fp1=fopen("管理员信息.txt","rb+"))==NULL) //打开文件,判断输入的账户和密码是否正确
{
printf("文件打开失败,请稍后重试!!");
return 0;
}
else
{
while(num) //判断错误类型,并给出相应提示,3次错误则退出系统
{
i=0;
if(sign==1)
{
printf("\n\n\t该管理员账户不存在,您还有%d次输入机会\n\n",num);
}
else if(sign==0)
{
printf("\n\n\t密码输入错误,您还有%d次输入机会\n\n",num);
}
printf("\n\t请输入管理员姓名:");
scanf("%s",administor);
getchar();
printf("\n\t请输入密码:");
while((passward[i]=getch())!='\r')
{
if(i==0&&passward[i]=='\b')
{
}
else if(passward[i]=='\b')
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
else
{
printf("*");
i++;
}
}
passward[i]='\0';
fscanf(fp1,"%40s%50s",F_administor,F_passward);
if(stricmp(F_administor,administor)==0)
{
if(strcmp(F_passward,passward)==0)
{
fclose(fp1);
return 1;
}
else
{
sign=0;
}
}
else
{
sign=1;
}
num--;
}
printf("\n\t您的输入错误次数超过3次,系统将在3秒后自动关闭!\n");
fclose(fp1);
Sleep(3000);
return 0;
}
}
//2.主菜单
int Menu()
{
fflush(stdin);
char choose;
Outlook(); //调用Outlook函数显示菜单项
scanf("%c",&choose);
getchar();
switch(choose) //判断要执行的操作
{
case 'A': Insert(); break;
case 'B': Output(); break;
case 'C': Delete(); break;
case 'D': Search(); break;
case 'E': Modify(); break;
case 'F': Change(); break;
case 'G': Clean(); break;
case 'Q': exit(0); break;
default:
{
Outlook();
break;
}
}
return 0;
}
//3.UI界面
//除了printf出来,还有其他方法?
int Outlook() //显示菜单项
{
printf(" 软工三班班费收支管理系统\n\n");
printf("------------------------------功能选择界面-------------------------------------\n\n");
printf("\t请选则功能:\n\n");
printf("\t\t[A] 添加班费收支信息\n");
printf("\t\t[B] 浏览所有班费收支信息\n");
printf("\t\t[C] 删除班费收支信息\n");
printf("\t\t[D] 查询班费收支信息\n");
printf("\t\t[E] 修改班费收支信息\n");
printf("\t\t[F] 修改账户和密码\n");
printf("\t\t[G] 清空数据库\n");
printf("\t\t[Q] 安全退出\n\n");
printf("\t版权所有:何大大\t盗版必究\n\n");
printf("\t请选着要进行的操作:");
return 0;
}
//4.添加班费收支信息
int Insert()
{
system("cls");
fflush(stdin);
//判断该数据库是否存在
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
fp2=fopen("软工三班班费收支管理系统.txt","wb+");
}
fclose(fp2);
struct note one;
//如果数据库里有记录则以追加方式打开
printf(" 软工三班班费收支管理系统\n\n");
printf("------------------------------添加新记录界面-----------------------------------\n\n");
printf("\t添加新记录:\n");
if((fp2=fopen("软工三班班费收支管理系统.txt","ab+"))==NULL)
{
printf("\n\t对不起,不能打开该数据库!");
return 0;
}
//按格式添加数据
printf("\n\t\t请按此格式输入当前日期(20180303):");
scanf("%s",one.time);
getchar();
while(strlen(one.time)!=8)
{
printf("\t\t格式输入有误,请重新输入日期(20180303):");
scanf("%s",one.time);
getchar();
}
printf("\n\t\t请输入记录项目(不多于20个字符):");
scanf("%s",one.xiangmu);
getchar();
printf("\n\t\t请输入收支情况(正数表示收入,负号表示支出):");
scanf("%s",one.money);
getchar();
printf("\n\t\t请输入经办人姓名(不多于25个字符):");
scanf("%s",one.name);
getchar();
fprintf(fp2,"%10s%25s%20s%30s",one.time,one.xiangmu,one.money,one.name);
fclose(fp2);
printf("\n\t操作成功,请按任意键继续...");
getch();
return 0;
}
//5.浏览所有班费收支信息
int Output()
{
system("cls");
fflush(stdin);
//判断该数据库是否存在
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------错误提示----------------------------------------\n\n");
printf("\t您尚未录入任何记录,按任意键返回重新选择.");
getch();
return 0;
}
double sum=0; //统计总的收支情况
double sum1=0; //统计总的收入情况
double sum2=0; //统计总的支出情况
double number; //将字符串临时转化为整形数据
struct note one;
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf("\t对不起,不能打开该数据库!请按任意键继续...");
getch();
return 0;
}
printf(" 软工三班班费收支管理系统\n\n");
printf("------------------------------财务记录总账显示------------------------------\n\n");
printf(" 时间 项目 收支 经办人\n");
while(!feof(fp2))//循环输出记录
{
fscanf(fp2,"%10s%25s%20s%30s",one.time,one.xiangmu,one.money,one.name);
printf("%10s%20s%16s%23s\n\n",one.time,one.xiangmu,one.money,one.name);
number=atof(one.money);
if(number>0)
{
sum1+=number;
}
else
{
sum2+=number;
}
}
//班费统计
sum=sum1+sum2;
printf("\n\t班费总收入为:%.2lf元",sum1);
printf("\n\t班费总支出为:%.2lf元",sum2);
printf("\n\t班费余额为:%.2lf元",sum);
printf("\n\n\t操作成功,请按任意键继续...");
getch();
fclose(fp2);
return 0;
}
//6.删除班费收支信息
int Delete()
{
system("cls");
fflush(stdin);
//判断该数据库是否存在
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------错误提示----------------------------------------\n\n");
printf("您尚未录入任何记录,按任意键返回重新选择.");
getch();
return 0;
}
fclose(fp2);
char choose; //判断是否决定删除
int i=1;
int num;
long locate[100];//标记记录在文件中的位置
char timekey[10];
struct note one;
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------删除记录界面------------------------------------\n\n");
printf("\t删除记录:\n");
//输入日期,查找到相应记录项
printf("\n\t\t请按次格式输入要删除记录的日期(20180303):");
scanf("%s",timekey);
getchar();
while(strlen(timekey)!=8)
{
printf("\t\t格式输入有误,请重新输入日期(20180303):");
scanf("%s",timekey);
getchar();
}
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf("\n\t对不起,不能打开该数据库!请按任意键继续...");
getch();
return 0;
}
locate[0]=ftell(fp2);
while(!feof(fp2))//循环查找
{
fscanf(fp2,"%10s%25s%20s%30s",one.time,one.xiangmu,one.money,one.name);
if(!strcmp(one.time,timekey))
{
locate[i]=ftell(fp2);
printf("<%d>\n 时间 项目 收支 经办人\n",i);
printf("%10s%20s%16s%23s",one.time,one.xiangmu,one.money,one.name);
i++;
printf("\n");
}
}
if(i-1)
{
printf("\n\t共找到%d条符合条件的记录\n",i-1);
//选择要删除的记录编号
printf("\n\t\t请选择要删除的记录编号:");
scanf("%d",&num);
getchar();
//确定界面
printf("\n\t确实要删除该记录吗?<y/n>");
scanf("%c",&choose);
getchar();
if((choose=='y')||(choose=='Y'))
{
fseek(fp2,locate[num-1],0);
fprintf(fp2,"%10s%25s%20s%30s","","","","");
fclose(fp2);
if(i==2)
{
remove("软工三班班费收支管理系统.txt");
}
printf("\t操作成功,请按任意键继续...");
getch();
return 0;
}
}
else
{
printf("\t对不起,数据库中无此记录!请按任意键继续...");
getch();
}
fclose(fp2);
return 0;
}
//7.查询班费收支信息
int Search()
{
system("cls");
fflush(stdin);
//判断该数据库是否存在
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------错误提示----------------------------------------\n\n");
printf("\t\t您尚未录入任何记录,按任意键返回重新选择.");
getch();
return 0;
}
fclose(fp2);
int num=0; //用于记录共有几项符合条件的记录
char timekey[10];
struct note one;
//根据时间查找记录
printf(" 软工三班班费收支管理系统\n\n");
printf("------------------------------查找记录界面-------------------------------------\n\n");
printf("\t查找记录:\n");
printf("\n\t\t请按次格式输入要查找的记录的日期(20180303):");
scanf("%s",timekey);
getchar();
while(strlen(timekey)!=8)
{
printf("\n\t\t格式输入有误,请重新输入日期(20180303):");
scanf("%s",timekey);
getchar();
}
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf("\n\t对不起,不能打开该数据库!");
return 0;
}
while(!feof(fp2)) //循环查找
{
fscanf(fp2,"%10s%25s%20s%30s",one.time,one.xiangmu,one.money,one.name);
if(!strcmp(one.time,timekey))
{
printf("\n 时间 项目 收支 经办人\n");
printf("%10s%20s%16s%23s",one.time,one.xiangmu,one.money,one.name);
num++;
printf("\n");
}
}
if(!num)
{
printf("\n\t对不起,数据库中无此记录!请按任意键继续...");
getch();
}
else
{
printf("\n\n\t共找到%d条符合条件的记录",num);
printf(",按任意键继续...");
getch();
}
fclose(fp2);
return 0;
}
//8.修改班费收支信息
int Modify()
{
system("cls");
fflush(stdin);
//判断数据库里是否有记录
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------错误提示----------------------------------------\n\n");
printf("\t您尚未录入任何记录,按任意键返回重新选择.");
getch();
return 0;
}
fclose(fp2);
int i=1; //标记记录条数
long locate[100];//标记记录的位置
char timekey[10];
struct note one;
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------修改记录界面------------------------------------\n\n");
printf("\t修改记录:\n");
//输入日期,查找到相应记录项
printf("\n\t\t请按此格式输入要修改记录的日期(20180303):");
scanf("%s",timekey);
getchar();
while(strlen(timekey)!=8)
{
printf("\t\t格式输入有误,请重新输入日期(20180303):");
scanf("%s",timekey);
getchar();
}
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf("\t对不起,不能打开该数据库!");
return 0;
}
locate[0]=ftell(fp2);
while(!feof(fp2)) //循环查找
{
fscanf(fp2,"%10s%25s%20s%30s",one.time,one.xiangmu,one.money,one.name);
if(!strcmp(one.time,timekey))
{
locate[i]=ftell(fp2);
printf("<%d>\n 时间 项目 收支 经办人\n",i);
printf("%10s%20s%16s%23s",one.time,one.xiangmu,one.money,one.name);
printf("\n");
i++;
}
}
if(i-1)
{
printf("\n\t共找到%d条符合条件的记录\n",i-1);
//选择要修改的记录
printf("\n\t请选择要修改的的记录编号(退出请输入0):");
scanf("%d",&i);
getchar();
if(i==0)
{
return 0;
}
fseek(fp2,locate[i-1],0);
//输入新数据
printf("\n\t\t请按次格式输入新日期(20180303):");
scanf("%s",timekey);
getchar();
while(strlen(timekey)!=8)
{
printf("\t\t格式输入有误,请重新输入新日期(20180303):");
scanf("%s",timekey);
getchar();
}
printf("\n\t\t请输入新记录项目(不多于20个字符):");
scanf("%s",one.xiangmu);
getchar();
printf("\n\t\t请输入新收支情况(正数表示收入,负号表示支出):");
scanf("%s",one.money);
getchar();
printf("\n\t\t请输入新经办人姓名(不多于25个字符):");
scanf("%s",one.name);
getchar();
fprintf(fp2,"%10s%25s%20s%30s",timekey,one.xiangmu,one.money,one.name);
printf("\n\t操作成功,请按任意键继续...");
getch();
}
else
{
printf("\n\t对不起,数据库中无此记录!请按任意键继续...");
getch();
}
fclose(fp2);
return 0;
}
//9.修改账户和密码
int Change()
{
system("cls");
fflush(stdin);
//判断文件是否存在
if((fp1=fopen("管理员信息.txt","rb+"))==NULL)
{
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------错误提示----------------------------------------\n\n");
printf("\t文件打开失败,请稍后重试。");
Sleep(3000);
return 0;
}
//如果找到文件则执行下面的修改语句
int i=0;
char F_administor[40],F_passward[50];//文件中储存的信息
char administor[40],passward[50]; //用户输入的信息
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------密码修改界面------------------------------------\n\n");
printf("\t密码修改:\n");
printf("\n\t\t请输入原管理员姓名:");//输入原信息
scanf("%s",administor);
getchar();
printf("\n\t\t请输入原密码:");
while((passward[i]=getch())!='\r')
{
if(i==0&&passward[i]=='\b')
{
}
else if(passward[i]=='\b')
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
else
{
printf("*");
i++;
}
}
passward[i]='\0';
fscanf(fp1,"%40s%50s",F_administor,F_passward);
if((strcmp(F_administor,administor)==0)&&(strcmp(F_passward,passward)==0))//判断输入的用户名和密码是否正确
{
fclose(fp1);
i=0;
if((fp1=fopen("管理员信息.txt","wb+"))==NULL)
{
printf("\n\t操作失败!按任意键继续...");
getch();
}
else
{
//输入新信息
printf("\n\n\n\t\t请输入新管理员名称:");
scanf("%s",administor);
getchar();
printf("\n\t\t请输入新密码:");
while((passward[i]=getch())!='\r')
{
if(i==0&&passward[i]=='\b')
{
}
else if(passward[i]=='\b')
{
printf("\b");
printf(" ");
printf("\b");
i--;
}
else
{
printf("*");
i++;
}
}
passward[i]='\0';
fprintf(fp1,"%40s%50s",administor,passward);//将新的管理员账户和密码存入文件
fclose(fp1);
printf("\n\n\t操作成功,请按任意键继续...");
getch();
}
}
else
{
printf("\n\n\t操作失败!按任意键继续...");
getch();
}
return 0;
}
//10.清空数据库函数
int Clean()
{
system("cls");
fflush(stdin);
char choose; //判断是否删除
printf(" 软工三班班费收支管理系统\n\n");
printf("-------------------------------清空数据库界面----------------------------------\n\n");
printf("\t清空数据库:\n\n");
printf("\t\t数据库清空后将无法恢复,您确定么?<Y/任意字符返回>");
scanf("%c",&choose);
if((fp2=fopen("软工三班班费收支管理系统.txt","rb+"))==NULL)
{
printf("\n\t您未记录任何数据,按任意键返回...");
getch();
return 0;
}
fclose(fp2);
if(choose=='Y')
{
if(remove("软工三班班费收支管理系统.txt"))
{
printf("\n\t操作失败,按任意键继续...");
getch();
}
else
{
printf("\n\t操作成功,按任意键继续...");
getch();
}
}
return 0;
}