前言
如题,IDE使用的VC++6.0(上古软件了)
帮朋友完善修改了下工程实践,各种错误bug还是搞了几个小时,想了想还是发布出来,供大家参考
虽说程序使用了C++,但实际上用到的并不多,基本上是用C的模式写的。
工程结构简单,一个.h文件,一个.cpp文件,仅此
我会将代码贴在下方,也会提供一个完整打包的压缩包链接:
题目要求
运行效果:
登录/注册
账目文件导入/手动输入
账目查询
账务统计
测试内容过多,就不一一贴出来了
请自行运行测试
注意
程序运行过程中会生成四个txt文件以存储数据,已集成在打包下载链接中。
否则需要自己创建login.txt,格式如下,以一个制表符(单个空格貌似也行)间隔,不然程序会运行出错
in.txt作为文件导入,需遵循以下格式,以一个制表符作为间隔,out.txt,temp.txt也是遵循该格式
若有疑问,欢迎评论区交流讨论
程序代码
废话已毕,贴代码:
main.cpp
//#define _CRT_SECURE_NO_WARNINGS
#include"PFOS.h"
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
int main() //主函数
{
cout << "***********欢迎进入个人帐本管理系统****************************" << endl;
//实时时间
system("color f0"); //可以写成 red 调出颜色组
system("date /T");
system("TIME /T");
Login(); //登陆注册
UI(); //选择菜单
while (scanf("%d", &key) != EOF)
{
//falg2选择键
if (key == 1) //账目录入
input();
else if (key == 2) //删除账目
del();
else if (key == 3) //浏览账目
query();
else if (key == 4) //修改账目
change();
else if (key == 5) //排序--选择排序方式
acc_sort();
else if (key == 6) //统计账目--选择统计方式
data_report();
else if (key == 7)
save(); //没有返回到主调函数
else if (key == 0)
exit(0);
UI();
}
return 0;
}
PFOS.H(个人账目系统英文简称)
#ifndef _PFOS_H_
#define _PFOS_H_
#include "PFOS.h"
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<iostream>
using namespace std;
int cnt = 0, //记录当前所有账目数量
key, //选择键 (菜单选项)
Myid, //接收账目序号 (删除操作)
minj,
moncmp1 = 0,
moncmp2 = 0,
vis;
int tmpi; //接收临时整型数 (查询操作)
char tmps[20]; //接收临时字符串 (查询操作)
int strcnt = 0; //字符串长度计数
struct MyAccount
{
int money, //金额
dateint, //整型日期
flag_print, //
id; //序号
char
date[20], //日期
name[20], //名称
type[20], //类型
ps[20]; //备注
} MyACC[1000], T; //定义一个结构体数组MyACC[1000]来存储账目表,一个结构体变量T来暂时账目数据
struct USER
{
char ID[18];
char PW[20];
}user[20];
int num = 0; //账务明细条目
int num_0=0;
int User=0;//对应用户
void initialDateint();
void UI(); //主菜单UI
void input(); //输入相关函数
void Hand_Input();
void File_Input();
void Auto_File_Input();
void del(); //删除
void place(); //整理
void query(); //查询相关
int FindDataItemIndexById(int dataId);
void change(); //修改相关
void save(); //文件保存
void moneysort(); //排序相关函数
void datesort();
void name_sort();
void acc_sort();
void data_report();
bool cmp_money(MyAccount A, MyAccount B);
bool cmp_date(MyAccount A, MyAccount B);
/*************************************************************************************************************************/
// 登录注册部分
void readfile_0()
{
FILE *fl;
int i=0;
fl=fopen("login.txt","r");
if(!fl)
{
printf("\n请创建login.txt文件");
}
//读入条目达到计数的目的
while(fscanf(fl,"%s%s",user[i].ID,user[i].PW)==2)
i++;
num_0=i;
fclose(fl);
}
/*************************************************************************************************************************/
//向文件中注册账户
void CreatUser()
{
FILE *fl;
int i=0;
fl=fopen("login.txt","w");
if(!fl)
{
printf("\n请创建login.txt文件");
}
for(i=0;i<num_0;i++)
//输出到文件
{
fprintf(fl,"\n%s %s",user[i].ID,user[i].PW);
}
printf("\n");
fclose(fl);
}
/*************************************************************************************************************************/
void Login()
{
int i=0;
readfile_0();
char ID[20]={0},PW[20]={0};
printf("\n=================================\n 登录到个人帐本管理助手 \n=================================\n");
printf("如未注册,按0键进行注册,如已有账号按1键进行登陆 \n");
scanf("%d",&i);
if(i==0)
{
int k=num_0,j,flag=1;
while(flag)
{
flag=0;
printf("\n请输入您要注册的账号:");
scanf("%s",user[k].ID);
for(j=0;j<k;j++)
if(strcmp(user[k].ID,user[j].ID)==0)
{
printf("该用户已注册,请勿重复注册,\n");
flag=1;
break; /*如有重复立即退出该层循环,提高判断速度*/
}
}
printf("\n请输入密码:");
scanf("%s",user[k].PW);
num_0++;
printf("\n%s 账户已成功注册",user[k].ID);
//在文本文件注册信息
CreatUser();
Login();
}
else if(i==1)
{
int j=0;
printf("Please input your Usernumber \n");
scanf("%s",ID);
printf("Please input your PassWord \n");
scanf("%s",PW);
for(i=0;i<num_0;i++)
{
if(strcmp(user[i].ID,ID)==0&&strcmp(user[i].PW,PW)==0)
{
User=i;
j++;
break;
}
}
if (j==0) {
printf("Please recheck the number or your password!\n");
Login();
}
else printf("Successfully!");
}
}
/*************************************************************************************************************************/
void UI() //UI主界面
{
cout << endl << endl;
cout << "***************************************************************" << endl;
cout << "** 请输入以下选项编号进行下一步操作! **" << endl;
cout << "** 1.输入账目 **" << endl;
cout << "** 2.删除账目明细条目 **" << endl;
cout << "** 3.查询账目明细条目 **" << endl;
cout << "** 4.修改账目明细条目 **" << endl;
cout << "** 5.账务数据排序 **" << endl;
cout << "** 6.财务统计 **" << endl;
cout << "** 7.保存文件 **" << endl;
cout << "*****************0.退出系统************************************" << endl;
}
/*************************************************************************************************************************/
void place() //数组序号整理
{
FILE* fp;
int k=1; //删除后的真实序号
if ((fp = fopen("temp.txt", "w")) == NULL) //写入临时文件
{
printf("无法打开文件!请检查是否建立输出文件!\n");
exit(0);
}
else
{
for (int i = 1; i <= cnt; i++)
{
if( MyACC[i].id == 0)
{
continue;
}
fprintf(fp, "%d\t%d\t%s\t%s\t%s\t%s\n\n", k,MyACC[i].money, MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
printf("%d,%d,%s,%s,%s,%s\n", k,MyACC[i].money,MyACC[i].date,MyACC[i].name,MyACC[i].type,MyACC[i].ps);
printf("保存成功!%d\n",i);
k++;
}
printf("保存成功!");
}
fclose(fp);
memset(MyACC,0,10);
cnt=1;
if ((fp = fopen("temp.txt", "r")) == NULL) //再读取
{
//r+:指针指向文件开头,这里要自己打开in.txt文件写入账目
printf("无法打开文件!请检查文件是否存在!\n");
exit(0);
}
else
{
while (!feof(fp))
{
fscanf(fp, "%d%d%s%s%s%s\n\n", &T.id,&T.money,&T.date,&T.name,&T.type,&T.ps); //暂存一项数据
if(T.id!=0)
{
MyACC[cnt]=T;
cnt++;
}
}
cnt--;
printf("再输入完成,共%d条账目", cnt);
}
fclose(fp);
}
/*************************************************************************************************************************/
void initialDateint() //整型日期初始化
{
for (int i = 1; i <= cnt; i++)
{
int rank = 1, Date_int = 0; //rank表示位阶(个位、十位、百位...),Date_int存放转换结果
for (int j = 7; j >= 0; j--)
{
//日期是8位数 例如2020.05.03
Date_int += rank * (MyACC[i].date[j] - 48); //一个数字与它对应在ascii码的数字字符相差48
rank *= 10; //字符转化为整数:从个位到最高位,size表示进位
}
MyACC[i].dateint = Date_int;
}
}
/*************************************************************************************************************************/
void input() //输入
{
printf("手动输入账务请输1,文件读取账务请输2\n");
scanf("%d", &key);
if (key == 1)
Hand_Input();
else if (key == 2)
File_Input();
initialDateint();
}
void Hand_Input() //手动输入
{
int flag; //输入账目函数
printf("您需要录入多少条账务记录?\n");
scanf("%d", &flag);
getchar();
while (flag--)
{
cnt++;
Myid = cnt;
printf("请按顺序输入以下内容:\n序号 收支金额 交易日期 收支项名称 收支类型 备注信息\n");
scanf("%d", &MyACC[Myid].id);
scanf("%d", &MyACC[Myid].money);
scanf("%s", MyACC[Myid].date);
scanf("%s", MyACC[Myid].name);
scanf("%s", MyACC[Myid].type);
scanf("%s", MyACC[Myid].ps);
getchar();
printf("第%d条录入完成!\n", cnt);
}
}
void File_Input() //文件输入
{
char name[30]; //存储文件名
printf("请输入文件名:\n");
scanf("%s",name);
FILE* fp;
if ((fp = fopen(name, "r+")) == NULL) //读写,若不存在,不建立
{
//r+:指针指向文件开头,这里要自己打开in.txt文件写入账目
printf("无法打开文件!请检查文件是否存在!\n");
exit(0);
}
else
{
cnt = 1;
while (!feof(fp))
{
fscanf(fp, "%d%d%s%s%s%s\n\n", &MyACC[cnt].id,&MyACC[cnt].money,&MyACC[cnt].date,&MyACC[cnt].name,&MyACC[cnt].type,&MyACC[cnt].ps);
printf("%d,%d,%s,%s,%s,%s\n", MyACC[cnt].id,MyACC[cnt].money,MyACC[cnt].date,MyACC[cnt].name,MyACC[cnt].type,MyACC[cnt].ps);
printf("数目:%d\n",cnt);
cnt++;
}
cnt--;
printf("输入完成,共%d条账目", cnt);
}
fclose(fp);
}
/*************************************************************************************************************************/
void save() //存储数据文件
{
FILE* fp;
if ((fp = fopen("out.txt", "w+")) == NULL)
{
printf("无法打开文件!请检查是否建立输出文件!\n");
exit(0);
}
else
{
for (int i = 1; i <= cnt; i++)
fprintf(fp, "%d\t%d\t%s\t%s\t%s\t%s\n\n", MyACC[i].id,MyACC[i].money, MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
printf("保存成功!");
}
fclose(fp);
// return;
}
/*************************************************************************************************************************/
void del() //删除
{
//删除账目函数
printf("请输入需要删除的账目ID:\n");
scanf("%d", &Myid);
memset(&MyACC[Myid],0,sizeof(MyACC[Myid])); //数据清零
MyACC[Myid].money = 0;
MyACC[Myid].date[0] = '0';
MyACC[Myid].name[0] = 0;
MyACC[Myid].type[0] = 0;
MyACC[Myid].ps[0] = 0;
MyACC[Myid].id = 0;
printf("删除成功!\n\n");
place();
}
/*************************************************************************************************************************/
void acc_sort() //排序
{
//选择排序类型
printf("根据金额排序输入1,根据日期排序输入2,根据名称排序输入3\n");
scanf("%d", &key);
if (key == 1)
moneysort();
else if (key == 2)
datesort();
else if (key == 3)
name_sort();
}
void moneysort() //金额排序
{
for (int i = 1; i <= cnt - 1; i++)
{
for (int j = 1; j <= cnt - 1; j++)
{
if (MyACC[j].money>0)
{
//默认金额是正数,但若出现负数,则把该条账目置后 ;分类后的结果
//为正数金额在前,负数金额在后;
T = MyACC[j];
MyACC[j] = MyACC[j + 1];
MyACC[j + 1] = T;
}
}
}
for ( i = 1; i <= cnt; i++)
if (MyACC[i].money<0)
{
vis = i;
break;
}
sort(MyACC + 1, MyACC + vis, cmp_money); //数组元素比较大小可用地址比较,数组名也为地址
sort(MyACC + vis, MyACC + cnt + 1, cmp_money);
for (i = 1; i <= cnt; i++)
{
MyACC[i].id=i;
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", i,MyACC[i].money,
MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
}
printf("已按金额递减排序完成!\n");
}
bool cmp_money(MyAccount A, MyAccount B) //金额比较
{
//比较金额大小的方式:由高到低 ,为后面作排序
if (A.money > B.money)
return true;
else
return false;
}
void datesort() //日期排序
{
sort(MyACC + 1, MyACC + 1 + cnt, cmp_date);
for (int i = 1; i <= cnt; i++)
{
MyACC[i].id=i;
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", i,MyACC[i].money,
MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
}
printf("根据日期排序完成!\n");
}
bool cmp_date(MyAccount A, MyAccount B) //日期比较
{
if (A.dateint < B.dateint)
return true;
else
return false;
}
void name_sort() //名称排序
{
for (int i = 1; i <= cnt; i++)
MyACC[i].flag_print = 0; //0表示没有被输出过
for (i = 1; i <= cnt; i++)
{
if (!MyACC[i].flag_print)
{
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", i, MyACC[i].money,
MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
MyACC[i].flag_print = 1;
}
for (int j = i + 1; j <= cnt; j++)
{
if (!strcmp(MyACC[i].name, MyACC[j].name) && !MyACC[j].flag_print)
{
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", j,MyACC[j].money,
MyACC[j].date, MyACC[j].name, MyACC[j].type, MyACC[j].ps);
MyACC[j].flag_print = 1;
}
}
}
}
/*************************************************************************************************************************/
void data_report() //统计
{
printf("请输入需要统计的日期区间,如:20190909 20190918\n");
int a, b;
scanf("%d %d", &a, &b);
printf("\n%d %d", a, b);
int sumplus = 0, summinus = 0, sum = 0;
for (int j = 1; j <= cnt; j++)
{
if (MyACC[j].dateint >= a && MyACC[j].dateint <= b)
{
if (MyACC[j].money>0)
{
sum += MyACC[j].money;
sumplus += MyACC[j].money; //统计该时段的盈余
}
if(MyACC[j].money<0)
{
sum += MyACC[j].money;
summinus += MyACC[j].money; //统计该时段的亏损
//sum是最终的营业额
}
}
}
printf("账务统计完成!\n在此阶段,收入:%d元,支出:%d元,结余:%d元\n\n", sumplus, summinus, sum);
}
/*************************************************************************************************************************/
void change() //修改
{
int flag=1; //结束标识
printf("请输入需要修改的账目序号\n");
scanf("%d", &Myid); //输入要修改账目对应的序号
// scanf("%d,&num_"); //输入修改的板块个数
//while(flag){
printf("选择要修改的账目信息类型,1代表收支金额,2代表交易日期,3代表收支项名称,4代表收支类型,5代表备注信息 6则修改所有\n");
scanf("%d", &key); //选择要修改的板块 (1-6)
if (key == 1){
printf("收支金额:");
scanf("%d", MyACC[Myid].money);
getchar();
}
else if (key == 2){
printf("日期:");
scanf("%s", MyACC[Myid].date);
getchar();
fflush(stdin);
}
else if (key == 3){
printf("名称:");
scanf("%s", MyACC[Myid].name);
getchar();
fflush(stdin);
}
else if (key == 4){
printf("类型:");
scanf("%s", MyACC[Myid].type);
getchar();
fflush(stdin);
}
else if (key == 5){
printf("备注:");
scanf("%s", MyACC[Myid].ps);
getchar();
fflush(stdin);
}
printf("修改成功!\n修改后该条账目为:\nid:%d money:%d date:%s name:%s type:%s ps:%s\n", Myid,
MyACC[Myid].money, MyACC[Myid].date, MyACC[Myid].name, MyACC[Myid].type, MyACC[Myid].ps);
//printf("0:结束修改 1:继续修改\n");
//scanf("%d",flag);
//getchar();
//}
//printf("abab");
//return;
}
/*************************************************************************************************************************/
void query() //查询账目,得到的结果就是按照序号,日期,名称,金额查询的结果
{
int flag=0; //表示查询结果
printf("查询全部记录输入1,按字段查询输入2\n");
scanf("%d", &key);
if (key == 1) //1 查询全部记录
{
//查询全部记录
printf("查询成功!\n\n");
for (int i = 1; i <= cnt; i++)
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", MyACC[i].id, MyACC[i].money,
MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
}
else if(key == 2) //2 按字段查询输入
{
printf("请输入查询所依据的字段\n1:序号\n2:日期\n3:名称\n4:金额\n");
scanf("%d", &key);
printf("请输入想查询字段的内容\n");
if (key == 1) //序号
{
scanf("%d", &tmpi);
//获取目标Id数据条目在数组里的索引
int targetDataItemIndex = 0;
targetDataItemIndex = FindDataItemIndexById(tmpi);
if(targetDataItemIndex==0)
{
printf("目标不存在\n");
return;
}
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", tmpi,MyACC[targetDataItemIndex].money, MyACC[targetDataItemIndex].date,MyACC[targetDataItemIndex].name, MyACC[targetDataItemIndex].type, MyACC[targetDataItemIndex].ps);
printf("查询成功!\n\n");
flag=1;
}
else if (key == 2) //日期
{
scanf("%s", tmps);
for (int i = 1; i <= cnt; i++)
{
if (strcmp(MyACC[i].date, tmps) == 0)
{
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", MyACC[i].id,MyACC[i].money, MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
flag=1; //查询成功
}
}
}
else if (key == 3) //名称
{
scanf("%s", tmps);
for (int i = 1; i <= cnt; i++)
{
if (strcmp(MyACC[i].name, tmps) == 0)
{
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", i,MyACC[i].money, MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
flag=1; //查询成功
}
}
}
else if (key == 4) //金额
{
char tmp;
//cin >> tmp; //键盘输入金额符号(正还是负)
cin >> tmpi; //键盘输入具体金额
for (int i = 1; i <= cnt; i++)
{
if (tmpi == MyACC[i].money)
{
printf("id:%d money:%d date:%s name:%s type:%s ps:%s\n\n", i, MyACC[i].money, MyACC[i].date, MyACC[i].name, MyACC[i].type, MyACC[i].ps);
flag=1; //查询成功
}
}
//然后进行修改操作,修改操作参考 void change()
}
if(!flag)
printf("目标不存在!\n");
else
printf("查询完毕!\n");
}
else //3等其他错误输入
{
printf("数据输入错误,请重新选择:\n");
return;
}
}
//依据序号查找数据条目索引,这个索引就是目标数据在MACC数组里的下标
int FindDataItemIndexById(int dataId)
{
for (int i = 0; i <= cnt; i++)
{
if (MyACC[i].id == dataId)
{
return i;
}
}
cout << "依据序号查找数据条目索引失败,序号:" << dataId << "不存在" << endl;
return -1;
}
#endif