【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("
Enter your choice:
");
    printf("1-Add a new cash LOG.
2-List All Cash LOG.
");
    printf("3-Query Last Cash LOG.
4-Update cash LOG.
0-End program.
");
    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
",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:
");
        scanf("%d", &id);
        if (id > logcount) {
            printf("Input id is error!
");
            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
", 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!
");
    
}

void ListAllLog(FILE *cfptr){
    struct LogData log;
    fseek(cfptr, 0L, SEEK_SET);
    fread(&log, size, 1, cfptr);
    printf("logid   logdate     lognote            charge     balance
");
    while (!feof(cfptr)) {
        printf("%6ld  %-11s %-15s %10.2lf %10.2lf
",
               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:
");
        printf("logid:%-6ld
logdata:%-11s
lognote:%-15s
",
               log.logid, log.logdate,log.lognote);
        printf("charge:%-10.2lf
balance:%-10.2f
",
               log.charge, log.balance);
    }else
        printf("no log in file!
");
}

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
", 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
", log.logid);
}


int main(void){
    FILE *fp; int choice;
    
    if ((fp=fopen("cashbox.dat", "r+"))==NULL) {
        printf("can not open file cashbox.dat!
");
        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!
");
        exit(0);
    }
    
    return 0;
}