【C语言程序设计第四版】练习12-7
#include <string.h> #include <stdlib.h> #include <stdio.h> long size; struct LogData{ long logid; char logdate[11]; char lognote[15]; double charge; double balance; }; int inputchoise(void){ int mychoise; printf("\nEnter your choice:\n"); printf("1-Add a new cash LOG.\n2-List All Cash LOG.\n"); printf("3-Query Last Cash LOG.\n4-Update cash LOG.\n0-End program.\n"); scanf("%d", &mychoise); return mychoise; } long getLogcount(FILE *cfptr){ long begin,end,logcount; fseek(cfptr, 0L, SEEK_SET); begin = ftell(cfptr); fseek(cfptr, 0L, SEEK_END); end = ftell(cfptr); logcount = (end-begin)/size; // printf("logcount = %ld\n",logcount); return logcount; } void UpdateLog(FILE *cfptr){ struct LogData c_log,o_log,f_log; long logcount; int id, w_flag; w_flag=0; logcount = getLogcount(cfptr); if (logcount != 0) { printf("Enter the update id:\n"); scanf("%d", &id); if (id > logcount) { printf("Input id is error!\n"); return; }else{ if (id == 1) { o_log.logid = id; printf("Input logdate(format: 2006-01-01):"); scanf("%s", o_log.logdate); printf("Input lognote:");scanf("%s", o_log.lognote); printf("Input Charge: Income+and expend-:"); scanf("%lf", &o_log.charge); o_log.balance = o_log.charge; fseek(cfptr, 0L, SEEK_SET); //到文件头部文件指针 fwrite(&o_log, size, 1, cfptr); while (!feof(cfptr)) { if (w_flag) { fseek(cfptr, -size, SEEK_CUR); c_log.balance = o_log.balance + c_log.charge; o_log = c_log; fwrite(&o_log, size, 1, cfptr); } fread(&c_log, size, 1, cfptr); w_flag = 1; } }else{ fseek(cfptr, size*(id-2), SEEK_SET); //把上一个的余额算出来 fread(&f_log, size, 1, cfptr); o_log.logid = id; printf("Input logdate(format: 2006-01-01):"); scanf("%s", o_log.logdate); printf("Input lognote:");scanf("%s", o_log.lognote); printf("Input Charge: Income+and expend-:"); scanf("%lf", &o_log.charge); o_log.balance = f_log.balance + o_log.charge; // printf("ftell = %ld\n", ftell(cfptr)); // 这里有一个问题,理论前面的了文件,这里写入刚好,打印出来文件指针的位置也是对的,但写入就不对,本来不需要这个 // 我的个人理解是读写缓存取的原理不一样,前面是读的缓存区,直接写入的话,不合适,需要对文件指针进行一步操作。 // 也就是在读写切换的时候,需要对文件指针的位置进行确认操作。 // fseek(cfptr, size*(id-1), SEEK_SET); ftell(cfptr); fwrite(&o_log, size, 1, cfptr); // printf("_blksize %d",cfptr->_blksize); // printf("_lbfsize %d",cfptr->_lbfsize); while (!feof(cfptr)) { if (w_flag) { fseek(cfptr, -size, SEEK_CUR); c_log.balance = o_log.balance + c_log.charge; o_log = c_log; fwrite(&o_log, size, 1, cfptr); } fread(&c_log, size, 1, cfptr); w_flag = 1; } } } }else printf("no log in file!\n"); } void ListAllLog(FILE *cfptr){ struct LogData log; fseek(cfptr, 0L, SEEK_SET); fread(&log, size, 1, cfptr); printf("logid logdate lognote charge balance\n"); while (!feof(cfptr)) { printf("%6ld %-11s %-15s %10.2lf %10.2lf\n", log.logid, log.logdate, log.lognote, log.charge, log.balance); fread(&log, size, 1, cfptr); } } void QueryLastLog(FILE *cfptr){ struct LogData log; long logcount; logcount = getLogcount(cfptr); if (logcount>0) { fseek(cfptr, size*(logcount-1), SEEK_SET); fread(&log, size, 1, cfptr); printf("The last log is:\n"); printf("logid:%-6ld\nlogdata:%-11s\nlognote:%-15s\n", log.logid, log.logdate,log.lognote); printf("charge:%-10.2lf\nbalance:%-10.2f\n", log.charge, log.balance); }else printf("no log in file!\n"); } void AddNewLog(FILE *cfptr){ struct LogData log, lastlog; long logcount; // logcount=getLogcount(cfptr); printf("Input logdate(format: 2006-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(cfptr); // printf("AddNewLog_logcount=%ld\n", logcount); if (logcount>0) { fseek(cfptr, size*(logcount-1), SEEK_SET); fread(&lastlog, size, 1, cfptr); log.logid = lastlog.logid + 1; log.balance = log.charge + lastlog.balance; }else{ log.logid =1; log.balance = log.charge; } fwrite(&log, sizeof(struct LogData), 1, cfptr); rewind(cfptr); printf("logid=%ld\n", log.logid); } int main(void){ FILE *fp; int choice; if ((fp=fopen("cashbox.dat", "r+"))==NULL) { printf("can not open file cashbox.dat!\n"); exit(0); } size = sizeof(struct LogData); while ((choice = inputchoise()) != 0) { switch (choice) { case 1: AddNewLog(fp); break; case 2: ListAllLog(fp); break; case 3: QueryLastLog(fp);break; case 4: UpdateLog(fp);break; default: printf("Input Error."); break; } } if (fclose(fp)) { printf("Can not close the file!\n"); exit(0); } return 0; }