// KURSACH#6 V.01b
// Task: bla-bla-bla...
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
typedef enum DataType {NIL, INT, LONGINT, FLOAT, CHAR, PTR_INT, PTR_LONGINT, PTR_FLOAT, PTR_CHAR};
struct UniType
{
union
{
int asInt;
long long asLongInt;
float asFloat;
char asChar;
int * asPtrInt;
long long * asPtrLongInt;
float * asPtrFloat;
char * asPtrChar;
};
DataType type;
UniType()
{
type = NIL;
asLongInt = 0;
}
UniType(DataType dt1)
{
type = dt1;
asLongInt = 0;
}
UniType(void * dp1, DataType dt1)
{
type = dt1;
switch (type)
{
case INT:
asInt = * ((int *) dp1);
break;
case LONGINT:
asLongInt = * ((long long *) dp1);
break;
case FLOAT:
asFloat = * ((float *) dp1);
break;
case CHAR:
asInt = * ((char *) dp1);
break;
case PTR_CHAR:
asPtrChar = (char *) dp1;
break;
default:
break;
}
}
bool operator>(UniType & ut1)
{
if (type == ut1.type)
{
switch (type)
{
case INT:
return (asInt > ut1.asInt);
case LONGINT:
return (asLongInt > ut1.asLongInt);
case FLOAT:
return (asFloat > ut1.asFloat);
case PTR_CHAR:
return strcmp(asPtrChar, ut1.asPtrChar) > 0;
default:
break;
}
}
return false;
}
bool operator<(UniType & ut1)
{
if (type == ut1.type)
{
switch (type)
{
case INT:
return (asInt < ut1.asInt);
case LONGINT:
return (asLongInt < ut1.asLongInt);
case FLOAT:
return (asFloat < ut1.asFloat);
case PTR_CHAR:
return strcmp(asPtrChar, ut1.asPtrChar) < 0;
default:
break;
}
}
return false;
}
bool operator==(UniType & ut1)
{
return ut1.asLongInt == asLongInt; /// KOSYAK!!!!
}
};
struct FieldDscr
{
int size;
int lenght;
int offset;
DataType type;
};
class DataDscr
{
public:
FieldDscr * fieldDscr;
int fieldQty;
int recSize;
public:
//////////////////////////////////////////////////////////////////////
DataDscr()
{
fieldDscr = NULL;
fieldQty = 0;
recSize = 0;
}
//////////////////////////////////////////////////////////////////////
void SetFieldQty(int fq)
{
FieldDscr * newDscr = new FieldDscr[fq];
if (fieldDscr)
{
if (fq < fieldQty)
fieldQty = fq;
memccpy(newDscr, fieldDscr, fieldQty, sizeof(FieldDscr)); //???
delete fieldDscr;
}
fieldQty = fq;
fieldDscr = newDscr;
}
//////////////////////////////////////////////////////////////////////
void SetField(int fn, DataType dt, int ln)
{
fieldDscr[fn].type = dt;
fieldDscr[fn].lenght = ln;
switch (dt)
{
case INT:
fieldDscr[fn].size = sizeof(int);
break;
case LONGINT:
fieldDscr[fn].size = sizeof(long long);
break;
case FLOAT:
fieldDscr[fn].size = sizeof(float);
break;
case CHAR:
fieldDscr[fn].size = sizeof(char);
break;
case PTR_CHAR:
fieldDscr[fn].size = sizeof(char);
break;
default:
break;
}
int offs = 0;
for (int i = 0; i < fieldQty; i++)
{
fieldDscr[i].offset = offs;
offs += fieldDscr[i].size * fieldDscr[i].lenght;
}
recSize = offs;
}
};
class DataStorage
{
protected:
DataDscr * dataDscr;
void * data;
int currRec;
int recQty;
unsigned int currField;
public:
//////////////////////////////////////////////////////////////////////
DataStorage()
{
data = NULL;
currRec = 0;
recQty = 0;
}
//////////////////////////////////////////////////////////////////////
DataStorage(DataDscr * dd)
{
DataDscr();
dataDscr = dd;
}
//////////////////////////////////////////////////////////////////////
~DataStorage()
{
if (data)
delete (char *) data;
}
//////////////////////////////////////////////////////////////////////
void SetRecQty(int rq)
{
void * newData = new char[rq * dataDscr->recSize];
if (data)
{
if (rq < recQty)
recQty = rq;
memccpy(newData, data, recQty, dataDscr->recSize); //???
delete (char *) data;
}
recQty = rq;
data = newData;
}
//////////////////////////////////////////////////////////////////////
int SetCurrRec(int cr)
{
if (cr < recQty)
currRec = cr;
return currRec;
}
//////////////////////////////////////////////////////////////////////
int operator++(int rq)
{
if ((currRec + 1) < recQty)
currRec++;
return currRec;
}
//////////////////////////////////////////////////////////////////////
int operator--(int rq)
{
if ((currRec - 1) >= 0)
currRec--;
return currRec;
}
//////////////////////////////////////////////////////////////////////
void LoadRecords(void * dp, int rq)
{
memcpy(data, dp, rq * dataDscr->recSize);
}
//////////////////////////////////////////////////////////////////////
DataStorage & operator[](unsigned p1)
{
currField = p1;
return * this;
}
//////////////////////////////////////////////////////////////////////
UniType Get()
{
UniType ur(((char *) data + dataDscr->recSize*currRec + dataDscr->fieldDscr[currField].offset),
dataDscr->fieldDscr[currField].type);
return ur;
}
//////////////////////////////////////////////////////////////////////
UniType Get(int rn1)
{
UniType ur(((char *) data + dataDscr->recSize*rn1 + dataDscr->fieldDscr[currField].offset),
dataDscr->fieldDscr[currField].type);
rn1 = 0;
return ur;
}
//////////////////////////////////////////////////////////////////////
void * GetRecPtr(unsigned int rn1)
{
return (char *) data + dataDscr->recSize*rn1;
}
//////////////////////////////////////////////////////////////////////
void SortMinMax(int fn = 0)
{
char * buff = new char[dataDscr->recSize];
for (int i=0; i<recQty; i++)
{
SetCurrRec(i);
UniType min = (* this)[fn].Get();
int minI = i;
for (int j=i+1; j<recQty; j++)
{
SetCurrRec(j);
if ((* this)[fn].Get() < min)
{
min = (* this)[fn].Get();
minI = j;
}
}
if (minI != i)
{
memcpy(buff, GetRecPtr(i), dataDscr->recSize);
memcpy(GetRecPtr(i), GetRecPtr(minI), dataDscr->recSize);
memcpy(GetRecPtr(minI), buff, dataDscr->recSize);
}
}
delete[] buff;
}
//////////////////////////////////////////////////////////////////////
unsigned int Search(UniType ud1, int fn = 0)
{
int tr = recQty - 1;
int br = 0;
while (true)
{
int cr = int(br + tr) / 2;
if ((* this)[fn].Get(cr) < ud1)
{
br = cr;
} else
if ((* this)[fn].Get(cr) > ud1)
{
tr = cr;
} else
return cr;
if ((int(br + tr) / 2) == cr)
{
if ((* this)[fn].Get(tr) == ud1)
return tr;
else
return 0;
}
}
}
//////////////////////////////////////////////////////////////////////
void SortMaxMin(int fn = 0)
{
char * buff = new char[dataDscr->recSize];
for (int i=0; i<recQty; i++)
{
SetCurrRec(i);
UniType max = (* this)[fn].Get();
int maxI = i;
for (int j=i+1; j<recQty; j++)
{
SetCurrRec(j);
if ((* this)[fn].Get() > max)
{
max = (* this)[fn].Get();
maxI = j;
}
}
if (maxI != i)
{
memcpy(buff, GetRecPtr(i), dataDscr->recSize);
memcpy(GetRecPtr(i), GetRecPtr(maxI), dataDscr->recSize);
memcpy(GetRecPtr(maxI), buff, dataDscr->recSize);
}
}
delete[] buff;
}
//////////////////////////////////////////////////////////////////////
};
class DataTable
{
protected:
char * fileName;
FILE * dataFile;
DataDscr * dataDscr;
DataStorage * storage;
int recQty;
public:
//////////////////////////////////////////////////////////////////////
DataTable()
{
fileName = NULL;
dataFile = NULL;
storage = NULL;
}
//////////////////////////////////////////////////////////////////////
~DataTable()
{
if (storage)
delete storage;
if (dataDscr)
delete dataDscr;
}
//////////////////////////////////////////////////////////////////////
void Init()
{
dataDscr = new DataDscr;
}
//////////////////////////////////////////////////////////////////////
void Open(char * fn)
{
fileName = fn;
dataFile = fopen(fileName, "r");
if (dataFile)
{
struct stat fileStat;
stat(fn, &fileStat);
int rqty = int(fileStat.st_size) / dataDscr->recSize;
storage = new DataStorage(dataDscr);
recQty = rqty;
fclose(dataFile);
}
else
recQty = 0;
}
//////////////////////////////////////////////////////////////////////
void Close()
{
if (storage)
delete storage;
fileName = NULL;
dataFile = NULL;
storage = NULL;
}
//////////////////////////////////////////////////////////////////////
void Update()
{
struct stat fileStat;
dataFile = fopen(fileName, "r");
stat(fileName, &fileStat);
recQty = int(fileStat.st_size) / dataDscr->recSize;
storage = new DataStorage(dataDscr);
storage->SetRecQty(recQty);
char * fimg = new char[dataDscr->recSize * recQty];
fread(fimg, dataDscr->recSize, recQty, dataFile);
storage->SetRecQty(recQty);
storage->LoadRecords(fimg, recQty);
delete fimg;
fclose(dataFile);
}
//////////////////////////////////////////////////////////////////////
void AddRecords(void * nr, int rq = 1)
{
dataFile = fopen(fileName, "a");
fwrite(nr, dataDscr->recSize, rq, dataFile);
fclose(dataFile);
recQty += rq;
}
//////////////////////////////////////////////////////////////////////
DataStorage & operator[] (int p1)
{
storage->SetCurrRec(p1);
return (* storage);
}
//////////////////////////////////////////////////////////////////////
int GetRecQty()
{
return recQty;
}
};
struct TGun
{
long long pKey;
char name[32];
char country[16];
char designer[16];
char caliber[16];
unsigned rate;
unsigned range;
unsigned year;
float weight;
};
class GunTable: public DataTable
{
public:
//////////////////////////////////////////////////////////////////////
void Init()
{
DataTable::Init();
dataDscr->SetFieldQty(9);
dataDscr->SetField(0, LONGINT, 1);
dataDscr->SetField(1, PTR_CHAR, 32);
dataDscr->SetField(2, PTR_CHAR, 16);
dataDscr->SetField(3, PTR_CHAR, 16);
dataDscr->SetField(4, PTR_CHAR, 16);
dataDscr->SetField(5, INT, 1);
dataDscr->SetField(6, INT, 1);
dataDscr->SetField(7, INT, 1);
dataDscr->SetField(8, FLOAT, 1);
}
//////////////////////////////////////////////////////////////////////
void Sort(int fn=0)
{
storage->SortMinMax(fn);
}
//////////////////////////////////////////////////////////////////////
void Select()
{
cout << "Enter pKey of record you want to find: ";
UniType ud1(LONGINT);
cin >> ud1.asLongInt;
storage->SetCurrRec(storage->Search(ud1, 0));
printf(" PKey: | Name: |Country: |Designer: |Caliber: | RoF: |Range:|Year: |Weight:\n");
printf("%6lli |%9s |%9s |%9s |%9s |%5d |%5d |%5d |%6.2f\n",
(* storage)[0].Get().asLongInt,
(* storage)[1].Get().asPtrChar,
(* storage)[2].Get().asPtrChar,
(* storage)[3].Get().asPtrChar,
(* storage)[4].Get().asPtrChar,
(* storage)[5].Get().asInt,
(* storage)[6].Get().asInt,
(* storage)[7].Get().asInt,
(* storage)[8].Get().asFloat
);
getchar();
}
//////////////////////////////////////////////////////////////////////
void Print()
{
printf(" PKey: | Name: |Country: |Designer: |Caliber: | RoF: |Range:|Year: |Weight:\n");
storage->SetCurrRec(0);
for (int i=0; i<recQty; i++)
{
printf("%6lli |%9s |%9s |%9s |%9s |%5d |%5d |%5d |%6.2f\n",
(* storage)[0].Get().asLongInt,
(* storage)[1].Get().asPtrChar,
(* storage)[2].Get().asPtrChar,
(* storage)[3].Get().asPtrChar,
(* storage)[4].Get().asPtrChar,
(* storage)[5].Get().asInt,
(* storage)[6].Get().asInt,
(* storage)[7].Get().asInt,
(* storage)[8].Get().asFloat
);
(* storage)++;
}
}
//////////////////////////////////////////////////////////////////////
void EnterRecord()
{
TGun sv;
memset(&sv, 0, sizeof(sv));
char pysh[16] = "";
printf("pKey: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%lli", &sv.pKey);
printf("Name: ");
gets(sv.name);
printf("Country: ");
gets(sv.country);
printf("Designer: ");
gets(sv.designer);
printf("Caliber: ");
gets(sv.caliber);
printf("Rate of fire: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.rate);
printf("Effective range: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.range);
printf("Year: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.year);
printf("Weight: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%f", &sv.weight);
AddRecords(&sv);
}
//////////////////////////////////////////////////////////////////////
void EnterTable()
{
int r = 0;
char pysh;
do
{
EnterRecord();
printf("Rerty? (y/n): ");
pysh = getchar();
r = 0;
while (!r)
if (pysh == 'y') r = 1;
else
if (pysh == 'n') r = 2;
getchar();
}
while (r!=2);
}
};
//////////////////////////////////////////////////////////////////////
GunTable Guns;
//////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
Guns.Init();
Guns.Open("Guns");
Guns.Update();
int choise = 10;
while (choise)
{
puts("*****************************************************************************");
puts("KURSACH#6 V0.01b");
puts(" 1 - Print \"Guns\" table;");
puts(" 2 - Sort records in \"Guns\" table;");
puts(" 3 - Find record in \"Guns\" table;");
puts(" 4 - Add information to \"Guns\" table;");
puts(" 5 - Exit");
puts("Select action:");
char pysh[16] = "";
choise = 10;
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &choise);
puts("*****************************************************************************");
switch(choise)
{
case 1:
Guns.Print();
getchar();
break;
case 2:
Guns.Sort();
break;
case 3:
Guns.Select();
break;
case 4:
Guns.EnterTable();
Guns.Update();
break;
case 5:
choise = 0;
break;
}
}
Guns.Close();
return EXIT_SUCCESS;
}
kursach09 final