// KURSACH#6 V.01b
// Task: bla-bla-bla...
#include <iostream>
#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 {INT, LONGINT, FLOAT, CHAR};
struct UniType
{
union
{
int asInt;
long long asLongInt;
float asFloat;
char asChar;
};
DataType type;
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 CHAR:
return strcmp(&asChar, &(ut1.asChar)) > 0;
}
}
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 CHAR:
return strcmp(&asChar, &(ut1.asChar)) < 0;
}
}
return false;
}
};
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;
}
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;
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);
}
//////////////////////////////////////////////////////////////////////
UniType & operator[](int p1)
{
return * ((UniType *) ((char *) data + dataDscr->recSize*currRec + dataDscr->fieldDscr[p1].offset));
}
//////////////////////////////////////////////////////////////////////
void Sort(int fn)
{
for (int i=0; i<recQty; i++)
{
UniType min = (* this)[i];
min.type = dataDscr->fieldDscr[fn].type;
for (int j=i+1; j<recQty; j++)
{
if ((* this)[i] < min)
{
min = (* this)[i];
min.type = dataDscr->fieldDscr[fn].type;
// nado sdelat' vozvrat ukazateley v [] cherez unitype;
}
}
}
}
//////////////////////////////////////////////////////////////////////
};
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, CHAR, 32);
dataDscr->SetField(2, CHAR, 16);
dataDscr->SetField(3, CHAR, 16);
dataDscr->SetField(4, CHAR, 16);
dataDscr->SetField(5, INT, 1);
dataDscr->SetField(6, INT, 1);
dataDscr->SetField(7, INT, 1);
dataDscr->SetField(8, FLOAT, 1);
}
//////////////////////////////////////////////////////////////////////
void Print()
{
printf(" PKey: | Name: |Designer: |Country: |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].asLongInt,
&((* storage)[1].asChar),
&((* storage)[2].asChar),
&((* storage)[3].asChar),
&((* storage)[4].asChar),
(* storage)[5].asInt,
(* storage)[6].asInt,
(* storage)[7].asInt,
(* storage)[8].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;
}
while (r!=2);
getchar();
}
};
//////////////////////////////////////////////////////////////////////
GunTable Guns;
//////////////////////////////////////////////////////////////////////
void TaskQuery()
{
// char str[8];
// int tn = 0;
// bool fl = true;
// printf("Enter number of term: ");
// gets(str);
// sscanf(str, "%d", &tn);
// puts("Guns who have not marks below than 4 (good):");
// for (int i=0; i<Guns.GetRecQty(); i++)
// {
// fl = true;
// for (int j=0; j<Marks.GetRecQty(); j++)
// {
// if ((Marks[j][1].asInt<=3) && (Marks[j][2].asInt==tn) && (Marks[j][3].asInt==i))
// fl = false;
// }
// if (fl)
// puts(&(Guns[i][1].asChar));
// }
}
//////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
Guns.Init();
Guns.Open("Guns");
int choise = 10;
while (choise)
{
puts("*****************************************************************************");
puts("KURSACH#6 V0.01b");
puts(" 1 - Print \"Guns\" table;");
puts(" 2 - Add information to \"Guns\" table;");
puts(" 7 - Make Task");
puts(" 8 - 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.Update();
Guns.Print();
getchar();
break;
case 2:
Guns.EnterTable();
break;
case 7:
TaskQuery();
getchar();
break;
case 8:
choise = 0;
break;
}
}
Guns.Close();
return EXIT_SUCCESS;
}