为什么文件意外更改?

时间:2015-01-17 07:45:17

标签: c file

我写了一个像ATM一样操作的程序。它接收卡片(通过获取卡号),将它们定义到数据库中并进行取款,存款等。 我的程序有一个defineAccount(FILE* f),可以收到卡号,所有者姓名等。并将这些信息写入文件Database.txt。另外,我有一个函数showCardInformation(FILE* f,int cardNumber),它显示了文件中定义的卡的信息。 当我第一次运行程序并在文件showCardInformation中保存卡信息正常工作但当我再次运行时,我收到此函数的运行时错误,因为文件中的卡所有者名称已更改为NULL。当文件中的卡号发生变化时,我的程序中的另一部分出现了同样的问题。为什么我遇到这个问题? 我的代码:

typedef enum myBoolean {freezed,notFreezed} Boolean;
typedef struct database
    {
        int cardNumber;
        int password;
        char* ownerName;
        int accounts;
        Boolean accessStatus;
    } Database;

void showCardInformation(FILE* f,int cardNumber)
    {
        system("cls");
        puts("This is information of your card:");
        fseek(f,sizeof(Database)*(cardNumber-1000),SEEK_SET);
        Database load;
        fread(&load,sizeof(Database),1,f);
        printf("%-15s:%d\n%-15s:%s\n%-15s:%d Rials\n","Card Number",cardNumber,"Owner name",
            load.ownerName,"Finance",load.accounts);
        return;
    }

void defineAccount(FILE* f)
{
    system("cls");
    puts("You can open a new account here.");
    puts("Enter card number:");
    scanf("%[\n]");
    char cardNumberInput[100];
    fgets(cardNumberInput,99,stdin);
//I do some confinement for user input.This is one of the confinements:
    for(int index=0;index<strlen(cardNumberInput)-1;index++)
    {
        if(!isdigit(cardNumberInput[index]))
        {
            puts("invalid card number.Defining new account failed.");
            return;
        }//if
    }//for
    if(strlen(cardNumberInput)!=5)
    {
        puts("card number must have 4 digits.Defining new account failed.");
        return;
    }
    fseek(f,sizeof(Database)*(atoi(cardNumberInput)-1000),SEEK_SET);
    Database load;
    fread(&load,sizeof(Database),1,f);
    if(load.cardNumber<10000 && load.cardNumber>=1000)
    {
        puts("This card has been already defined in database.Defining new account failed.");
        return;
    }
    puts("Enter owner name:");
    char nameInput[100];
    fgets(nameInput,99,stdin);
    //confinements


    puts("Enter password:");
    char passwordInput[100];
    fgets(passwordInput,99,stdin);
    //confinements

    puts("Enter finance(in Rials):");
    char financeInput[100];
    fgets(financeInput,99,stdin);
    //confinements

    Database newAccount={atoi(cardNumberInput),atoi(passwordInput),strdup(nameInput),
        atoi(financeInput),notFreezed};
    fseek(f,sizeof(Database)*(atoi(cardNumberInput)-1000),SEEK_SET);
    fwrite(&newAccount,sizeof(Database),1,f);
return;
}

我已按如下方式初始化文件:

/*
    DatabaseFile=fopen("Database.txt","w");
    Database blank={0,0,"",0,freezed};
    for(int accounts=1000;accounts<10000;accounts++)
    {
        fwrite(&blank,sizeof(Database),1,DatabaseFile);
    }
    */

2 个答案:

答案 0 :(得分:1)

当您保存/恢复的对象使用堆内存时,您无法使用fwritefread来保存和恢复磁盘中的数据。

如果您希望能够使用fwritefread来保存和恢复数据,则应将struct database更改为:

typedef struct database
{
   int cardNumber;
   int password;
   char ownerName[100];
   int accounts;
   Boolean accessStatus;
} Database;

如果将ownerName移动到最后一个成员,将更容易在对象上创建。

typedef struct database
{
   int cardNumber;
   int password;
   int accounts;
   Boolean accessStatus;
   char ownerName[100];
} Database;

然后,您可以使用:

Database newAccount=
{
   atoi(cardNumberInput),
   atoi(passwordInput),
   atoi(financeInput),
   notFreezed
};
strcpy(newAccount.ownerName, nameInput);

答案 1 :(得分:1)

您的问题是您在文件中编写Database结构并且它包含一个指针(ownerName)。你不能像这样序列化一个C字符串,因为你只需将指针值写入文件中,这对于不同的运行是非敏感的。

为简化起见,我建议您将ownerName定义为某个大小的char数组:

char ownerName[MAX_OWNER_NAME_LENGTH];

数组嵌入到结构中,因此可以在以后正确编写和读回。