我写了一个像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);
}
*/
答案 0 :(得分:1)
当您保存/恢复的对象使用堆内存时,您无法使用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);
答案 1 :(得分:1)
您的问题是您在文件中编写Database
结构并且它包含一个指针(ownerName
)。你不能像这样序列化一个C字符串,因为你只需将指针值写入文件中,这对于不同的运行是非敏感的。
为简化起见,我建议您将ownerName
定义为某个大小的char
数组:
char ownerName[MAX_OWNER_NAME_LENGTH];
数组嵌入到结构中,因此可以在以后正确编写和读回。