#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
//äàííûå õðàíÿòñÿ â âèäå ìàññèâà ñòðóêòóð èç óêàçàòåëÿ è êëþ÷à
//ñòðóêòóðà ýëåìåíòà òàáëèöû
typedef struct Item
{
int busy; //ïîëå çàíÿòîñòè
int key; //êëþ÷
int release; //íîìåð âåðñèè
int offset; //ñìåùåíèå â ôàéëå (ïî îòíîøåíèþ ê íà÷àëó ôàéëà)
int len; //äëèíà èíôîðìàöèè
char* info; //ïîëå äàííûõ - ñòðîêà
}Item;
//ñòðóêòóðà - òàáëèöà
typedef struct Table
{
int size; //ìàêñèìàëüíûé ðàçìåð òàáëèöû
int count; //òåêóùèé ðàçìåð òàáëèöû
Item* val; //ìàññèâ ñòðóêòóð item
FILE *fd; //äåñêðèïòîð ôàéëà, ÷òîáû âûïîëíÿòü îïåðàöèè ñ ôàéëîì äàííûõ
}Table;
//ôóíêöèè äëÿ îðãàíèçàöèè äèàëîãà
int F1_End(Table*); //ôóíêöèÿ âûõîäà
int F2_Menu(Table*); //ôóíêöèÿ ïîêàçà ìåíþ
int F3_Print(Table*); //âûâîä ýëåìåíòîâ
int F4_Input(Table*); //ââîä ýëåìåíòà
int F5_DeleteKey(Table*); //óäàëåíèå ýëåìåíòîâ ïî êëþ÷ó â òàáëèöå
int F6_DeleteRelease(Table*); //óäàëåíèå ýëåìíåòà ïî êëþ÷ó è âåðñèè
int F7_FindKey(Table*); //ïîèñê è êîïèðîâàíèå ýëåìåíòà
int F8_FindRelease(Table*); //ïîèñê âåðñèè
//ôóíêöèè ðàáîòû ñ òàáëèöåé
Table* TableCreate(int size); //ôóíêöèÿ ñîçäàíèÿ ïóñòîé òàáëèöû
void TableDelete(Table* T); //óäàëåíèå òàáëèöû
void TablePrint(Table* T); //âûâîä òàáëèöû
int TableAdd(Table* T, int key, char* info); //äîáàâëåíèå ýëåìåíòà ñ êëþ÷îì â òàáëèöó
void TableZip(Table* T); //ñæàòèå òàáëèöû
int TableFindLast(Table* T, int key); //ïîèñê ýëåìíåòà ïîñëåäíåé âåðñèè ïî êëþ÷ó â òàáëèöå (íà÷èíàåòñÿ ñ êîíöà òàáëèöû)
int TableDeleteKey(Table* T, int key); //óäàëåíèå ýëåìåíòîâ ïî êëþ÷ó
int TableDeleteRelease(Table* T, int key, int release); //óäàëåíèå ýëåìåíòa ïî êëþ÷ó è âåðñèè
Table* TableFindKey(Table* T, int key); //ïîèñê è ïîëó÷åíèå êîïèè ýëåìåíòà
char* TableFindRelease(Table* T, int key, int release); //ïîèñê ïî êëþ÷ó è âåðñèè
void TableSave(Table *T);
int D_load(Table *T);
int TableLoad(Table *T, char *fname);
int TableCreateFile(Table* T, int size, char * fname);
int ItemPrint(Table* T, int ind); //âûâîä ýëåìåíòà òàáëèöû
//äðóãèå ôóíêöèè
int getInt(int*); //÷òåíèå öåëîãî ÷èñëà
int getStr(char**); //ôóíêöèÿ ââîäà ñòðîê
const char *msgs[] = { NULL, "Exit programm", "Show menu", "Print table",
"Input item", "Delete key", "Delete release", "Find key", "Find release" }; //ñòðîêè ìåíþ
int main()
{
const int SIZE = 10; //ìàêñèìàëüíû ðàçìåð òàáëèöû
int ex = 0; //ïåðåìåíûå äëÿ óäîáíîãî âûâîäà ìåíþ
int menu = 0; //äàëåå äî êîíöà - âûâîä ìåíþ
int(*fun[]) (Table*) = { NULL, F1_End, F2_Menu, F3_Print,
F4_Input, F5_DeleteKey, F6_DeleteRelease, F7_FindKey, F8_FindRelease }; //ìàññèâ ôóíêöèé
Table T ={0,0,NULL,NULL};
if(D_load(&T)==0)
return 1;
F2_Menu(&T); //âûâîä ìåíþ
while (ex != 1)
{
menu = 0; //ïóíêò ìåíþ
while (menu <= 0 || menu >= 9)
getInt(&menu); //÷òåíèå íîìåðà ïóíêòà ìåíþ
ex = (*fun[menu])(&T);
}
TableSave(&T);
printf("Good buy!");
TableDelete(&T);
return 0;
}
// ôóíêöèè ìåíþ
//çàâåðøåíèå ïðîãðàììû
int F1_End(Table* T)
{
TableDelete(T); //óäàëåíèå òàáëèöû
return 1;
}
//âûâîä ìåíþ
int F2_Menu(Table* T)
{
int i;
for (i = 1; i < 9; ++i)
printf("%d. %s\n", i, msgs[i]);//âûâîä ïóíêòîâ ìåíþ
return 0;
}
//âûâîä òàáëèöû
int F3_Print(Table* T)
{
puts("Table:");
TablePrint(T); //âûâîä
return 0;
}
//äîáàâëåíèå êëþ÷à
int F4_Input(Table* T)
{
int key = 0;
char* info;
int res;
printf("Enter key: ");
getInt(&key); //÷èòàåì êëþ÷
printf("Enter information: ");
res = getStr(&info); //÷òåíèå èíôîðìàöèè
if (res) //ïðîâåðêà íà âîçìîæíîñòü âûäåëèòü ïàìÿòü
{
puts("Memory is out");
TableDelete(T); //óäàëÿåì òàáëèöó ïðè íåõâàòêå ïàìÿòè
return 1;
}
if (TableAdd(T, key, info)) //åñëè äîáàâëåíèå óñïåøíî
puts("Table is full");
else
puts("Item added.");
return 0;
}
//óäàëåíèå ýëåìåíòà
int F5_DeleteKey(Table* T)
{
int key = 0;
printf("Enter key: "); //ââîä êëþ÷à
getInt(&key);
printf("Deleted %d items.\n", TableDeleteKey(T, key)); //âûâîäèì ñêîëüêî êëþ÷åé ìû óäàëèëè
return 0;
}
//óäàëåíèå ýëåìåíòà ïî êëþ÷ó è âåðñèè
int F6_DeleteRelease(Table* T)
{
int key = 0;
int release = 0;
printf("Enter key: "); //ââîä êëþ÷à è âåðñèè
getInt(&key);
printf("Enter release: ");
getInt(&release);
if (TableDeleteRelease(T, key, release)) //óäàëåíèå ýëåìåíòà òàáëèöè, åñëè óäàëåíèå óñïåøíî
puts("Items deleted.");
else
puts("Items not found."); //åñëè íå óñïåøíî
return 0;
}
//ïîèñê â òàáëèöå êëþ÷à
int F7_FindKey(Table* T)
{
int key = 0;
Table* NewTable;
printf("Enter key: ");
getInt(&key);
NewTable = TableFindKey(T, key); //ïîëó÷àåì óêàçàòåëü íà òàáëèöó ñ êîïèÿìè êëþ÷à
if (NewTable)
{
puts("Table:");
TablePrint(NewTable); //âûâîä
TableDelete(NewTable); //è óäàëåíèå òàáëèöû
}
else
{
puts("Keys not found."); //èëè âûâîäèì ñîîáùåíèå îá îøèáêå
}
return 0;
}
//ïîèñê â òàáëèöå êëþ÷à è âåðñèè
int F8_FindRelease(Table* T)
{
int key = 0;
int release = 0;
char* info;
printf("Enter key: ");
getInt(&key); //ââîä êëþ÷à
printf("Enter release: ");
getInt(&release); //ââîä âåðñèè
info = TableFindRelease(T, key, release); //ïîèñê èíôîðìàöèè ïî êþ÷ó è âåðñèè
if (info)
printf("Information: %s.\n", info); //âûâîä åñëè íàøëè
else
puts("Key not found."); //èíà÷å âûâîäèì ñîîáùåíèå îá îøèáêå
return 0;
}
//ôóíêöèè ðàáîòû ñ òàáëèöåé
//ñîçäàíèå òàáëèöû, âîçâðàùàåì óêàçàòåëü íà ïóñòóþ òàáëèöó
int D_load(Table *T)
{
int size;
char * fname=NULL;
printf("Enter file name:");
// getStr(&fname);
fname = "data.dat";
if(fname==NULL)
return NULL;
if(TableLoad(T,fname)==0)
{
printf("File not fount. Create file. Enter Size:");
if(getInt(&size)==0)
return 0;
return TableCreateFile(T,size,fname);
}
return 1;
}
int TableLoad(Table *T, char *fname)
{
int i;
Item z;
T->fd = fopen(fname,"r+b");
if(T->fd==0)
return 0;
fread(&T->size,sizeof(int),1,T->fd);
T->val = (Item*)calloc(T->size,sizeof(Item));
fread(&T->count,sizeof(int),1,T->fd);
fseek(T->fd,8,SEEK_SET);
fread(T->val,sizeof(Item),T->size,T->fd);
for(i=0;i<(T->size);i++)
{
if(T->val[i].busy)
{
char *info = (char*)calloc(T->val[i].len,sizeof(char));
fseek(T->fd,T->val[i].offset,SEEK_SET);
fread(info,sizeof(char),T->val[i].len,T->fd);
T->val[i].info = info;
}
}
return 1;
}
int TableCreateFile(Table* T, int size, char * fname)
{
T->size =size;
T->count=0;
T->fd = fopen(fname,"w+b");
if(T->fd==0)
{
T->val=0;
return 0;
}
T->val = (Item*)calloc(T->size,sizeof(Item));
fwrite(&T->size,sizeof(int),1,T->fd);
fwrite(&T->count,sizeof(int),1,T->fd);
fwrite(T->val,sizeof(Item),T->size,T->fd);
return 1;
}
Table* TableCreate(int size)
{
Table* T;
if (size < 0)
return NULL;
T = (Table*)malloc(sizeof(Table)); //ïàìÿòü ïîä ñòðóêòóðó òàáëèöû
if (T == NULL)
return NULL;
T->count = 0;
T->size = size;
T->val = (Item*)calloc(size, sizeof(Item)); //ïàìÿòü ïîä ìàññèâ ýëåìåíòîâ
if (T->val == NULL)
{
free(T);
return NULL;
}
return T;
}
void TableSave(Table *T)
{
int i;
int st = 8 + sizeof(Item)*T->size;
fseek(T->fd,4,SEEK_SET);
fwrite(&T->count,sizeof(int),1,T->fd);
//Ïåðåñ÷èòûâàåì ñòðîêè
for(i=0;i<(T->size);i++)
{
if(T->val[i].busy==1)
{
T->val[i].len=strlen(T->val[i].info)+1;
T->val[i].offset = st;
st+=T->val[i].len;
}
else
{
T->val[i].len=0;
T->val[i].offset=0;
}
}
fwrite(T->val,sizeof(Item),T->size,T->fd);
for(i=0;i<T->size;i++)
{
if(T->val[i].busy==1)
fwrite(T->val[i].info,sizeof(char),T->val[i].len,T->fd);
}
fclose(T->fd);
T->fd=0;
}
//óäàëåíèå òàáëèöû
void TableDelete(Table* T)
{
int i;
for (i = 0; i < T->count; i++)
if (T->val[i].busy)
free(T->val[i].info); //óäàëåíèå èíôîðìàöèè
free(T->val); //÷èñòêà îñòàëüíîé ïàìÿòè
}
//âûâîä òàáëèöû
void TablePrint(Table* T)
{
int i;
printf("count = %d, size = %d.\n", T->count, T->size);
printf("%2s %7s %7s %s\n", "i", "key", "release", "string");
if (T->count == 0)
puts("Empty table");
for (i = 0; i < T->size; i++) //ïðîõîäèì ïî ìàññèâó
if (T->val[i].busy)
{
printf("%2d ", i);
ItemPrint(T,i); //âûâîäèì î÷åðåäíîé ýëåìåíò
}
else
{
printf("%2d -----no item-----\n", i); //åñëè ýëåìåíòà íåò, òî âûâîäèì ñîîòâåòñòâóþùåå ñîîáùåíèå
}
}
//äîáàâëåíèå êëþ÷à â òàáëèöó
int TableAdd(Table* T, int key, char* info)
{
int ind,st;
fseek(T->fd,0,SEEK_END);
st = ftell(T->fd);
if (T->count == T->size) //ïðîâåðêà íà ïåðåïîëíåíèå
TableZip(T); //ïûòàåìñÿ ñæàòü òàáëèöó
if (T->count == T->size) //åñëè íå ïîëó÷èëîñü ñæàòü - âîçâðàùàåì îøèáêó
return 1;
ind = TableFindLast(T, key); //ïîèñê èíäåêñà ïîñëåäíåé âåðñèè êëþ÷à
T->val[T->count].busy = 1; //ïèøåì íîâûé ýëåìåíò â êîíåö òàáëèöû
T->val[T->count].info = info;
T->val[T->count].key = key;
if (ind < 0)
T->val[T->count].release = 1; //ïèøåì ïðàâèëüíóþ âåðñèþ
else
T->val[T->count].release = T->val[ind].release + 1;
T->val[T->count].offset=st;
T->val[T->count].len = strlen(info)+1;
fwrite(info,strlen(info)+1,1,T->fd);
++T->count; //óâåëè÷èâàåì òåêóùåå êîëè÷åñòâî ýëåìåíòîâ â òàáëèöå
return 0;
}
//ñæàòèå ìàññèâà
void TableZip(Table* T)
{
int j = 0;
int i;
for (i = 0; i < T->count; i++)
if (T->val[i].busy) //ïåðåäâèãàåì íà ïóñòîå ìåñòî íàø ýëåìåíò
{
T->val[j].busy = T->val[i].busy;
T->val[j].info = T->val[i].info;
T->val[j].key = T->val[i].key;
T->val[j].len = T->val[i].len;
T->val[j].offset = T->val[i].offset;
T->val[j].release = T->val[i].release;
++j;
//TableDeleteRelease(T, T->val[i].key, T->val[i].release);
}
T->count = j;
}
//ïîèñê ýëåìåíòà â òàáëèöå
int TableFindLast(Table* T, int key)
{
int i;
for (i = T->count - 1; i >= 0; i--) //èä¸ì ñ êîíöà, ò.ê. âåðñèè ýëåìåíòà â ñèëó ìåõàíèçìà äîáàâëåíèÿ ðàñïîëîæåíû ïî âîçâðàñòàíèþ
if (T->val[i].busy && T->val[i].key == key) //ïîýòîìó ñàìîå ïîñëåäíåå óïîìèíàíèå êëþ÷à áóäåò ñ ñàìîé áîëüøîé âåðñèåé
return i;
return -1;
}
//óäàëåíèå êëþ÷à
int TableDeleteKey(Table* T, int key)
{
int count = 0, i;
for (i = 0; i < T->count; i++)
if (T->val[i].busy && T->val[i].key == key) //åñëè êëþ÷ ñîâïàë è ýëåìåíò ñóùåñòâóåò
{
T->val[i].busy = 0; //ïðîñòî ìåíÿåì ïîëå çàíÿòîñòè íà 0
free(T->val[i].info); //è î÷èùàåì ïàìÿòü îò èíôîðìàöèè
++count;
}
return count; //âîçâðàùàåì ÷èñëî óäàë¸ííûõ ýëåìåíòîâ
}
//óäàëåíèå ýëåìåíòa ïî êëþ÷ó è âåðñèè
int TableDeleteRelease(Table* T, int key, int release)
{
int i;
for (i = 0; i < T->count; i++)
if (T->val[i].busy && T->val[i].key == key && T->val[i].release == release) //åñëè êëþ÷ è âåðñèÿñîâïàëè
{
T->val[i].busy = 0; //ìåíÿåì çíà÷åíèå ïîëÿ çàíÿòîñòè
free(T->val[i].info); //î÷èùàåì èíôîðìàöèþ
return 1;
}
return 0;
}
//èùåì ýëåìåíò è ñîçäà¸ì òàáëèöó ñ íàéäåííûìè ýëåìåíòàìè
Table* TableFindKey(Table* T, int key)
{
Table* NewTable = TableCreate(T->size);
int i, j;
for (i = 0; i < T->count; i++)
if (T->val[i].busy && T->val[i].key == key) //åñëè ýëåìåíò ñóùåâñòóåò è êëþ÷è ñîâïàëè
{
j = NewTable->count; //ïèøåì â êîíåö íàøåé íîâîé òàáëèöû
NewTable->val[j].busy = 1;
NewTable->val[j].info = (char*)calloc(T->val[i].len, sizeof(char)); //êîïèþ íàéäåííîãî ýëåìåíòà
fseek(T->fd,T->val[i].offset,SEEK_SET);
fread(NewTable->val[j].info,sizeof(char),T->val[i].len,T->fd);
NewTable->val[j].len = T->val[i].len;
NewTable->val[j].offset = T->val[i].offset;
strcpy(NewTable->val[j].info, T->val[i].info);
NewTable->val[j].key = key;
NewTable->val[j].release = T->val[i].release;
++NewTable->count; //óâåëè÷èâàåì ðàçìåð òàáëèöû
}
NewTable->size = NewTable->count;
if (NewTable->count)
return NewTable;
else
TableDelete(NewTable);
return NULL;
}
//ïîèñê ïî êëþ÷ó è âåðñèè
char* TableFindRelease(Table* T, int key, int release)
{
int i;
char* info;
for (i = 0; i < T->count; i++)
if (T->val[i].busy && T->val[i].key == key && T->val[i].release == release) //åñëè ñîâïàëî
{
info = (char*)calloc(T->val[i].len, sizeof(char));
fseek(T->fd,T->val[i].offset,SEEK_SET);
fread(info,sizeof(char),T->val[i].len,T->fd);
strcpy(info, T->val[i].info); //êîïèðóåì èíôîðìàöèþ
return info; //è âîçâðàùàåì ñòðîêó
}
return NULL;
}
//âûâîä ýëåìåíòà
int ItemPrint(Table* T, int ind)
{
char *info = (char*)malloc(T->val[ind].len);
fseek(T->fd,T->val[ind].offset,SEEK_SET);
fread(info,sizeof(char),T->val[ind].len,T->fd);
printf("%7d %7d %s\n", T->val[ind].key, T->val[ind].release, info);
free(info);
return 0;
}
//äðóãèå ôóíêöèè
//÷òåíèå öåëîãî ÷èñëà
int getInt(int *a)
{
int n = scanf("%d", a); //ñ÷èòàåì ïî àäðåñó à - çíà÷åíèå ñèìâîëà. ñàìà ôóíêöèÿ âåðí¸ò -1, åñëè êîíåö ôàéëà, 0 åñëè ñèìâîë íå êîððåêòíûé
if (!n) // îáíàðóæåí íåêîððåêòíûé ñèìâîë - îøèáêà
printf("%s\n", "Error! All incorrect symbols will be skiped.");
while (n < 0)
{
scanf("%*c");
n = scanf("%d", a);
}
return 1;
}
//ïîëó÷àåì ñòðîêó èç âõîäíîãî ïîòîêà
int getStr(char** s)
{
char buf[21];
int n;
int len = 0; //ñþäà äëèíà ðåçóëüòèðóþùåé ñòðîêè
*s = (char *)malloc(1); //óêàçàòåëü íà ðåçóëüòèðóþùóþ ñòêðîó
**s = '\0'; //íîëü áàéò, ïîêà ñòðîêà èìååò òîëüêî êîíåö ñòðîêè
scanf("%*c");
do {
n = scanf("%20[^\n]", buf); //ñ÷èòûâàåì áóôåð
if (n < 0)
{ //åñëè ââåëè êîíåö ôàéëà (ctrl+Z), òî áóäåò -1
free(*s); //î÷èùàåì ïàìÿòü, âîçâðàùàåì ïóñòîé óêàçàòåëü
return -1;
}
if (n > 0) { //åñëè áóôåð íå ïóñòîé
len += strlen(buf); //óâåëè÷èâàåì ðåçóëüòèðóþùóþ äëèíó
*s = (char *)realloc(*s, len + 1); //äîáàâëÿåì ïàìÿòü
if (*s) //åñëè ïàìÿòü âûäåëèëàñü
strcat(*s, buf); //êîïèðóåì ñòðîêó èç áóôåðà â êîíåö íàøåé ñòðîêè
else
{ //åñëè ïàìÿòü íå âûäåëèëàñü
free(*s); //î÷èùàåì ïàìÿòü
return -2;
}
}
else
scanf("%*c"); //åñëè ïåðåíîñ ñòðîêè, òî î÷èùàåì âõîäíîé ïîòîê
} while (n > 0); //ïîêà âî âõîäíîì ïîòîêå åñòü õîòü îäèí ñèìâîë
return 0;
}