Информатика и технология программирования

       

Файловая коллекция однотипных элементов


До сих пор мы рассматривали только отдельные объекты и их размещение в файле, но не оговаривали общей структуры файла и принципов размещения в нем всех объектов:



-размерность всех структур данных в файле должна быть переменной и увеличиваться по мере заполнения файла;



-все структуры данных файла должны быть достижимы через его начало, там же должны располагаться параметры, определяющие размерность данных, идентификаторы типов содержащейся информации и т.д.. Всем этим условиям удовлетворяет приведенная ниже схема размещения данных в файле.

При работе с файлом через объект класса "файловая коллекция" все управляющие структуры данных из файла читаются в соответствующие элементы данных объекта, при изменении объектов коллекции или ее состава в памяти одновременно производятся соответствующие изменения в файле. Ввиду относительной простоты программы объекты коллекции не сохраняются в памяти, связанной с коллекцией (не кэшируются), а передаются вызывающим программам.


//------------------------------------------------------bk8-06.cpp


//------Класс - файловая коллекция


class FCollect : FArray
{
TElem *Prototype;
//----- Объект производного класса, тип которого соответст-


// вует типу объектов, с которыми работает программа и ко-


// торые должны храниться в файле.


BinFile F;
FPTR head;
//----- Указатель в файле на массив файловых указателей


public:
BOOL Create(char *,int);
BOOL Open(char *);
void Close();
BOOL Expand();
TElem *operator[](int);
int Insert(TElem *,int=-1);
BOOL Delete(int);
void Sort();
FCollect(TElem *);
~FCollect() {}
};


//---------------------------------------------------------


void FCollect::Close()
{
FArray::Close();
F.close();
}


BOOL FCollect::Expand()
{
FPTR *pnew;
if (size != NElem()+1)
return( FArray::Update(F,head,0) !=FNULL);
if ((pnew = new FPTR[size*2]) ==NULL) return(0);
for (int n=0; n &#60 size; n++) pnew[n] = ptr[n];
delete ptr;
ptr = pnew;
size *= 2;
if ((head = FArray::Update(F,head,1)) ==FNULL)
return(0);
F.seekg(sizeof(int));


if (!F.good()) return(0);
F.write((BUF)&#38head, sizeof(FPTR));
if (!F.good()) return(0);
return(1);
}

FCollect::FCollect(TElem *PROTO)
{
Prototype = PROTO;
}

BOOL FCollect::Create(char *nm, int sz)
{
int id;
Close();
if ((ptr = new FPTR[sz])==NULL) return(0);
size = sz;
ptr[0]=FNULL;
id = Prototype-&#62IDENT();
head = sizeof(int) + sizeof(FPTR);
if (!F.Create(nm)) return(0);
if (!F.Open(nm)) return(0);
F.seekg(0L);
F.write((BUF)&#38id, sizeof(int));
F.write((BUF)&#38head, sizeof(FPTR));
if (!F.good()) { F.close(); return(0); }
if (!FArray::Append( F )) return(0);
return(1);
}

BOOL FCollect::Open(char *nm)
{
int id;
Close();
if (!F.Open(nm)) return(0);
F.seekg(0L);
F.read((BUF)&#38id, sizeof(int));
F.read((BUF)&#38head, sizeof(FPTR));
if (!F.good()) return(0);
if (!FArray::Load( F , head)) return(0);
if (id !=Prototype-&#62IDENT()) return(0);
return(1);
}

TElem *FCollect::operator[](int n)
{
TElem *pobj;
if (n &#62=NElem()) return(NULL);
pobj = Prototype-&#62Copy();
if (!pobj-&#62Load( F, ptr[n] ))
{ delete pobj; return(NULL); }
return(pobj);
}

//----- Крайне неэффективный, с постоянной перезагрузкой

// объектов, но тем не менее работающий алгоритм сортировки

// методом "пузырька"

void FCollect::Sort()
{
int k,m;
TElem *p1,*p2;
if ((m = NElem()) &#60 2) return;
do
{
k = 0; p1 = (*this)[0];
for (int n=1; n &#60 m; n++)
{
p2 = (*this)[n];
if (p1-&#62Compare(p2) ==1)
{
k++;
FPTR tmp;
tmp = ptr[n];
ptr[n] = ptr[n-1];
ptr[n-1] = tmp;
delete p2;
}
else
{
delete p1; p1 = p2;
}
}
}
while (k);
FArray::Update( F,head,0);
}

int FCollect::Insert(TElem *pnew, int indx)
{
FPTR pp;
int n = NElem();
if (ptr ==NULL) return(-1);
if (Prototype-&#62IDENT() != pnew-&#62IDENT()) return(-1);
if (indx ==-1)
{
if ((ptr[n] = pnew-&#62Append(F)) ==FNULL)
return(-1);
ptr[n+1] = FNULL;
indx = n;
}
else
{
if (indx &#62 n) return(-1);
if ((pp = pnew-&#62Append(F)) ==FNULL)
return(-1);
for (int i = n; i &#62= indx; i--) ptr[i+1] = ptr[i];
ptr[indx] = pp;
}
if (!Expand()) return(-1);
return(indx);
}

BOOL FCollect::Delete(int indx)
{
int n = NElem();
if (ptr==NULL) return(0);
if (indx &#62= n) return(0);
for (int i=indx; i&#60n; i++) ptr[i] = ptr[i+1];
return (FArray::Update(F,head,0)!=FNULL);
}


Содержание раздела