【程序设计与实践】实验二:个人资金账户管理

实验二:个人资金账户管理

题目:

阅读下列“资金账户的管理”程序,对程序进行调试、改错,并增加函数,使之符合如下具体功能。

1) 资金账户的信息统一放在*随机文件中,该随机文件包括的数据项有记录ID、发生日期、发生事件、发生金额(正的表示收入,负的表示支出)和金额。每发生一笔收支,文件要增加一条记录,并计算一次余额。
在这里插入图片描述

2) 程序实现3个功能,包括:
(1) 能创建资金账户文件并添加收入或支出信息记录
(2) 能显示所有记录,得知资金账户的收支流水账;
(3) 能查询最后一条记录,获知账户最后的余额。
账户文件名命名为cashbox.dat,文件部分内容如下;

cashbox.dat
LongID CreateDateNote Charge Balance
1 2006-06-01 alimony 500.00 500.00
2 2006-06-08 shopping -300.00 200.00
3 2006-06-15 shopping -60.00 140.00
4 2006-06-20 workingpay 200.00 340.00
5 2006-08-01 scholarship 1000.00 1340.00

2) 增加修改资金账户的功能。输入一个记录ID,如果文件中已存在该记录,则输入新的记录信息并更新资金账户文件中相应记录的信息。
要求定义和调用函数UpdateLog(),其功能是修改资金账户记录。

3) 增加删除资金账户的功能。输入一个记录ID,如果文件中已存在该记录,则删除该记录信息。
要求定义和调用函数Deletelog(),其功能是删除资金账户记录。

注释

随机读写是按你给的地点读写,(用 fseek 等函数找地点),可以在文件的任何地方–开始处,文件尾,文件中部,前前后后地读写。顺序读写 是从文件开始处依次读,从文件尾开始依次写。
对文件的读写操作可按指定的字节号进行。即可以通过调用库函数去指定开始读或写的字节号,然后直接对该位置上的数据进行读或写操作。

