Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Затирается начало файла при чтении или закрытии

37K
30 ноября 2010 года
Tolias28
48 / / 20.09.2010
Есть программа для работы с базой данных. БД хранится в бинарном файле. Одна запись БД состоит из одной структуры, в которой есть несколько полей разных типов. С помощью программы можно добавлять, изменять или удалять выбранные записи. Ну так вот, все это работает, но странность и неприятность заключается вот в чем: после добавления новой записи в конец файла затирается первая запись :( В отладчике прошерстил каждую строчку и непонятно из чего такое случается. Вот мой код ниже(точнее это часть кода, так как весь код где-то на 3000 с лишним строк, то я выложил только ту часть и те функции, что имеют отношение к вопросу).

Код:
#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:
Я уже сам старался найти причину, ищу уже очень долго, но ничего не получается. Помогите пожалуйста :(
297
30 ноября 2010 года
koodeer
1.2K / / 02.05.2009
Отладчик...
Вроде Никлаус Вирт говорил, что отладчики не нужны совершенно. Так как развращают программиста, позволяя найти и заткнуть ошибку, не разбираясь в её причине... (Но я так не утверждаю).

Я внимательно не смотрел, но если не ошибаюсь, сначала происходит запись структуры в конец файла - 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;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог