#include <stdio.h>
#include <stdlib.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(" ============================= 24计科A2班宋培元 2025.6.16 \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(" Enter your choice:");
scanf("%d", &mychoice);
while (getchar() != '\n'); // 清除输入缓冲区
return mychoice;
}
long getLogcount(FILE *cfptr) /*获取文件记录总数*/
{
long count = 0;
if (cfptr == NULL) return 0;
fseek(cfptr, 0, SEEK_END);
count = ftell(cfptr) / size;
return count;
}
void ListAllLog(FILE *cfptr) /*列出所有收支流水帐*/
{
struct LogData log;
if (cfptr == NULL) return;
fseek(cfptr, 0, SEEK_SET);
printf("\n所有收支记录:\n");
printf("ID\t日期\t\t摘要\t\t金额\t余额\n");
while (fread(&log, size, 1, cfptr) == 1) {
printf("%ld\t%s\t%s\t%.2f\t%.2f\n",
log.logid, log.logdate, log.lognote, log.charge, log.balance);
}
printf("\n按任意键继续...");
getch();
}
void QueryLastLog(FILE *cfptr) /*查询显示最后一条记录*/
{
struct LogData log;
long count;
if (cfptr == NULL) return;
count = getLogcount(cfptr);
if (count == 0) {
printf("\n没有记录!\n");
getch();
return;
}
fseek(cfptr, (count - 1) * size, SEEK_SET);
if (fread(&log, size, 1, cfptr) == 1) {
printf("\n最后一条记录:\n");
printf("ID: %ld\n日期: %s\n摘要: %s\n金额: %.2f\n余额: %.2f\n",
log.logid, log.logdate, log.lognote, log.charge, log.balance);
}
printf("\n按任意键继续...");
getch();
}
void AddNewLog(FILE *cfptr) /*添加新记录*/
{
struct LogData log;
long count;
if (cfptr == NULL) return;
count = getLogcount(cfptr);
log.logid = count + 1;
printf("\n添加新记录:\n");
printf("输入日期 (YYYY-MM-DD): ");
scanf("%10s", log.logdate);
while (getchar() != '\n'); // 清除输入缓冲区
printf("输入摘要 (最多14个字符): ");
fgets(log.lognote, 15, stdin);
log.lognote[strcspn(log.lognote, "\n")] = 0; // 去除换行符
printf("输入金额 (正数为收入,负数为支出): ");
scanf("%lf", &log.charge);
while (getchar() != '\n'); // 清除输入缓冲区
// 计算余额
if (count > 0) {
fseek(cfptr, (count - 1) * size, SEEK_SET);
struct LogData lastLog;
fread(&lastLog, size, 1, cfptr);
log.balance = lastLog.balance + log.charge;
} else {
log.balance = log.charge;
}
// 写入新记录
fseek(cfptr, 0, SEEK_END);
fwrite(&log, size, 1, cfptr);
printf("\n记录添加成功!\n");
printf("ID: %ld\n日期: %s\n摘要: %s\n金额: %.2f\n余额: %.2f\n",
log.logid, log.logdate, log.lognote, log.charge, log.balance);
printf("\n按任意键继续...");
getch();
}
/*函数功能:更新记录 ID 并修改该账户记录*/
void Updatelog(FILE *cfptr)
{
long id, count;
struct LogData log;
if (cfptr == NULL) return;
count = getLogcount(cfptr);
if (count == 0) {
printf("\n没有记录可更新!\n");
getch();
return;
}
printf("\n更新记录:\n");
printf("输入要更新的记录ID: ");
scanf("%ld", &id);
while (getchar() != '\n'); // 清除输入缓冲区
if (id < 1 || id > count) {
printf("\n无效的记录ID!\n");
getch();
return;
}
// 定位到记录
fseek(cfptr, (id - 1) * size, SEEK_SET);
if (fread(&log, size, 1, cfptr) != 1) {
printf("\n读取记录失败!\n");
getch();
return;
}
printf("\n当前记录信息:\n");
printf("ID: %ld\n日期: %s\n摘要: %s\n金额: %.2f\n余额: %.2f\n",
log.logid, log.logdate, log.lognote, log.charge, log.balance);
printf("\n输入新日期 (YYYY-MM-DD, 留空则不修改): ");
char temp[11];
if (fgets(temp, 11, stdin) && temp[0] != '\n') {
strncpy(log.logdate, temp, 10);
log.logdate[10] = '\0';
}
printf("输入新摘要 (最多14个字符, 留空则不修改): ");
if (fgets(temp, 15, stdin) && temp[0] != '\n') {
strncpy(log.lognote, temp, 14);
log.lognote[14] = '\0';
}
printf("输入新金额 (正数为收入,负数为支出, 留空则不修改): ");
if (fgets(temp, 20, stdin) && temp[0] != '\n') {
log.charge = atof(temp);
}
// 重新计算余额
double oldCharge = log.charge;
if (id == 1) {
log.balance = log.charge;
} else {
fseek(cfptr, (id - 2) * size, SEEK_SET);
struct LogData prevLog;
fread(&prevLog, size, 1, cfptr);
log.balance = prevLog.balance + log.charge;
}
// 写入更新后的记录
fseek(cfptr, (id - 1) * size, SEEK_SET);
fwrite(&log, size, 1, cfptr);
// 更新后续记录的余额
if (id < count) {
double balanceDiff = log.balance - (log.balance - oldCharge + log.charge);
struct LogData nextLog;
for (long i = id; i < count; i++) {
fseek(cfptr, i * size, SEEK_SET);
fread(&nextLog, size, 1, cfptr);
nextLog.balance += balanceDiff;
fseek(cfptr, i * size, SEEK_SET);
fwrite(&nextLog, size, 1, cfptr);
}
}
printf("\n记录更新成功!\n");
printf("ID: %ld\n日期: %s\n摘要: %s\n金额: %.2f\n余额: %.2f\n",
log.logid, log.logdate, log.lognote, log.charge, log.balance);
printf("\n按任意键继续...");
getch();
}
/*函数功能:查询记录 ID 并删除该账户记录*/
void Deletelog(FILE *cfptr)
{
long id, count;
struct LogData log;
FILE *tempFile;
if (cfptr == NULL) return;
count = getLogcount(cfptr);
if (count == 0) {
printf("\n没有记录可删除!\n");
getch();
return;
}
printf("\n删除记录:\n");
printf("输入要删除的记录ID: ");
scanf("%ld", &id);
while (getchar() != '\n'); // 清除输入缓冲区
if (id < 1 || id > count) {
printf("\n无效的记录ID!\n");
getch();
return;
}
// 创建临时文件
tempFile = fopen("temp.dat", "wb");
if (tempFile == NULL) {
printf("\n无法创建临时文件!\n");
getch();
return;
}
// 复制除要删除记录外的所有记录
fseek(cfptr, 0, SEEK_SET);
for (long i = 1; i <= count; i++) {
if (fread(&log, size, 1, cfptr) != 1) break;
if (i != id) {
// 更新ID
if (i > id) {
log.logid = i - 1;
}
fwrite(&log, size, 1, tempFile);
}
}
fclose(tempFile);
fclose(cfptr);
// 删除原文件并重命名临时文件
remove("cashbox.dat");
rename("temp.dat", "cashbox.dat");
// 重新打开文件
cfptr = fopen("cashbox.dat", "rb+");
if (cfptr == NULL) {
printf("\n无法重新打开文件!\n");
exit(1);
}
printf("\n记录删除成功!\n");
printf("\n按任意键继续...");
getch();
}
int main(void)
{
FILE *fp;
int choice;
if((fp=fopen("cashbox.dat", "ab+")) == NULL){
printf("can not open file cashbox.dat!\n");
exit(0);
}
size = sizeof(struct LogData);
while((choice=inputchoice())!=0){
switch(choice){
case 1:
AddNewLog(fp);
break; /*添加新记录*/
case 2:
ListAllLog(fp);
break;/*列出所有的收入支出情况*/
case 3:
QueryLastLog(fp);
break;/*查询最后的余额*/
case 4:
Updatelog(fp);
break;/*更新资金账户记录*/
case 5:
Deletelog(fp);
break;/*删除一条资金账户记录*/
default:
printf("Input Error.");
break;
}
}
if(fclose(fp)){
printf( "Can not close the file!\n" );
exit(0);
}
return 0;
}
改好bug发给我
最新发布