МІНІСТЕРСТВО ОСВІТИ ТА НАУКИ УКРАЇНИ
Національний університет «Львівська політехніка»
Кафедра САПР
Звіт
Про виконання лабораторної роботи №3
З курсу:
«Бази даних»
Тема: ІНДЕКСНО-ПОСЛІДОВНИЙ МЕТОД ДОСТУПУ ДО ФАЙЛІВ НА ЗОВНІШНІХ ЗАПАМ’ЯТОВУЮЧИХ ПРИСТРОЯХ.
Мета: Розглянути органiзацiю i ведення файлiв iндексно-послiдовного доступу; набути практичнi навички у програмуваннi алгоритмiв iндексно-послiдовного доступу до файлiв на зовнiшнiх запам'ятовуючих пристроях.
Текст програми:
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <dir.h>
#define blockCount 10
#define maxID 100
char *mainPath[blockCount];
char tempPath[] = "src.pdb";
char _template[]="tmp.pdb";
char dbDirectory[MAXDIR]="c:\\";
char indexPath[]="index.idb";
char keyTab = 1;
FILE *mainFile = NULL, *temFile = NULL, *infoFile=NULL;
int DBflag=0;
class animalRecord
{public:
int ID;
int Age;
char Pet[40+2];
char ownerName[40+2];
char Illness[40+2];
int Price;
char Notes[40+2];
int isSet;
int errorcode;
void readFromFile(FILE *CUR = NULL);
void writeToFile(FILE *CUR = NULL);
void goToKey(FILE *CUR = NULL);
animalRecord();};
animalRecord::animalRecord()
{ID = -1;
Age = 0;
strcpy (Pet,"NULL");
strcpy (ownerName,"NULL");
strcpy (Illness,"NULL");
Price = 0;
strcpy (Notes,"NULL");
errorcode = isSet = 0;}
void animalRecord::writeToFile(FILE* CUR)
{if (CUR == NULL) return;
fprintf(CUR,"%c\n%d\n%d\n%s\n%s\n%s\n%d\n%s\n",keyTab,
this->ID,
this->Age,
this->Pet,
this->ownerName,
this->Illness,
this->Price,
this->Notes);CUR=NULL;}
void animalRecord::readFromFile(FILE *CUR)
{animalRecord buf=animalRecord();
int eofflag=0, l, read=0;
char cbuf, key=0;
buf.isSet=0;
do
{if(feof(CUR))
{eofflag=1;break;}
fscanf(CUR,"%c",&key);}
while(key!=keyTab);
if(eofflag)
{if(!read)
{buf.errorcode=1;
*this = buf;
return;}}
//Reading record --------------------------------------------------------------
fscanf(CUR,"\n%d\n",&buf.ID);
fscanf(CUR,"%d\n",&buf.Age);
for(l=0, fscanf(CUR,"%c",&cbuf);cbuf!='\n';l++)
{buf.Pet[l]=cbuf;
fscanf(CUR,"%c",&cbuf);}
buf.Pet[l]='\0';
for(l=0, fscanf(CUR,"%c",&cbuf);cbuf!='\n';l++)
{buf.ownerName[l]=cbuf;
fscanf(CUR,"%c",&cbuf);}
buf.ownerName[l]='\0';
for(l=0, fscanf(CUR,"%c",&cbuf);cbuf!='\n';l++)
{buf.Illness[l]=cbuf;
fscanf(CUR,"%c",&cbuf);}
buf.Illness[l]='\0';
fscanf(CUR,"%d\n",&buf.Price);
for(l=0, fscanf(CUR,"%c",&cbuf);cbuf!='\n';l++)
{buf.Notes[l]=cbuf;
fscanf(CUR,"%c",&cbuf);}
buf.Notes[l]='\0';
buf.isSet=1;
*this = buf;}
void animalRecord::goToKey(FILE *CUR)
{int i=0,a;float ad;
char key;
if((ftell(CUR))>0)
fseek(CUR,-1,SEEK_CUR);
else{return;}
do
{ad = ftell(CUR);
fscanf(CUR,"%c",&key);
fseek(CUR,ad,SEEK_SET);
if(key=='\n')
a=-2;
else
a=-1;
fseek(CUR,a,SEEK_CUR);
}while(key!=keyTab);
fseek(CUR,1,SEEK_CUR);}
//------------------------------------------------------------------------------
void SetIndexFile();
int ChangeDir(char[MAXDIR]);
char* SetBlockName(int);
void FileGenerator();
int reccmp(char str1[47], char str2[47], int count);
void New();
void Open();
char* SetStr(int);
animalRecord Set (animalRecord set = animalRecord () );
void Insert (animalRecord sav = animalRecord () );
void Delete (animalRecord Del = animalRecord () );
void Modify ();
void Find ();
void Print ();
int main()
{textmode(64);
clrscr();
for(int i=0;i<blockCount;i++)
if (!(mainPath[i] = (char*) malloc(15)))
{exit(0);}
FileGenerator();
do
{cout<<"Main menu:";
cout<<"\n1. New base"<<
"\n2. Open base"<<
"\n3. Insert"<<
"\n4. Delete"<<
"\n5. Modify"<<
"\n6. Find"<<
"\n7. Print"<<
"\n8. Quit program\n"<<
"Your choise: ";
switch(getch())
{case '1': clrscr();New(); break;
case '2': clrscr();Open(); break;
case '3': clrscr();Insert(); break;
case '4': clrscr();Delete(); break;
case '5': clrscr();Modify(); break;
case '6': clrscr();Find(); break;
case '7': clrscr();Print(); break;
case '8': clrscr();return 0;
default: clrscr();cout<<"Your choise is incorrect!\n";break;}
}while(1);}
void New()
{int R,B,i;
animalRecord buf = animalRecord();
DBflag=0;
cout<<"Enter path to base (directory only): ";
cin>>dbDirectory;
if(ChangeDir(dbDirectory))
{cout<<"Base not created!\n";return;}
if((infoFile=fopen(indexPath,"r"))!=NULL)
{fclose(infoFile);cout<<"Base not created!\n";return;}
for(i=0; i<blockCount; i++)
{if((mainFile=fopen(mainPath[i],"r"))!=NULL)
{fclose(mainFile);cout<<"Base not created!\n";return;}
fclose(mainFile); }
infoFile=fopen(indexPath,"w+");
SetIndexFile();
for (i=0;i<blockCount;i++)
{mainFile=fopen(mainPath[i],"w+");
rewind(mainFile);
fclose(mainFile);}
cout<<"Base "<<dbDirectory<<" created...\n";
DBflag=1;}
void Open()
{int i;cout<<"Enter path to directory with base files: ";
DBflag=0;
cin>>dbDirectory;
if(ChangeDir(dbDirectory))
{cout<<"Can't open base!\n";return;}
if((infoFile=fopen(indexPath,"r"))==NULL)
{cout<<"Can't open base!\n";
return;}
for(i=0; i<blockCount; i++)
{
if((mainFile=fopen(mainPath[i],"r"))==NULL)
{cout<<"Can't open base!\n";
return;}
fclose(mainFile);
}
fclose(mainFile);
cout<<"Base "<<dbDirectory<<" opened...\n";DBflag=1;}
animalRecord Set (animalRecord set)
{clrscr();
if (!set.isSet) set.ID=0;
do
{cout<<"Set the form:\n\n";
cout<<"1. ID: "<<set.ID<<"\n";
cout<<"2. Age: "<<set.Age<<"\n";
cout<<"3. Pet: "<<set.Pet<<"\n";
cout<<"4. ownerName: "<<set.ownerName<<"\n";
cout<<"5. Illness: "<<set.Illness<<"\n";
cout<<"6. Price: "<<set.Price<<"\n";
cout<<"7. Notes: "<<set.Notes<<"\n\n";
cout<<"8. Confirm\n";
cout<<"9. Cancel\n\n";
cout<<"Choise:\n";
switch (getch())
{case '1': cout<<"1. ID: ";cin>>set.ID;clrscr();break;
case '2': cout<<"2. Age: ";cin>>set.Age;clrscr();break;
case '3': cout<<"3. Pet: ";strcpy(set.Pet,SetStr(40));clrscr();break;
case '4': cout<<"4. ownerName: ";strcpy(set.ownerName,SetStr(40));clrscr();break;
case '5': cout<<"5. Illness: ";strcpy(set.Illness,SetStr(40));clrscr();break;
case '6': cout<<"6. Price: ";cin>>set.Price;clrscr();break;
case '7': cout<<"7. Notes: ";strcpy(set.Notes,SetStr(40));clrscr();break;
case '8': clrscr();set.isSet=1;return set;
case '9': clrscr();set.isSet=0;return set;
default: clrscr();cout<<"Your choise is incorrect!\n";}
}while(1);}
void Insert(animalRecord sav)
{
int MAX=0;
int BID;
if(DBflag==0){cout<<"Base is not opened!\n";return;}
animalRecord ins = animalRecord();
if(sav.isSet)ins=sav;
else ins=Set();
animalRecord buf=animalRecord();
if(ins.isSet==0){return;}
if(ins.ID<0){return;}
fclose(temFile);temFile=NULL;
fclose(mainFile);mainFile=NULL;
if((temFile=fopen(_template,"w"))==NULL){return;};
rewind(infoFile);
do
{fscanf(infoFile,"MAX# %d: BLOCK# %d\n",&MAX,&BID);}
while(ins.ID>MAX);
fclose (mainFile);
if ((mainFile = fopen(mainPath[BID],"r+"))==NULL)
{return;};
rewind(temFile);
//fclose(DBF);
//DBF=fopen(BASE_PATH,"r+");
rewind(mainFile);
int insert=0;
do{ buf.readFromFile(mainFile);
if(buf.errorcode==1)
{if(!insert)
{ins.writeToFile(mainFile);
fclose(temFile);
remove(_template);}
if(insert)
{fclose(mainFile);
fclose(temFile);
remove(mainPath[BID]);
rename(_template,mainPath[BID]);
mainFile=fopen(mainPath[BID],"r+");}
//fclose(DBF); DBF=NULL;
//DBF=fopen(BASE_PATH,"r+");
fflush(mainFile);
printf("animalRecord %d was inserted to BLOCK# %d\n\rMAX# %d, %s.\n",ins.ID,BID,MAX,mainPath[BID]);
fclose(mainFile);
fclose(temFile);
return;}
//Kopiyuvanna doky ne znajdeno misce vstavky a takozh pisla vsyavky
if((ins.ID > buf.ID)||(insert))
buf.writeToFile(temFile);
//nevirne id
if(ins.ID==buf.ID){fclose(temFile);
remove(_template);
fclose(mainFile);
mainFile=NULL;
//DBF=fopen(BASE_PATH[BID],"r+");
return;}
//Vstavka
if((ins.ID < buf.ID)&&(!insert))
{ins.writeToFile(temFile);
buf.writeToFile(temFile);
insert=1;}
}while(1);}
void Delete(animalRecord Del)
{int MAX,BID;
int ID;
int R;
int bl,fr;
float ad,ov,ov1;
animalRecord buf = animalRecord(),nul=animalRecord();
if (DBflag == 0)
{cout<<"Base is not opened!\n";return;}//Pomylka
if (!Del.isSet)
{Del.ID=0;
while(1)
{cout<<"1. Delete animalRecord (ID): "<<Del.ID<<"\n";
cout<<"2. Delete\n";
cout<<"3. Cancel\n\nChoise:\n";
switch(getch())
{case '1': cout<<"1. Delete animalRecord (ID): ";cin>>Del.ID;clrscr();break;
case '2': clrscr();goto ex1;
case '3': clrscr();
default: clrscr();cout<<"Your choise is incorrect\n";break;}
}}
ex1:;
fclose(temFile);temFile=NULL;
fclose(mainFile);mainFile=NULL;
ID=Del.ID;
rewind(infoFile);
do
{fscanf(infoFile,"MAX# %d: BLOCK# %d\n",&MAX,&BID);}
while(ID>MAX);
fclose (mainFile);
if ((mainFile = fopen(mainPath[BID],"r+"))==NULL)
{return;};
buf=animalRecord();
if((temFile=fopen(_template,"w+"))==NULL){return;};
rewind(temFile);
int del=0;
do{buf.readFromFile(mainFile);
if(buf.errorcode==1)
{if(!del)
{
fclose(temFile);
remove(_template);
return;}
if(del)
{fclose(mainFile);
fclose(temFile);
remove(mainPath[BID]);
rename(_template,mainPath[BID]);
//DBF=fopen(BASE_PATH[BID],"r+");
}
printf("animalRecord %d was deleted from BLOCK# %d.\n\rMAX# %d, %s.\n",ID,BID,MAX,mainPath[BID]);
return;}
//Kopiyuvanna doky ne znajdeno misce vstavky a takozh pisla vsyavky
if((ID > buf.ID)||(del))
buf.writeToFile(temFile);
//virne id
if(ID==buf.ID){del=1;}
if( (ID < buf.ID)&&(!del) )
{
fclose(temFile);
remove(_template);
return;}
}while(1);
}
void Modify()
{fclose(temFile);
animalRecord mod = animalRecord(),buf = animalRecord();
int bl,fr,read=0;
if (mainFile == NULL)
{cout<<"Base is not opened!\n";return;}//Pomylka
mod.ID=0;
while(1)
{cout<<"1. Modify animalRecord (ID): "<<mod.ID<<"\n";
cout<<"2. Modify\n";
cout<<"3. Cancel\n\nChoise:\n";
switch(getch())
{case '1': cout<<"1. Modify animalRecord (ID): ";cin>>mod.ID;clrscr();break;
case '2': clrscr();goto ex2;
case '3': clrscr();return;
default: clrscr();cout<<"Your choise is incorrect\n";break;}
}
ex2:;
int BID;int MAX;
rewind(infoFile);
do
{fscanf(infoFile,"MAX# %d: BLOCK# %d\n",&MAX,&BID);}
while(mod.ID>MAX);
fclose (mainFile);
if ((mainFile = fopen(mainPath[BID],"r+"))==NULL)
{return;};
rewind(mainFile);
do{
buf.readFromFile(mainFile);
if(buf.errorcode==1)
{
if(!read)
{return;}
}
if(mod.ID==buf.ID)
{read=1;
mod=Set(buf);
Delete(mod);
clrscr();
Insert(mod);
clrscr();
printf("Modification of record %d in BLOCK# %d was executed.\n\rMAX# %d, %s.\n",mod.ID,BID,MAX,mainPath[BID]);
return;}
if( (mod.ID < buf.ID)&&(!read) )
{ return;}
}while(1);}
void Find()
{fclose(temFile);
temFile = NULL;
int fnd=0;
clrscr();
if (DBflag == 0)
{cout<<"Base is not opened!\n";return;}//Pomylka
int tofin=0;char k;
animalRecord set = animalRecord(),buf = animalRecord();
animalRecord tmp;
if((temFile = fopen (tempPath,"w+"))==NULL)
{return;};
cout<<"Search to:\n\n";
cout<<"1. ID "<<"\n";
cout<<"2. Age "<<"\n";
cout<<"3. Pet "<<"\n";
cout<<"4. ownerName "<<"\n";
cout<<"5. Illness "<<"\n";
cout<<"6. Price "<<"\n";
cout<<"7. Notes "<<"\n\n";
cout<<"8. Cancel\n\n";
cout<<"Choise:\n";
k = getch();
switch (k)
{case '1': cout<<"1. ID: ";cin>>set.ID;clrscr();break;
case '2': cout<<"2. Age: ";cin>>set.Age;clrscr();break;
case '3': cout<<"3. Pet: ";strcpy(set.Pet,SetStr(40));clrscr();break;
case '4': cout<<"4. ownerName: ";strcpy(set.ownerName,SetStr(40));clrscr();break;
case '5': cout<<"5. Illness: ";strcpy(set.Illness,SetStr(40));clrscr();break;
case '6': cout<<"6. Price: ";cin>>set.Price;clrscr();break;
case '7': cout<<"7. Notes : ";strcpy(set.Notes,SetStr(40));clrscr();break;
case '8': clrscr();return;
default: clrscr();cout<<"Your choise is incorrect!\n";return;}
tmp = set;
tofin = k - '1';
int ind;
rewind(temFile);
for(ind=0;ind<blockCount;ind++){
if((mainFile=fopen(mainPath[ind],"r"))==NULL)
{return;}
rewind(mainFile);
do{buf.readFromFile(mainFile);
if(buf.isSet)
switch(tofin)
{ case 0: if(tmp.ID==buf.ID)
{fnd++;
buf.writeToFile(temFile);}break;
case 1: if(tmp.Age==buf.Age)
{fnd++;
buf.writeToFile(temFile);}break;
case 2: if(!(reccmp(tmp.Pet,buf.Pet,strlen(tmp.Pet))))
{fnd++;
buf.writeToFile(temFile);}break;
case 3: if(!(reccmp(tmp.ownerName,buf.ownerName,strlen(tmp.ownerName))))
{fnd++;
buf.writeToFile(temFile);}break;
case 4: if(!(reccmp(tmp.Illness,buf.Illness,strlen(tmp.Illness))))
{fnd++;
buf.writeToFile(temFile);}break;
case 5: if(tmp.Price==buf.Price)
{fnd++;
buf.writeToFile(temFile);}break;
case 6: if(!(reccmp(tmp.Notes,buf.Notes,strlen(tmp.Notes))))
{fnd++;
buf.writeToFile(temFile);}break;
}fflush(temFile);
}while(buf.errorcode!=1);
fclose(mainFile);
}
fclose(temFile);
clrscr();
cout<<"Results "<<fnd<<":\n";
temFile = fopen(tempPath,"r");
rewind(temFile);
do
{set.readFromFile(temFile);
if(set.ID!=-1){
cout<<"ID: "<<set.ID<<"\n";
cout<<"Age: "<<set.Age<<"\n";
cout<<"Pet: "<<set.Pet<<"\n";
cout<<"ownerName: "<<set.ownerName<<"\n";
cout<<"Illness: "<<set.Illness<<"\n";
cout<<"Price: "<<set.Price<<"\n";
cout<<"Notes: "<<set.Notes<<"\n\n";}
}while(set.errorcode!=1);
fclose(temFile);
cout<<"Press enter...";while(getch()!=13);clrscr();}
void Print()
{fclose(mainFile);
mainFile=NULL;
animalRecord set;
if (DBflag == 0)
{cout<<"Base is not opened!\n";return;}
int ind=0;
for(ind=0;ind<blockCount;ind++){
if((mainFile = fopen(mainPath[ind],"r"))==NULL)
{return;}
rewind(mainFile);
do
{set.readFromFile(mainFile);
if(set.ID!=-1){
cout<<"ID: "<<set.ID<<"\n";
cout<<"Age: "<<set.Age<<"\n";
cout<<"Pet: "<<set.Pet<<"\n";
cout<<"ownerName: "<<set.ownerName<<"\n";
cout<<"Illness: "<<set.Illness<<"\n";
cout<<"Price: "<<set.Price<<"\n";
cout<<"Notes: "<<set.Notes<<"\n\n";}
}while(set.errorcode!=1);
fclose(mainFile);}
cout<<"Press enter...";while(getch()!=13);clrscr();
}
char* SetStr(int count)
{char k;
int curpos=0;
char* str = (char*) malloc (count*sizeof(char));
do
{k=getche();
switch (k)
{case 8: cprintf(" %c",8);curpos--;if(curpos<0)curpos=0;str[curpos]='\0';break;//backspace
case 13: if(curpos==0){str[curpos]='-';curpos++;}str[curpos]='\0';break;
case 27: strcpy(str,"-");k=13;break;
default: str[curpos]=k; curpos++;}
if(curpos>=count-2)
{k=13;str[curpos]=k; curpos++;}
}while(k!=13);
return str;}
int reccmp(char str1[47], char str2[47], int count)
{int i=0,l1=strlen(str1),l2=strlen(str2), res=1;
for(i=0;(i<l2)&&(res);i++)
res=memcmp(str1,(str2+i),l1);
return res;}
void FileGenerator()
{char tmp[12];
int i;
for (i=0;i<blockCount;i++)
{strcpy(mainPath[i],SetBlockName(i));
strcat(mainPath[i],".TXT");}}
char* SetBlockName(int n)
{int i,tmp;
char *name;
name = (char*)malloc(15*sizeof(char));
strcpy(name, "B_0000");
for(i=5;i>1;i--)
{tmp = n;
n = int(n/10);
tmp-=n*10;
name[i]+=tmp;}
return name;}
int ChangeDir(char path[MAXDIR])
{char drv[3];
int a;
a = chdir(path);
if(path[1]==':')
drv[0]=path[0];
else drv[0] = getdisk() + 'a';
if((drv[0]>='A')&&(drv[0]<='Z'))
if(drv[0]!=getdisk() + 'A')
setdisk(-'A'+drv[0]);
if((drv[0]>='a')&&(drv[0]<='z'))
if(drv[0]!=getdisk() + 'a')
setdisk(-'a'+drv[0]);
return (a);}
void SetIndexFile()
{int i;
int cur=0;
FILE *f=NULL;
f=fopen(indexPath,"r+");
for (i=0;i<blockCount;i++)
{cur+=maxID/blockCount;
fprintf(f,"MAX# %05d: BLOCK# %04d\n",cur-1,i);}
fclose(f);
}
Висновок: На даній лабораторній роботі я розглянув органiзацiю i ведення файлiв послiдовного доступу; набув практичних навичок у програмуваннi алгоритмiв роботи з файлами послiдовного доступу.