首页 > 解决方案 > C二进制文件不更新/读取

问题描述

下面我提供了我的代码。我将根据提供的帐号“存款”。姓名、帐号和余额都在下面的“accounts.dat”文件中。

Herman T Travis 3 $500
Sam L Travis 1 $40
Henry O Billiam 2 $6000

我不确定它是我创建文件的方式(使用简单的 vi 编辑器)还是我的代码中的问题,但是当我运行它并将帐号和余额提供给程序时不会报告新的余额文件。有什么建议么?

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char first[15];
    char middle[2];
    char last[15];
    float balance;
    long int acct;
} data;

int main() {
    int choice = -1, i = 0, n = 0;
    long int number;
    double amount;
    FILE *aPtr;
    data accounts[50];

    aPtr = fopen("accounts.dat", "ab+");/* Opens file for read/write; appends to file if exist */

    if (aPtr == NULL) {
        printf("File could not be opened");
        exit(1);
    }

    fseek(aPtr, 0, SEEK_SET); /* Moving pointer to start of file*/

    while (fread(accounts + 1, sizeof(data), 1, aPtr) == 1) /* Read and store info in file, into accounts array */

        i++;
        n = i; /* Num. of records in file */

        do {
            printf("Select Option\n" );
            printf("0: Exit\n1: Deposit\n2: Withdrawl\n3: Add Account\n4: Remove Account\n5: Balance Inquiry\n6: View Accounts\n: ");
            scanf("%d", &choice);

            switch (choice) {
              case 0: /* Exit */
                fclose(aPtr);
                break;

              case 1: /* Deposit*/
                fseek(aPtr, 0, SEEK_SET);
                printf("Enter account number:\n");
                scanf("%ld", &number);
                printf("Enter amount to be deposited:\n");
                scanf("%lf", &amount);
                for (i = 0; i < n; i++) {
                    if (accounts[i].acct == number) {
                        accounts[i].balance = accounts[i].balance + amount;
                        fseek(aPtr, i * sizeof(data), SEEK_SET); /* Pointer goes to accountlocation in file*/
                        fwrite(accounts + i, sizeof(data), 1, aPtr); /* Write modified account into file */
                        break;
                    }
                }
                if (i == n) {
                    printf ( "Account does not exist\n" );
                }
                break;
            }
        } while (choice != 0);

    return 0;
}

标签: cfile

解决方案


正确填充结构是此答案的重点。

您的文件的命名约定表明它应该是一个二进制文件(即.dat行业中常用的二进制文件)。但是你显示的内容清楚地表明它是一个文本文件,所以在下面的例子中,我使用 data.txt 作为文件名。由于它是一个文本文件,并且包含定义明确的行字段,因此将内容解析为结构将非常简单

文件的格式是严格定义的,并使用空格作为分隔符。这一切都可以,但是选择一个可见的分隔符,通常不用于字段内容,例如逗号:,在不使用字段时会更容易,例如没有中间名时。但这不是必需的,以下示例将使用空格分隔符。

如果您愿意在此实现中使用fgets()and strtok()(几乎没有错误检查/处理),它提供了一个使用数据文件内容填充结构的示例:

typedef struct
{
    char first[15];
    char middle[2];
    char last[15];
    float balance;
    long int acct;
}DATA;
const char filename[] = {".\\data.txt"}; 

int lineCount(const char *fname);
DATA * populateData(int lines, const char *fname);

int main(void)
{
    int lines = lineCount(filename);//count number of accounts in file (lines in file)
    DATA *data = populateData(lines, filename);//Create and populate data structure
    if(data)
    {
        ;   //use data here
        free(data); //free data memory when finished using it.
    }

    return 0;
}


int lineCount(const char *fname)
{
    int count=0;
    char line[260];
    FILE *fp = fopen(fname, "r");
    if(fp)
    {
        while(fgets(line, 260, fp)) count++;
        fclose(fp);
    }
    return count;
}

DATA * populateData(int lines, const char *fname)
{
    int i;
    char *tok;
    char *endPtr;
    char line[260];
    DATA *data = calloc(lines, sizeof(*data ));
    if(data)
    {
        FILE *fp = fopen(fname, "r");
        if(fp)
        {
            for(i=0;i<lines;i++)
            {
                if(fgets(line, 260, fp))
                {
                    //get first name
                    tok = strtok(line, " ");
                    if(tok)
                    {
                        strcpy(data[i].first, tok);
                        //get Middle name
                        tok = strtok(NULL, " ");
                        if(tok)
                        {
                            strcpy(data[i].middle, tok);
                            //get last name
                            tok = strtok(NULL, " ");
                            if(tok)
                            {
                                strcpy(data[i].last, tok);
                                //get balance
                                tok = strtok(NULL, " ");
                                if(tok)
                                {
                                    data[i].acct = atoi(tok);
                                    //get acct
                                    tok = strtok(NULL, "$");
                                    if(tok)
                                    {
                                        data[i].balance = strtod(tok, &endPtr);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            fclose(fp);
        }
    }

    return data;    
}

推荐阅读