// KURSACH#6 V.01b // Task: bla-bla-bla... #include #include #include #include #include #include #include #include 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; irecSize); 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 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