为什么文件意外更改?
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 使用堆内存时,您不能使用 fwrite
和 fread
从磁盘保存和恢复数据。
如果您希望能够使用fwrite
和fread
来保存和恢复数据,您应该将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);
您的问题是您在文件中编写了 Database
s 结构并且它包含一个指针 (ownerName
)。你不能像这样序列化 C 字符串,因为你只是将指针值写入文件,这在不同的运行中是无意义的。
为了简化,我建议您将 ownerName
定义为某个大小的 char
数组:
char ownerName[MAX_OWNER_NAME_LENGTH];
数组嵌入到结构中,所以它会被正确写入并稍后读回。
我写了一个程序,它的操作类似于 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 使用堆内存时,您不能使用 fwrite
和 fread
从磁盘保存和恢复数据。
如果您希望能够使用fwrite
和fread
来保存和恢复数据,您应该将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);
您的问题是您在文件中编写了 Database
s 结构并且它包含一个指针 (ownerName
)。你不能像这样序列化 C 字符串,因为你只是将指针值写入文件,这在不同的运行中是无意义的。
为了简化,我建议您将 ownerName
定义为某个大小的 char
数组:
char ownerName[MAX_OWNER_NAME_LENGTH];
数组嵌入到结构中,所以它会被正确写入并稍后读回。