// 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>
union UniType
{
int asInt;
float asFloat;
char asChar;
};
typedef enum DataType {INT, FLOAT, CHAR};
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 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));
}
};
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 TStudent
{
uint pkey;
char surname[32];
char name[16];
char father[16];
uint sex;
uint group;
};
class StudTable: public DataTable
{
public:
//////////////////////////////////////////////////////////////////////
void Init()
{
DataTable::Init();
dataDscr->SetFieldQty(6);
dataDscr->SetField(0, INT, 1);
dataDscr->SetField(1, CHAR, 32);
dataDscr->SetField(2, CHAR, 16);
dataDscr->SetField(3, CHAR, 16);
dataDscr->SetField(4, INT, 1);
dataDscr->SetField(5, INT, 1);
}
//////////////////////////////////////////////////////////////////////
void Print()
{
printf("PKey: Surname: Name: Father name: Sex: Group:\n");
storage->SetCurrRec(0);
for (int i=0; i<recQty; i++)
{
printf("%10d %-12s %-12s %-12s %6d %6d\n",
(* storage)[0].asInt,
&((* storage)[1].asChar),
&((* storage)[2].asChar),
&((* storage)[3].asChar),
(* storage)[4].asInt,
(* storage)[5].asInt
);
(* storage)++;
}
}
//////////////////////////////////////////////////////////////////////
void EnterRecord()
{
TStudent sv;
memset(&sv, 0, sizeof(sv));
char pysh[16] = "";
printf("pKey: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.pkey);
printf("Surname: ");
gets(sv.surname);
printf("Name: ");
gets(sv.name);
printf("Father name: ");
gets(sv.father);
printf("Male/female: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.sex);
printf("group: ");
gets(pysh);
sscanf(pysh,"%d", &sv.group);
AddRecords(&sv);
}
//////////////////////////////////////////////////////////////////////
void EnterTable()
{
int r = 0;
char pysh[32];
do
{
EnterRecord();
printf("Rerty? (yes/no): ");
gets(pysh);
r = 0;
while (!r)
if (!strcmp(pysh, "yes")) r = 1;
else
if (!strcmp(pysh, "no")) r = 2;
}
while (r!=2);
}
};
struct TSubject
{
uint pkey;
char name[32];
};
class SubjectTable: public DataTable
{
public:
//////////////////////////////////////////////////////////////////////
void Init()
{
DataTable::Init();
dataDscr->SetFieldQty(2);
dataDscr->SetField(0, INT, 1);
dataDscr->SetField(1, CHAR, 32);
}
//////////////////////////////////////////////////////////////////////
void Print()
{
printf("PKey: Name:\n");
storage->SetCurrRec(0);
for (int i=0; i<recQty; i++)
{
printf("%10d %-12s\n",
(* storage)[0].asInt,
&((* storage)[1].asChar)
);
(* storage)++;
}
}
//////////////////////////////////////////////////////////////////////
void EnterRecord()
{
TSubject sv;
memset(&sv, 0, sizeof(sv));
char pysh[16];
printf("pKey: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.pkey);
printf("Name: ");
gets(sv.name);
AddRecords(&sv);
}
//////////////////////////////////////////////////////////////////////
void EnterTable()
{
int r = 0;
char pysh[32];
do
{
EnterRecord();
printf("Rerty? (yes/no): ");
gets(pysh);
r = 0;
while (!r)
if (!strcmp(pysh, "yes")) r = 1;
else
if (!strcmp(pysh, "no")) r = 2;
}
while (r!=2);
}
};
struct TMark
{
uint pkey;
uint mark;
uint term;
uint fkStudent;
uint fkSubject;
};
class MarkTable: public DataTable
{
public:
//////////////////////////////////////////////////////////////////////
void Init()
{
DataTable::Init();
dataDscr->SetFieldQty(5);
dataDscr->SetField(0, INT, 1);
dataDscr->SetField(1, INT, 1);
dataDscr->SetField(2, INT, 1);
dataDscr->SetField(3, INT, 1);
dataDscr->SetField(4, INT, 1);
}
//////////////////////////////////////////////////////////////////////
void Print()
{
printf("PKey: Mark: Term: fkStudent: fkSubject:\n");
storage->SetCurrRec(0);
for (int i=0; i<recQty; i++)
{
printf("%10d %6d %6d %6d %6d\n",
(* storage)[0].asInt,
(* storage)[1].asInt,
(* storage)[2].asInt,
(* storage)[3].asInt,
(* storage)[4].asInt
);
(* storage)++;
}
}
//////////////////////////////////////////////////////////////////////
void EnterRecord()
{
TMark sv;
memset(&sv, 0, sizeof(sv));
char pysh[16] = "";
printf("pKey: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.pkey);
printf("Mark: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.mark);
printf("Term: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.term);
printf("fkStudent: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.fkStudent);
printf("fkSubject: ");
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &sv.fkSubject);
AddRecords(&sv);
}
//////////////////////////////////////////////////////////////////////
void GenerateRecord()
{
TMark sv;
memset(&sv, 0, sizeof(sv));
sv.pkey = recQty + 1;
srandomdev();
sv.mark = 2 + random()%4;
sv.term = random()%12;
sv.fkStudent = 1 + random()%6;
sv.fkSubject = 1 + random()%6;
AddRecords(&sv);
}
//////////////////////////////////////////////////////////////////////
void EnterTable()
{
int r = 0;
char pysh[32];
do
{
//EnterRecord();
GenerateRecord();
printf("Rerty? (y/n): ");
gets(pysh);
r = 0;
while (!r)
if (!strcmp(pysh, "y")) r = 1;
else
if (!strcmp(pysh, "n")) r = 2;
}
while (r!=2);
}
};
//////////////////////////////////////////////////////////////////////
StudTable Students;
SubjectTable Subjects;
MarkTable Marks;
//////////////////////////////////////////////////////////////////////
void TaskQuery()
{
char str[8];
int tn = 0;
bool fl = true;
printf("Enter number of term: ");
gets(str);
sscanf(str, "%d", &tn);
puts("Students who have not marks below than 4 (good):");
for (int i=0; i<Students.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(&(Students[i][1].asChar));
}
}
//////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
Students.Init();
Students.Open("students");
Subjects.Init();
Subjects.Open("subjects");
Marks.Init();
Marks.Open("marks");
int choise = 10;
while (choise)
{
puts("*****************************************************************************");
puts("KURSACH#6 V0.01b");
puts(" 1 - Print \"Students\" table;");
puts(" 2 - Add information to \"Students\" table;");
puts(" 3 - Print \"Subjects\" table;");
puts(" 4 - Add information to \"Subjects\" table;");
puts(" 5 - Print \"Marks\" table;");
puts(" 6 - Add information to \"Marks\" table;");
puts(" 7 - Make Task");
puts(" 8 - Exit");
puts("Select action:");
char pysh[16] = "";
memset(pysh, 0, 16);
gets(pysh);
sscanf(pysh,"%d", &choise);
puts("*****************************************************************************");
switch(choise)
{
case 1:
Students.Update();
Students.Print();
getchar();
break;
case 2:
Students.EnterTable();
break;
case 3:
Subjects.Update();
Subjects.Print();
getchar();
break;
case 4:
Subjects.EnterTable();
break;
case 5:
Marks.Update();
Marks.Print();
getchar();
break;
case 6:
Marks.EnterTable();
break;
case 7:
TaskQuery();
getchar();
break;
case 8:
choise = 0;
break;
}
}
Students.Close();
Subjects.Close();
Marks.Close();
return EXIT_SUCCESS;
}