gpt4 book ai didi

C 覆盖文件中已有的记录

转载 作者:太空宇宙 更新时间:2023-11-03 23:50:32 24 4
gpt4 key购买 nike

我正在编写一个程序,该程序具有一个针对银行客户 (BankAccount) 的结构,该结构具有 3 个元素 - 帐号、客户名称和银行余额。我有一个已经有记录的文件,我有一个修改余额的功能。但是,我无法这样做。余额保持不变。我认为我的 fseek() 是错误的,但我不确定如何/为什么。我在某些可能不需要的地方使用了 fflush(stdin),但我认为这与问题无关。我发表评论是为了让你知道我的逻辑,以防万一我的概念有一些误解。这是代码:

 void modify(){

int account_number;
FILE *ptr;
BankAccount account;

ptr = fopen("account.txt", "r+");
printf("Enter account number: ");
fflush(stdin);
scanf("%d", &account_number);

while (!feof(ptr)) // To search the whole "account.txt" file.
{
fread(&account, sizeof(BankAccount), 1, ptr); //brings record into memory
if (account.account_number == account_number){ // if record's account number is same as account number entered by user above
printf("***Account found***\n\nAccount number: %d\nAccount name: %s\nAccount balance: %.2f\n", account.account_number, account.name, account.balance);
printf("\nEnter new balance: ");
fflush(stdin);
scanf("%f", &account.balance); // rewrites account's balance in memory
fseek(ptr, -sizeof(BankAccount), SEEK_CUR); //pointer seeked to the beginning of the record to overwrite it with the one in memory
fwrite(&account,sizeof(BankAccount), 1, ptr); // record overwritten
return;

}
}


printf("Account not found\n");
fflush(stdin);
getch();
}

这是我项目的整个 .cpp 文件,如果您想运行它:Source code .我会很感激一些指导。提前致谢。

最佳答案

问题可能出在 fseek() 调用上:

fseek(ptr, -sizeof(BankAccount), SEEK_CUR);

sizeof() 的返回值是无符号类型;对它的否定将是一个非常大的数字。从技术上讲,这是不正确的(fseek() 应该得到一个 long,而不是 size_t)。但是,如果 sizeof(size_t) == sizeof(long),您就可以摆脱它(它对我有用)。

问题的另一个方面可能是您在返回之前没有关闭文件(无论您是否找到记录)。那肯定是内存泄漏;它还可能影响数据写入磁盘的方式。这可能是您遇到麻烦的根本原因。您还有另一个功能,即打开文件以读取数据以查看更改,但由于文件未关闭,因此数据尚未写入磁盘。 注意:由于源代码现在可用,这就是问题的原因。

由于您没有向我们展示数据结构,另一个问题可能是 balance 成员的 floatdouble 类型不匹配;同样,唯一的问题可能是 float 是一种不适合账户余额的类型(例如,它不能可靠地表示超过约 100,000.00 美元的余额,精确到最接近的美分——例如,输入 199999.99 显示为 199999.98) .

注意:在 Linux 的现代版本中和 Windows , fflush(stdin) 是定义的操作(并且定义的行为是明智且有用的)。根据 C 标准和 POSIX,它会产生未定义的行为。使用它时要谨慎——请注意它不是可移植操作。

转换为 SSCCE ( Short, Self-Contained, Correct Example ),对您的代码稍作修改(添加 fclose())对我有用:

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

typedef struct BankAccount
{
int account_number;
char name[20];
float balance;
} BankAccount;

static void modify(void)
{
int account_number;
FILE *ptr;
BankAccount account;

ptr = fopen("account.txt", "r+");
printf("Enter account number: ");
fflush(stdin);
scanf("%d", &account_number);

while (!feof(ptr))
{
fread(&account, sizeof(BankAccount), 1, ptr);
printf("***Account read***(%d: %s: %.2f)\n",
account.account_number, account.name, account.balance);
if (account.account_number == account_number)
{
printf("***Account found***\n\nAccount number: %d\nAccount name: %s\nAccount balance: %.2f\n", account.account_number, account.name, account.balance);
printf("\nEnter new balance: ");
fflush(stdin);
scanf("%f", &account.balance);
fseek(ptr, -sizeof(BankAccount), SEEK_CUR);
fwrite(&account, sizeof(BankAccount), 1, ptr);
fclose(ptr);
return;
}
}

printf("Account not found\n");
fflush(stdin);
fclose(ptr);
}

static void write(void)
{
FILE *fp = fopen("account.txt", "w");
if (fp == 0)
{
fprintf(stderr, "Create file failed\n");
exit(1);
}
static const BankAccount data[] =
{
{ 1, "His", 20.00 },
{ 2, "Hers", 2000.00 },
{ 3, "Theirs", 1.00 },
};
if (fwrite(data, sizeof(data), 1, fp) != 1)
{
fprintf(stderr, "Write file failed\n");
exit(1);
}
fclose(fp);
}

static void read(void)
{
FILE *fp = fopen("account.txt", "r");
if (fp == 0)
{
fprintf(stderr, "Open file failed\n");
exit(1);
}
BankAccount ac;
while (fread(&ac, sizeof(ac), 1, fp) == 1)
{
printf("A/C: %4d %-20s %8.2f\n", ac.account_number, ac.name, ac.balance);
}
fclose(fp);
}

int main(void)
{
write();
read();
modify();
read();
return 0;
}

编译器甚至不关心使用编译器选项在 fseek() 上进行的转换:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Werror ba.c -o ba

运行时显示:

A/C:    1 His                      20.00
A/C: 2 Hers 2000.00
A/C: 3 Theirs 1.00
Enter account number: 2
***Account read***(1: His: 20.00)
***Account read***(2: Hers: 2000.00)
***Account found***

Account number: 2
Account name: Hers
Account balance: 2000.00

Enter new balance: 4000
A/C: 1 His 20.00
A/C: 2 Hers 4000.00
A/C: 3 Theirs 1.00

请注意在函数 read() 中检查是否已到达文件末尾的正确形式。如果您调用 feof(),那么您在 99.9% 的情况下都会出错。

关于C 覆盖文件中已有的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20729274/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com