Проблема может заключаться в вызове fseek()
:
fseek(ptr, -sizeof(BankAccount), SEEK_CUR);
Возвращаемое значение из sizeof()
является беззнаковым типом; отрицание этого будет очень большим числом. Технически это неверно (fseek()
должен получить long
, а не size_t
). Однако, если sizeof(size_t) == sizeof(long)
, вам это сойдет с рук (у меня это работает).
Другой аспект проблемы может заключаться в том, что вы не закрываете файл до того, как вернетесь (независимо от того, найдете ли вы запись или нет). Это, безусловно, утечка памяти; это также может повлиять на то, как данные записываются на диск. Это, вероятно, основная причина ваших проблем. У вас есть еще одна функция, которая открывает файл для чтения данных, чтобы увидеть изменения, но, поскольку файл не закрыт, данные не были записаны на диск. Примечание. Поскольку исходный код теперь доступен, это является причиной проблем.
Поскольку вы не показываете нам структуру данных, другой проблемой может быть несоответствие типа float
и double
для члена balance
; в равной степени единственная проблема может заключаться в том, что float
является неподходящим типом для остатков на счетах (например, он не может надежно представить остатки выше примерно 100 000,00 долларов США с точностью до цента — например, ввод 199999,99 отображается как 199999,98).
Примечание. В современных версиях Linux и в Windows, fflush(stdin)
— это определенная операция (и определенное поведение разумно и полезно). Согласно стандарту C и POSIX, это дает неопределенное поведение. Будьте осторожны при его использовании — помните, что это не переносимая операция.
Преобразование в SSCCE (Короткий, автономный, правильный пример), очень небольшая модификация вашего кода (добавление 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% случаев.
person
Jonathan Leffler
schedule
22.12.2013
while(!feof(ptr))
предупреждение о злоупотреблении... в этом цикле while говорится: Пока мы не прочитали _past EOF, и при чтении не возникло ошибок, do ..._ - person Elias Van Ootegem   schedule 22.12.2013while (!feof(file))
всегда неправильно для обсуждения того, почему ваша структура цикла неверна. . Вы не ошибаетесь, проверяя операции открытия или чтения; это всегда плохая идея. - person Jonathan Leffler   schedule 22.12.2013