#include <stdio.h>
#include <limits.h>
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include <time.h>
#define FALSE 0
#define TRUE 1
#define PhoneNameLEN 8
#define PhoneNumLEN 11
typedef struct record{
union{
int numrecs;
}info;
char PhoneName[PhoneNameLEN];
char PhoneNum[PhoneNumLEN];
}Record;
#define MAXREC (LONG_MAX / sizeof(Record))
int ReadRecord(FILE *f,long recnum, Record *recp) //
{
if(recnum>MAXREC)
return FALSE;
//if(recnum!=0){
if(fseek(f,recnum * sizeof(Record),SEEK_SET)!=0) //переміщення покажчика в позицію
return FALSE;
//}
return(fread(recp,sizeof(Record),1,f)==1);
}
FILE *OpenDB(const char *path, Record *header)
{
FILE *f=fopen(path,"r+b"); //відкриття файлу f
if (f)
ReadRecord(f,0, header); //читання інформаційного запису файлу, визначаючи кількість записів, що містяться у файлі
return f;
}
int GetNewRecToDB(Record *prod)
{
memset(prod,1,sizeof(Record));
textcolor(15);
textbackground(7);
gotoxy(7,6);
cprintf(rl(" Iм'я абонента : "));
textcolor(0);
textbackground(3);
cprintf(" ");
gotoxy(24,6);
int pch;
pch=InputChar("",prod->PhoneName,PhoneNameLEN-1); //записывает строку символьного типа
if(pch==27) return pch;
gotoxy(7,8);
textbackground(7);
textcolor(15);
cprintf(rl(" Номер телефону: "));
textcolor(0);
textbackground(3);
cprintf(" ");
gotoxy(24,8);
pch=InputCharInt("",prod->PhoneNum,PhoneNumLEN-1); //Записывает строку символьного типа из цифр
if(pch==27) return pch;
}
int WriteRecord(FILE *f, long recnum, Record *recp)
{
if (recnum > MAXREC)
return FALSE;
if(fseek(f,recnum* sizeof(Record),SEEK_SET)!=0) //позиціювання покажчика
return FALSE;
return(fwrite(recp,sizeof(Record),1,f)==1);
}
int AppendRecord(FILE *f, int *recnum, Record *recp)
{
if (fseek(f,0, SEEK_END)!=0) //установка файлового покажчи-ка в кінець файлу
return FALSE;
*recnum = ftell(f) / sizeof(Record); // ftell(f) повертає значення покажчика у файлі
//визначення номера запису, що додається
return WriteRecord(f, *recnum, recp); //дозапис у кінець файлу
}
void PhoneBook(FILE *dbf,int numpnames)
{
Window(4,3,35,23,7,0,'y');
gotoxy(6,3);
textbackground(6);
textcolor(15);
cprintf(rl(" Телефонна книга "));
gotoxy(5,4);
textbackground(7);
textcolor(4);
cprintf(rl(" № "));
cprintf(rl(" Абонент "));
cprintf(rl(" Мобiльний номер "));
textcolor(0);
Record pname;
int i;
textcolor(0);
gotoxy(5,5);
for(i=0;i<numpnames+1;i++){
ReadRecord(dbf,i,&pname);
gotoxy(40,5+i);
gotoxy(5,5+i);
cprintf(" %2d %s %s",i+1,pname.PhoneName,pname.PhoneNum);
}
}
int main()
{
Record pname;
FILE *dbf;
dbf=OpenDB("phonebook.dat",&pname);
fseek(dbf,0L,SEEK_END);
if(ftell(dbf)==0) memset(&pname,0,sizeof(Record));
numnames=pname.info.numrecs;
GetNewRecToDB(&pname);
if(AppendRecord(dbf, &numnames, &pname))
{
gotoxy(10,20);
textcolor(4);
textbackground(7);
memset(&pname,0,sizeof(Record));
pname.info.numrecs=numnames;
WriteRecord(dbf,0,&pname);
Window(4,4,41,10,1,0,'n');
PhoneBook(dbf,numnames);
Window(31,11,52,14,2,0,'y');
gotoxy(33,12);
cprintf(rl("Контакт №%lu додано."),numnames+1);
}
fclose(dbf);
return 0;
}
Затирается начало файла при чтении или закрытии
Код:
Добавление записи в файл происходит в строке:
WriteRecord(dbf,0,&pname);
что находится в мейне в условии if(AppendRecord(dbf, &numnames, &pname))
После добавления в конце файла создается новая запись и все нормально, но стоит только пройтись функции PhoneBook, как первая запись исчезает. Для справки скажу, что если эту функцию PhoneBook вызывать не после добавления записи, а в любом другом месте программы, то затирания первой записи не происходит. Когда я прошелся отладчиком по функции PhoneBook, то выявилось, что затирание происходит после чтения(!) первой записи из файла (в коде это ReadRecord(dbf,i,&pname); в теле цикла for). А если же пойти глубже и пройтись отладчиком по функции ReadRecord, то видно, что первая запись исчезает после строки:
if(fseek(f,recnum* sizeof(Record),SEEK_SET)!=0).
Не зная решения этой проблемы, решил ее не решить, а избежать, просто не используя функцию PhoneBook. Но тогда первая запись уничтожается после закрытия файла fclose(dbf); :eek: . От чего и почему?
По своему неогромному опыту в программировании уже не один раз убеждался, что причины ошибок в коде всегда не там, где их ищут, а иногда в самых безобидных местах. Потому прошу помощи найти это место или хотя бы подскажите приблизительно, что может способствовать такому вот нехорошему поведению, что при вызове безобидных функций затирается первая запись в файле. :confused:
Я уже сам старался найти причину, ищу уже очень долго, но ничего не получается. Помогите пожалуйста :(
Вроде Никлаус Вирт говорил, что отладчики не нужны совершенно. Так как развращают программиста, позволяя найти и заткнуть ошибку, не разбираясь в её причине... (Но я так не утверждаю).
Я внимательно не смотрел, но если не ошибаюсь, сначала происходит запись структуры в конец файла - AppendRecord, а потом структура записывается в начало файла - WriteRecord.
Код:
int main()
{
...
fseek(dbf,0L,SEEK_END);
if(ftell(dbf)==0) memset(&pname,0,sizeof(Record));
...
if(AppendRecord(dbf, &numnames, &pname))
{
....
WriteRecord(dbf,[highlight]0[/highlight],&pname);
...
}
fclose(dbf);
return 0;
}
{
...
fseek(dbf,0L,SEEK_END);
if(ftell(dbf)==0) memset(&pname,0,sizeof(Record));
...
if(AppendRecord(dbf, &numnames, &pname))
{
....
WriteRecord(dbf,[highlight]0[/highlight],&pname);
...
}
fclose(dbf);
return 0;
}