“b”是二进制模式//
if((fp=fopen(“cashbox.dat”,“ab+”))==NULL){
"a+"模式:
打开文件进行“读写”操作,即既可读取,又可写入
若欲操作的文件不存在,则新建文件
成功打开文件时,文件指针位于文件结尾
打开文件后,不会清空文件内原有内容
读取内容时,可以在任意位置进行,但写入内容时,只会追加在文件尾部

fp1=fopen(“cashbox.dat”,“wb+”);
"w+"模式:
1.打开文件进行“读写”操作,即既可读取,又可写入。
2.若欲操作的文件不存在,则新建文件。
3.成功打开文件时,文件指针位于文件开头。
4.打开文件后,会清空文件内原有的内容。
5.无论是读取内容还是写入内容,都可在文件中任意位置进行,且进行写入操作时,会覆盖原有位置的内容。

fseek函数设置文件指针cfp的位置(从SEEK_SET开始移动size*(logcount-1))
(0L不移动)SEEK_SET文件头 SEEK_END文件尾

ftell用于得到文件位置指针当前位置相对于文件首的偏移字节数

rewind(cfp);//重设文件指针

fread(&log,size,1,cfp); /1.读取到的位置指针 2.一个对象的字节大小 3.对象个数 4.要读的目标指针/

fwrite(plog,size,logcount,cfp);

附录

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <string.h>
#include <conio.h>

long size;	

/*当前最近一次的流水号*/
				
struct LogData{					/*记录的结构*/
    long logid;					/*记录ID*/
    char logdate[11];			/*记录发生日期*/
    char lognote[15];			/*记录事件说明*/
    double charge;				/*发生费用:负表示支出,正表示收入*/
    double balance;				/*余额*/
};


int inputchoice()/*选择操作参数*/
{
	system("cls");
	int mychoice;
	printf("\n");
	printf("\n");
	printf("                     程序设计与实践        实验(二) 个人资金账户管理\n");
	printf("\n");
	printf("      Personal Cashbox Management\n");
	printf("     =============================                   \n");
	printf("      1 - Add a new cash log.\n      2 - List all cash log.\n");
	printf("      3 - Query last cash log.\n      4 - Update a cash log.\n");
	printf("      5 - Delete a cash log.\n      0 - End program.\n"); 
	printf("\n");
	printf("   Enter your choice:");
	scanf("%d",&mychoice);
	return mychoice;
}


long getLogcount(FILE *cfp) 	/*获取文件记录总数*/
{  
	long begin,end,logcount;
	fseek(cfp,0L,SEEK_SET);		//SEEK_SET文件头 
	begin=ftell(cfp);			//ftell用于得到文件位置指针当前位置相对于文件首的偏移字节数 
	fseek(cfp,size,SEEK_END);	//SEEK_END文件尾 
	end=ftell(cfp);
	logcount=(end-begin)/size -1;
   	return logcount;
}

void AddNewLog(FILE *cfp)             /*添加新记录*/
{
    struct LogData log,lastlog;
    long logcount;
    printf("Input logdate(format:2020-01-01):");
    scanf("%s",log.logdate);
    printf("Input lognote:");
    scanf("%s",log.lognote);
    printf("Input Charge:Income+ and expend-:");
    scanf("%lf",&log.charge);    
    logcount=getLogcount(cfp);                    /*获取记录数*/
	if(logcount>0){
        fseek(cfp,size*(logcount-1),SEEK_SET);    /*fseek函数设置文件指针cfp的位置(从SEEK_SET开始移动size*(logcount-1))*/
        fread(&lastlog,size,1,cfp);              /*读入最后记录*/
		log.logid=lastlog.logid+1;                    /*记录号按顺序是上次的号+1*/
        log.balance=log.charge+lastlog.balance;
    }
    else{                                        /*如果文件是初始,记录数为0*/
        log.logid=1;
        log.balance=log.charge;
    }
    rewind(cfp);//重设文件指针
    getch();    //等待按下任意键,再继续执行下面的语句
    fwrite(&log,sizeof(struct LogData),1,cfp);    /*写入记录*/
    fclose(cfp);
}

void ListAllLog(FILE *cfp)				/*列出所有收支流水帐*/
{
	struct LogData log;
	long logcount;
	logcount=getLogcount(cfp);
	if(logcount>0){						/*表示有记录存在*/	
		fseek(cfp,0L,SEEK_SET);			/*定位指针到文件开始位置,0L—不移动*/
		fread(&log,size,1,cfp);			/*1.读取到的位置指针 2.一个对象的字节大小 3.对象个数 4.要读的目标指针*/
		printf("LogID  LogDate      LogNote            Charge     Balance\n");
		while(!feof(cfp)){				//检测文件结束符,如果文件结束,则返回非0值,否则返回0 
			printf("%5ld  %-12s %-15s %10.2lf %10.2lf\n",
log.logid,log.logdate,log.lognote,log.charge,log.balance);
			fread(&log,size,1,cfp);
		}
	}
	else	printf("no logs in file!\n");
	
	printf("\n");
	printf("Press any key to continue...");
	
	system("pause");
}

void QueryLastLog(FILE *cfp)					/*查询显示最后一条记录*/
{
	struct LogData log;
	long logcount;
	logcount=getLogcount(cfp);
	if(logcount>0){								/*表示有记录存在*/
		fseek(cfp,size*(logcount-1),SEEK_SET);	/*定位最后一条记录*/
	    fread(&log,size,1,cfp);			 		/*读取最后一条记录*/
	    printf("The last log is:\n");			/*显示最后一条记录*/
	    printf("            LogID:%-6ld\n            LogDate:%-11s\n            LogNote:%-15s\n",
log.logid,log.logdate,log.lognote);
		printf("            Charge:%-10.2lf\n           *Balance:%-10.2lf\n",
log.charge,log.balance);
	}
	else	printf("no logs in file!\n");
	
	printf("\n");
    printf("Press any key to continue...");
	getch();

}


/*函数功能:查询记录 ID 并更新账户记录*/
void Updatelog(FILE *cfp){
	struct LogData log[1000],*plog=log,newlog;	/*假定文件不超过1000记录*/ 
//plog=log数组首地址? 

	long logcount,logid,i,index=-1;

 	printf("Input LogID:"); 
 	scanf("%ld",&logid);						/*输入要修改的记录 ID*/ 

/*查找帐户号是否存在,若存在则更新*/ 
	logcount=getLogcount(cfp);				/*获取记录数*/ 
	rewind(cfp);
	fread(plog,size,logcount,cfp);			//相当于copy?从文件中读到数组中 
	for(i=0;i<logcount;i++){
		if(logid==log[i].logid){			/*已经找到*/ 
			printf("LogID  LogDate      LogNote            Charge     Balance\n");/*显示当前记录*/
			printf("%5ld  %-12s %-15s %10.2lf %10.2lf\n",
log[i].logid,log[i].logdate,log[i].lognote,log[i].charge,log[i].balance);
			index=i;
			break;
   		} 
	} 
	rewind(cfp); 
	if(index>=0){
		printf("Input logdate(format:2020-01-01):");
		scanf("%s",newlog.logdate); 
		printf("Input lognote:");
		scanf("%s",newlog.lognote); 
		printf("Input Charge:Income+ and expend-:");
		scanf("%lf",&newlog.charge);
		if(strcmp(log[index].lognote,newlog.lognote)!=0)//比较,如果不相同,则修改 
    		strcpy(log[index].lognote,newlog.lognote); 
		if(strcmp(log[index].logdate,newlog.logdate)!=0) 
			strcpy(log[index].logdate,newlog.logdate); 
/*如果输入的收支额度改变,重新计算余额*/ 
		if(newlog.charge!=log[index].charge){	
  			newlog.balance=log[index].balance-log[index].charge+newlog.charge; /*计算新余额*/
    		log[index].charge=newlog.charge;	/*更新收支*/ 
    		log[index].balance=newlog.balance;	/*更新余额*/
/*当前记录之后的每条记录余额信息更新*/
    		for(i=index+1;i<logcount;i++)
      			log[i].balance=log[i-1].balance+log[i].charge;
  		}
		rewind(cfp);
		fwrite(plog,size,logcount,cfp);		/*更新回文件*/
  
	}
	else{  
		printf("Error logid and try another!\n");
		printf("Press any key to continue...");
		getch();
	}
 	fclose(cfp);
}


/*函数功能:查询记录 ID 并删除该账户记录*/ 
void Deletelog(FILE *cfp){ 
	FILE *fp1;
	struct LogData log[1000],*plog=log;/*假定文件不超过 1000 记录*/
	long logcount,logid,i,index=-1; 

	printf("Input LogID:"); 
	scanf("%ld",&logid);				/*输入要删除的记录 ID*/ 

/*查找帐户号是否存在,若存在则更新*/ 
	logcount=getLogcount(cfp);			/*获取记录数*/ 
	rewind(cfp); 
	fread(plog,size,logcount,cfp); 		//从文件中读到数组中 
	for(i=0;i<logcount;i++){ 
		if(logid==log[i].logid){ 		/*已经找到,显示当前记录*/
   			printf("LogID  LogDate      LogNote            Charge     Balance\n");
   			printf("%5ld  %-12s %-15s %10.2lf %10.2lf\n",
log[i].logid,log[i].logdate,log[i].lognote,log[i].charge,log[i].balance);
			index=i;
   			getch();
   			break; 
		} 
	} 
	printf("\n"); 
	
	rewind(cfp); 
	if(index>=0){ 
    	for(i=index;i<=logcount-1;i++){	//将index之后的数据整体前移 
	  		log[i].logid=i+1;
      		strcpy(log[i].logdate,log[i+1].logdate); 
       		strcpy(log[i].lognote,log[i+1].lognote); 
      		log[i].charge=log[i+1].charge;
	  		log[i].balance=log[i-1].balance+log[i].charge;
		}
	printf("Now\n");
	printf("LogID  LogDate      LogNote            Charge     Balance\n");
    for(i=0;i<logcount-1;i++){			/*输出当前new记录*/
    	printf("%5ld  %-12s %-15s %10.2lf %10.2lf\n",
log[i].logid,log[i].logdate,log[i].lognote,log[i].charge,log[i].balance);
	}
	getch();
	fp1=fopen("cashbox.dat","wb+");
//打开文件后,会清空文件内原有的内容。 
/*
"w+"模式:
1.打开文件进行“读写”操作,即既可读取,又可写入。
2.若欲操作的文件不存在,则新建文件。
3.成功打开文件时,文件指针位于文件开头。
4.打开文件后,会清空文件内原有的内容。
5.无论是读取内容还是写入内容,都可在文件中任意位置进行,且进行写入操作时,会覆盖原有位置的内容。
"b"表示二进制; 
*/	
	fwrite(plog,size,logcount-1,fp1);/*写回去更新*/
	fclose(fp1);
 	}
	else{
		printf("Error logid and try another!\n");
  		printf("Press any key to continue...");
  		getch();
	} 
}


int main(void)
{
	FILE *fp;
	int choice;
	if((fp=fopen("cashbox.dat","ab+"))==NULL){
//打开文件后,不会清空文件内原有内容 
/*
"a+"模式:
打开文件进行“读写”操作,即既可读取,又可写入
若欲操作的文件不存在,则新建文件
成功打开文件时,文件指针位于文件结尾
打开文件后,不会清空文件内原有内容
读取内容时,可以在任意位置进行,但写入内容时,只会追加在文件尾部
"b"表示二进制;
*/	
		printf("can not open file cashbox.dat!\n");
		exit(0);//退出程序 
    }
	size=sizeof(struct LogData);//一个结构体所占的字节—52? 
	while((choice=inputchoice())!=0){
		switch(choice){
			case 1:
			    fp=fopen("cashbox.dat", "ab+");
				AddNewLog(fp);break;/*添加新记录*/

			case 2:
	        	fp=fopen("cashbox.dat", "ab+");
				ListAllLog(fp);break;/*列出所有的收入支出情况*/
				
			case 3:
			 	fp=fopen("cashbox.dat", "ab+");
				QueryLastLog(fp);break;/*查询最后的余额*/
				
			case 4:
				fp=fopen("cashbox.dat", "rb+");
				Updatelog(fp);break;/*新增语句更新资金账户记录*/ 
				
			case 5:
				fp=fopen("cashbox.dat", "rb+");
				Deletelog(fp);break;/*删除一条资金账户记录*/ 
				
			default:
				printf("Input Error.");break;
		}
	}
	
    if(fclose(fp)){//如果关闭成功返回 0,否则返回EOF(-1)
		printf( "Can not close the file!\n" );
        exit(0);//退出程序 
    }
    
}


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值