工程实践:基于C/C++的学生账目管理系统(个人账本管理系统)

前言

如题,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
  • 17
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值