为什么文件意外更改?

Why file changes unexpectedly?

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

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);
    }
    */

当您的对象 saving/restoring 使用堆内存时,您不能使用 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);

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

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

char ownerName[MAX_OWNER_NAME_LENGTH];

数组嵌入到结构中,所以它会被正确写入并稍后读回。