rename files, sex-
This commit is contained in:
@@ -0,0 +1,152 @@
|
|||||||
|
#pragma once
|
||||||
|
#include<fstream>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Array
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned size, num; //Size and number of elements
|
||||||
|
T* arr;
|
||||||
|
|
||||||
|
void copy(const Array &other);
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
Array();
|
||||||
|
Array(unsigned S);
|
||||||
|
//
|
||||||
|
Array& operator=(const Array &other);
|
||||||
|
~Array();
|
||||||
|
|
||||||
|
void resize(unsigned toAdd = 0);
|
||||||
|
unsigned gSize()const;
|
||||||
|
unsigned gNum()const;
|
||||||
|
void sNum(unsigned);
|
||||||
|
void push(const T&);
|
||||||
|
void remove(const unsigned id);
|
||||||
|
|
||||||
|
T& operator[](const unsigned i);
|
||||||
|
T& operator[](const unsigned i)const;
|
||||||
|
Array& operator+=(const Array &other);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Array<T>::Array() :
|
||||||
|
size(0),
|
||||||
|
num(0),
|
||||||
|
arr(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Array<T>::Array(unsigned S) :
|
||||||
|
size(S),
|
||||||
|
num(0)
|
||||||
|
{
|
||||||
|
arr = new T[S];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Array<T>& Array<T>::operator=(const Array &other)
|
||||||
|
{
|
||||||
|
copy(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Array<T>::~Array()
|
||||||
|
{
|
||||||
|
delete[] arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Array<T>::resize(unsigned toAdd)
|
||||||
|
{
|
||||||
|
toAdd = toAdd ? toAdd : size / 2;
|
||||||
|
T *temp = new T[num];
|
||||||
|
for (unsigned i = 0; i < num; ++i)
|
||||||
|
temp[i] = arr[i];
|
||||||
|
delete[] arr;
|
||||||
|
arr = new T[size + toAdd + 1];
|
||||||
|
for (unsigned i = 0; i < num; ++i)
|
||||||
|
arr[i]=temp[i];
|
||||||
|
size += toAdd + 1;
|
||||||
|
delete[] temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
unsigned Array<T>::gSize()const
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
unsigned Array<T>::gNum()const
|
||||||
|
{
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Array<T>::sNum(unsigned newNum)
|
||||||
|
{
|
||||||
|
num = newNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Array<T>::copy(const Array &other)
|
||||||
|
{
|
||||||
|
if (size < other.num)
|
||||||
|
{
|
||||||
|
delete[] arr;
|
||||||
|
arr = new T[other.num];
|
||||||
|
size = other.num;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < other.num; ++i)
|
||||||
|
arr[i] = other.arr[i];
|
||||||
|
num = other.num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Array<T>::push(const T& newEl)
|
||||||
|
{
|
||||||
|
if (num >= size)
|
||||||
|
resize();
|
||||||
|
arr[num] = newEl;
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Array<T>::remove(const unsigned id)
|
||||||
|
{
|
||||||
|
--num;
|
||||||
|
arr[id] = arr[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T& Array<T>::operator[](const unsigned i)
|
||||||
|
{
|
||||||
|
return arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T& Array<T>::operator[](const unsigned i)const
|
||||||
|
{
|
||||||
|
return arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Array<T>& Array<T>::operator+=(const Array &other)
|
||||||
|
{
|
||||||
|
if (size < other.num + num)
|
||||||
|
resize(other.num);
|
||||||
|
unsigned i = 0;
|
||||||
|
for (; i < other.num; ++i)
|
||||||
|
arr[num + i] = other.arr[i];
|
||||||
|
num += i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
typedef char C8;
|
||||||
|
|
||||||
|
typedef int8_t I8;
|
||||||
|
typedef uint8_t U8;
|
||||||
|
typedef int16_t I16;
|
||||||
|
typedef uint16_t U16;
|
||||||
|
typedef int32_t I32;
|
||||||
|
typedef uint32_t U32;
|
||||||
|
typedef int64_t I64;
|
||||||
|
typedef uint64_t U64;
|
||||||
|
|
||||||
|
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
g++ -Ofast -flto -fipa-pta -s *.cpp\
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
g++ *.cpp
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#include"help.h"
|
||||||
|
#include"tree.h"
|
||||||
|
|
||||||
|
unsigned strLen(const char* str)
|
||||||
|
{
|
||||||
|
unsigned len = 0;
|
||||||
|
for (; str[len] != '\0'; ++len)
|
||||||
|
;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void strCopy(char *to, const char* from)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
for (; from[i] != '\0'; ++i)
|
||||||
|
to[i] = from[i];
|
||||||
|
to[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool strComp(const char* first, const char* second)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; first[i] != '\0' || second[i] != '\0'; ++i)
|
||||||
|
{
|
||||||
|
if (first[i] != second[i])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* mergeStr(const char* first, const char* second) //Create new string from 2 existing and return it
|
||||||
|
{
|
||||||
|
char *result = new char[strLen(first) + strLen(second) + 1];
|
||||||
|
unsigned j = 0;
|
||||||
|
for (unsigned i = 0; first[i] != '\0'; ++i, ++j)
|
||||||
|
result[j] = first[i];
|
||||||
|
for (unsigned i = 0; second[i] != '\0'; ++i, ++j)
|
||||||
|
result[j] = second[i];
|
||||||
|
result[j] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Relation strToRel(const char* str)
|
||||||
|
{
|
||||||
|
if (strComp(str, "Father"))
|
||||||
|
return Father;
|
||||||
|
else if (strComp(str, "Mother"))
|
||||||
|
return Mother;
|
||||||
|
else if (strComp(str, "Son"))
|
||||||
|
return Son;
|
||||||
|
else if (strComp(str, "Daughter"))
|
||||||
|
return Daughter;
|
||||||
|
else if (strComp(str, "Brother"))
|
||||||
|
return Brother;
|
||||||
|
else if (strComp(str, "Sister"))
|
||||||
|
return Sister;
|
||||||
|
else if (strComp(str, "HalfBrother"))
|
||||||
|
return HalfBrother;
|
||||||
|
else if (strComp(str, "HalfSister"))
|
||||||
|
return HalfSister;
|
||||||
|
else if (strComp(str, "Wife"))
|
||||||
|
return Wife;
|
||||||
|
else if (strComp(str, "Husband"))
|
||||||
|
return Husband;
|
||||||
|
else if (strComp(str, "ExWife"))
|
||||||
|
return ExWife;
|
||||||
|
else if (strComp(str, "ExHusband"))
|
||||||
|
return ExHusband;
|
||||||
|
return Invalid;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum Relation : char;
|
||||||
|
|
||||||
|
unsigned strLen(const char* str);
|
||||||
|
void strCopy(char *to, const char* from);
|
||||||
|
bool strComp(const char* firts, const char* second); //0 - diffrent 1 - same
|
||||||
|
char* mergeStr(const char* first, const char* second);
|
||||||
|
Relation strToRel(const char* str);
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "tree.h"
|
||||||
|
#include "help.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/*Tree test1("Dechkovi"); //addTree Dechkovi addTree Karamanovi load 0 load 1 (to work with these example trees)
|
||||||
|
Tree test2("Karamanovi");
|
||||||
|
|
||||||
|
test1.addPerson("Rumen", 1968, 8, 9, 0);
|
||||||
|
test1.addPerson("Nadejda", 1972, 12, 15, 1);
|
||||||
|
test1.addRelation(0, Husband, 1);
|
||||||
|
test1.addPerson("Venelin", 1998, 6, 9, 0, 0, 1);
|
||||||
|
test1.addPerson("Vasil", 2001, 1, 16, 0, 0, 1);
|
||||||
|
test1.addRelation(2, Brother, 3);
|
||||||
|
test1.addPerson("Maria-Veronika", 2009, 9, 3, 1, 0, 1);
|
||||||
|
test1.addRelation(2, Brother, 4);
|
||||||
|
test1.addRelation(3, Brother, 4);
|
||||||
|
|
||||||
|
test2.addPerson("Vasil Dimitrov", 1941, 5, 18, 0);
|
||||||
|
test2.addPerson("Maria", 0, 0, 0, 1);
|
||||||
|
test2.addRelation(0, Husband, 1);
|
||||||
|
test2.addPerson("Dimitar", 0, 0, 0, 0, 0, 1);
|
||||||
|
test2.addPerson("Nadejda", 1972, 12, 15, 1, 0, 1);
|
||||||
|
test2.addRelation(2, Brother, 3);
|
||||||
|
test2.addPerson("Branimira", 0, 0, 0, 1);
|
||||||
|
test2.addRelation(2, Husband, 4);
|
||||||
|
test2.addPerson("Ioan", 0, 0, 0, 0, 2, 4);
|
||||||
|
test2.addPerson("Rumiana", 0, 0, 0, 1, 2, 4);
|
||||||
|
test2.addRelation(5, Brother, 6);
|
||||||
|
|
||||||
|
test1.saveTree();
|
||||||
|
test2.saveTree();*/
|
||||||
|
|
||||||
|
|
||||||
|
Array<Tree> trees;
|
||||||
|
|
||||||
|
bool quit=0;
|
||||||
|
char input[128];
|
||||||
|
short i; //Number of the entered command
|
||||||
|
const short numCom = 23;
|
||||||
|
const char* const commandList[] =
|
||||||
|
{
|
||||||
|
"quit", //0
|
||||||
|
"rename", //1
|
||||||
|
"load", //2
|
||||||
|
"save", //3
|
||||||
|
"addPerson", //4
|
||||||
|
"addPersonWP", //5 Adds a person and connects him to his parents, by their number
|
||||||
|
"addRelation", //6 Adds a relation between two people input by name
|
||||||
|
"addRelationID", //7 -||- by number
|
||||||
|
"findID", //8
|
||||||
|
"equate", //9 Enter the number of two trees, the second becomes equal to the first
|
||||||
|
"combine", //10
|
||||||
|
"subtract", //11
|
||||||
|
"removePerson", //12
|
||||||
|
"removePersonID", //13
|
||||||
|
"removeRelation", //14
|
||||||
|
"removeRelationID", //15
|
||||||
|
"addTree", //16
|
||||||
|
"prtRelatives", //17
|
||||||
|
"prtMember", //18
|
||||||
|
"prtAncestors", //19
|
||||||
|
"chooseTree", //20
|
||||||
|
"prtCommonAncestor",//21
|
||||||
|
"prtOldestAncestors"//22
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned curTree = 0, //Currently selected tree ID
|
||||||
|
id, secondId; //Indexes
|
||||||
|
Tree *newTree;
|
||||||
|
char name[128], secondName[128];
|
||||||
|
unsigned char day, month;
|
||||||
|
short year;
|
||||||
|
bool sex;
|
||||||
|
unsigned father, mother;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::cout << "Enter a command\n\n";
|
||||||
|
std::cin >> input;
|
||||||
|
for (i = 0; i < numCom; ++i)
|
||||||
|
{
|
||||||
|
if (strComp(input, commandList[i]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
std::cout << "Unknown command, try again\n\n";
|
||||||
|
break;
|
||||||
|
case 0: //quit
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
case 1: //rename
|
||||||
|
std::cout << "Enter new name\n\n";
|
||||||
|
std::cin >> name;
|
||||||
|
trees[curTree].rename(name);
|
||||||
|
break;
|
||||||
|
case 2: //load
|
||||||
|
if (!trees[curTree].loadTree())
|
||||||
|
std::cout << "File doesnt exist or is empty.\n\n";
|
||||||
|
break;
|
||||||
|
case 3: //save
|
||||||
|
trees[curTree].saveTree();
|
||||||
|
break;
|
||||||
|
case 4: //addPerson
|
||||||
|
std::cin >> name >> day >> month >> year >> sex;
|
||||||
|
trees[curTree].addPerson(name, year, month, day, sex);
|
||||||
|
break;
|
||||||
|
case 5: //addPersonWP
|
||||||
|
std::cin >> name >> day >> month >> year >> sex >> father >> mother;
|
||||||
|
trees[curTree].addPerson(name, year, month, day, sex, father, mother);
|
||||||
|
break;
|
||||||
|
case 6: //addRelation
|
||||||
|
std::cin >> name >> input >> secondName;
|
||||||
|
while (!strToRel(input))
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Relation, try again!\n";
|
||||||
|
std::cin >> input;
|
||||||
|
}
|
||||||
|
if(!trees[curTree].addRelation(name, strToRel(input), secondName))
|
||||||
|
std::cout << "Failure! One or both of the relatives don't exist.\n\n";
|
||||||
|
break;
|
||||||
|
case 7: //addRelationID
|
||||||
|
std::cin >> id >> input >> secondId;
|
||||||
|
while (!strToRel(input))
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Relation, try again!\n";
|
||||||
|
std::cin >> input;
|
||||||
|
}
|
||||||
|
if(trees[curTree].addRelation(id, strToRel(input), secondId))
|
||||||
|
std::cout << "Failure! One or both of the relatives don't exist.\n\n";
|
||||||
|
break;
|
||||||
|
case 8: //findID
|
||||||
|
std::cin >> name;
|
||||||
|
id = trees[curTree].findId(name);
|
||||||
|
if (id == Nobody)
|
||||||
|
std::cout << "No such person in tree " << curTree <<"\n\n";
|
||||||
|
else
|
||||||
|
std::cout << id << "\n\n";
|
||||||
|
break;
|
||||||
|
case 9: //equate
|
||||||
|
std::cin >> id >> secondId;
|
||||||
|
trees[id] = trees[secondId];
|
||||||
|
break;
|
||||||
|
case 10: //combine
|
||||||
|
std::cin >> id >> secondId;
|
||||||
|
trees[id] += trees[secondId];
|
||||||
|
break;
|
||||||
|
case 11: //subtract
|
||||||
|
std::cin >> id >> secondId;
|
||||||
|
trees[id] -= trees[secondId];
|
||||||
|
break;
|
||||||
|
case 12: //removePerson
|
||||||
|
std::cin >> name;
|
||||||
|
if (trees[curTree].findId(name) != Nobody)
|
||||||
|
trees[curTree].removePerson(name);
|
||||||
|
else
|
||||||
|
std::cout << "No such member!\n\n";
|
||||||
|
break;
|
||||||
|
case 13: //removePersonID
|
||||||
|
std::cin >> id;
|
||||||
|
if (trees[curTree].gNumP() > id)
|
||||||
|
trees[curTree].removePerson(id);
|
||||||
|
else
|
||||||
|
std::cout << "No such member!\n\n";
|
||||||
|
break;
|
||||||
|
case 14: //removeRelation
|
||||||
|
std::cin >> name >> secondName;
|
||||||
|
if (trees[curTree].gNumP() > trees[curTree].findId(name) && trees[curTree].gNumP() > trees[curTree].findId(secondName))
|
||||||
|
trees[curTree].removeRelation(name, secondName);
|
||||||
|
else
|
||||||
|
std::cout << "No such member!\n\n";
|
||||||
|
break;
|
||||||
|
case 15: //removeRelationID
|
||||||
|
std::cin >> id >> secondId;
|
||||||
|
if (trees[curTree].gNumP() > id && trees[curTree].gNumP() > secondId)
|
||||||
|
trees[curTree].removeRelation(id, secondId);
|
||||||
|
else
|
||||||
|
std::cout << "No such member\n\n";
|
||||||
|
break;
|
||||||
|
case 16: //addTree
|
||||||
|
std::cin >> name;
|
||||||
|
newTree = new Tree(name);
|
||||||
|
trees.push(*newTree);
|
||||||
|
delete newTree;
|
||||||
|
break;
|
||||||
|
case 17: //printRelatives
|
||||||
|
std::cin >> id;
|
||||||
|
if (id < trees[curTree].gNumP())
|
||||||
|
trees[curTree].printRel(id);
|
||||||
|
else
|
||||||
|
std::cout << "No such member\n\n";
|
||||||
|
break;
|
||||||
|
case 18: //printMember
|
||||||
|
std::cin >> id;
|
||||||
|
if (id < trees[curTree].gNumP())
|
||||||
|
trees[curTree].printMember(id);
|
||||||
|
else
|
||||||
|
std::cout << "No such member\n\n";
|
||||||
|
break;
|
||||||
|
case 19: //printAncestors
|
||||||
|
std::cin >> id;
|
||||||
|
/*if (id < trees[curTree].gNumP())
|
||||||
|
trees[curTree].printAncestors(id);
|
||||||
|
else
|
||||||
|
std::cout << "No such member\n\n";*/
|
||||||
|
break;
|
||||||
|
case 20: //chooseTree
|
||||||
|
std::cout << "Enter tree ID\n\n";
|
||||||
|
std::cin >> id;
|
||||||
|
if (id < trees.gNum())
|
||||||
|
curTree = id;
|
||||||
|
else
|
||||||
|
std::cout << "No such tree\n\n";
|
||||||
|
break;
|
||||||
|
case 21: //prtCommonAncestor
|
||||||
|
std::cin >> id >> secondId;
|
||||||
|
if (id < trees[curTree].gNumP() || secondId < trees[curTree].gNumP())
|
||||||
|
trees[curTree].printMember(trees[curTree].findCommonAncestor(id, secondId));
|
||||||
|
else
|
||||||
|
std::cout << "No such member\n\n";
|
||||||
|
break;
|
||||||
|
case 22: //prtOldestAncestors
|
||||||
|
std::cin >> id;
|
||||||
|
if (id < trees[curTree].gNumP())
|
||||||
|
trees[curTree].printOldestAncestors(id);
|
||||||
|
else
|
||||||
|
std::cout << "No such member\n\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (!quit);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
#include"person.h"
|
||||||
|
#include"help.h"
|
||||||
|
#include<iostream>
|
||||||
|
|
||||||
|
/*Person::Person():
|
||||||
|
name(nullptr),
|
||||||
|
numRel(0),
|
||||||
|
day(0),
|
||||||
|
month(0),
|
||||||
|
year(0),
|
||||||
|
isMale(true)
|
||||||
|
{}*/
|
||||||
|
|
||||||
|
Person::Person(const char* Name, unsigned char Day, unsigned char Month, short Year, bool IsMale) :
|
||||||
|
numRel(0),
|
||||||
|
day(Day),
|
||||||
|
month(Month),
|
||||||
|
year(Year),
|
||||||
|
isMale(IsMale)
|
||||||
|
{
|
||||||
|
name = new char[strLen(Name) + 1];
|
||||||
|
strCopy(name, Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Person& Person::operator=(const Person &other)
|
||||||
|
{
|
||||||
|
if (&other!=this)
|
||||||
|
{
|
||||||
|
rename(other.name);
|
||||||
|
numRel = other.numRel;
|
||||||
|
isMale = other.isMale;
|
||||||
|
day = other.day;
|
||||||
|
month = other.month;
|
||||||
|
year = other.year;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Person::~Person()
|
||||||
|
{
|
||||||
|
delete[] name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Person::operator==(const Person &other)const
|
||||||
|
{
|
||||||
|
return strComp(name, other.name) && isMale == other.isMale && (day == other.day || !day || !other.day) && (month == other.month || !month || !other.month) && (year == other.year || !year || !other.year);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Person::save(std::ofstream &file)const
|
||||||
|
{
|
||||||
|
//
|
||||||
|
char nameLen = strLen(name);
|
||||||
|
file.write(reinterpret_cast<char*>(&nameLen), sizeof(nameLen));
|
||||||
|
file.write(name, nameLen * sizeof(*name));
|
||||||
|
file.write(reinterpret_cast<const char*>(&numRel), sizeof(numRel));
|
||||||
|
file.write(reinterpret_cast<const char*>(&isMale), sizeof(isMale));
|
||||||
|
file.write(reinterpret_cast<const char*>(&day), sizeof(day));
|
||||||
|
file.write(reinterpret_cast<const char*>(&month), sizeof(month));
|
||||||
|
file.write(reinterpret_cast<const char*>(&year), sizeof(year));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Person::load(std::ifstream &file)
|
||||||
|
{
|
||||||
|
char nameLen;
|
||||||
|
file.read((char*)&nameLen, sizeof(nameLen));
|
||||||
|
|
||||||
|
name = new char[nameLen + 1];
|
||||||
|
file.read(name, nameLen * sizeof(*name));
|
||||||
|
name[nameLen] = '\0';
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&numRel), sizeof(numRel));
|
||||||
|
file.read(reinterpret_cast<char*>(&isMale), sizeof(isMale));
|
||||||
|
file.read(reinterpret_cast<char*>(&day), sizeof(day));
|
||||||
|
file.read(reinterpret_cast<char*>(&month), sizeof(month));
|
||||||
|
file.read(reinterpret_cast<char*>(&year), sizeof(year));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Person::rename(const char* newName)
|
||||||
|
{
|
||||||
|
delete[] name;
|
||||||
|
name = new char[strLen(newName) + 1];
|
||||||
|
strCopy(name, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Person::print()const
|
||||||
|
{
|
||||||
|
std::cout << name << "\nBirthday: " << (int)day << "." << (int)month << "." << year << "\nSex: ";
|
||||||
|
std::cout << (isMale ? "Male\n\n" : "Female\n\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <fstream>
|
||||||
|
#include "common/basicTypes.h"
|
||||||
|
|
||||||
|
class Person
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Person() = default;
|
||||||
|
Person(const char* Name, unsigned char Day, unsigned char Monthay, short Year, bool Sex);
|
||||||
|
//
|
||||||
|
Person& operator=(const Person &other);
|
||||||
|
~Person();
|
||||||
|
|
||||||
|
bool operator==(const Person &other)const;
|
||||||
|
|
||||||
|
void save(std::ofstream &file)const;//
|
||||||
|
void load(std::ifstream &file);
|
||||||
|
void rename(const char* newName);
|
||||||
|
void print()const;
|
||||||
|
|
||||||
|
friend class Tree;
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *name;
|
||||||
|
unsigned numRel; //Number of close relatives - mother, father, brother, sister, wife/husband, child, ex-wife/husband
|
||||||
|
unsigned char day, month; //Birth
|
||||||
|
short year;
|
||||||
|
bool isMale;
|
||||||
|
};
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# FamilyTree
|
||||||
|
|
||||||
|
I wrote this program in C ++ on Visual Studio 2017, starting with a blank project. I used iostream for input and output and fstream for saving and loading trees. Instead of using vector, I chose to write a dynamic array myself. I used HxD hex editor to look for errors in the files.
|
||||||
|
In the program, "family trees" are weighted graphs implemented through a list of neighbors. The program allows for addition, subtraction (removal of common members) and comparison of trees, saving them to and loading them from files and more.
|
||||||
|
|
||||||
|
Thus large constructs consisting of multiple family trees can be created and managed using this program.
|
||||||
|
|
||||||
|
# How to use
|
||||||
|
|
||||||
|
The program works with an array of trees numbered from 0. In order to execute a command on a tree you need to enter its number(treeID).
|
||||||
|
(S/E) = (Space/Enter)
|
||||||
|
|
||||||
|
Relations are as followed and cap sensitive:
|
||||||
|
|
||||||
|
Father
|
||||||
|
Mother
|
||||||
|
Son
|
||||||
|
Daughter
|
||||||
|
Brother
|
||||||
|
Sister
|
||||||
|
HalfBrother
|
||||||
|
HalfSister
|
||||||
|
Wife
|
||||||
|
Husband
|
||||||
|
ExWife
|
||||||
|
ExHusband
|
||||||
|
|
||||||
|
List of commands:
|
||||||
|
|
||||||
|
"quit" (S/E) - close the program
|
||||||
|
|
||||||
|
"chooseTree" (S/E) TreeID (S/E) - Choose tree to execute commands on
|
||||||
|
|
||||||
|
"addTree" (S/E) TreeName (S/E) - Adds a tree to the array
|
||||||
|
|
||||||
|
"rename" (S/E) NewName (S/E) - Renames a tree
|
||||||
|
|
||||||
|
"load" (S/E) TreeID (S/E) - Loads a tree based on its name
|
||||||
|
|
||||||
|
"save" (S/E) TreeID (S/E) - Saves a tree based on its name
|
||||||
|
|
||||||
|
"addPerson" (S/E) BirthDay (S/E) BirthMonth (S/E) BirthYear (S/E) PersonSex (S/E) - Add a person to a tree with treeID with a birthday on BirthDay.BirthMonth.BirthYear and sex (PersonSex) 0 = Male 1 = Female
|
||||||
|
|
||||||
|
"addPersonWP" (S/E) BirthDay (S/E) BirthMonth (S/E) BirthYear (S/E) PersonSex (S/E) FatherID (S/E) MotherID - The same as addPerson but adds father and motherbased on their IDs
|
||||||
|
|
||||||
|
"addRelation" (S/E) FirstRelativeName (S/E) Relation (S/E) SecondRelativeName - Adds a relation betwean two members based on their full names
|
||||||
|
|
||||||
|
"addRelationID" (S/E) FirstRelativeID (S/E) Relation (S/E) SecondRelativeID - Same as addElation but based on ID
|
||||||
|
|
||||||
|
"findID" (S/E) SoughtPersonName (S/E) - Prints the ID of a person with the given name
|
||||||
|
|
||||||
|
"equate" (S/E) FirstTreeID (S/E) SecondTreeID - Enter the IDs of two trees, the first one becomes equal to the second one
|
||||||
|
|
||||||
|
"combine" (S/E) FirstTreeID (S/E) SecondTreeID - Enter the IDs of two trees, the first one becomes equal to the combinatio of the two
|
||||||
|
|
||||||
|
"subtract" (S/E) FirstTreeID (S/E) SecondTreeID - Enter the IDs of two trees, the members that are present in both trees are removed from the first tree
|
||||||
|
|
||||||
|
"removePerson" (S/E) Name - Remove person with the given name
|
||||||
|
|
||||||
|
"removePersonID" (S/E) Name - Remove person with the given ID
|
||||||
|
|
||||||
|
"removeRelation" (S/E) FirstName (S/E) SecondName - Remove the relation betwean the people with the given names if they have one
|
||||||
|
|
||||||
|
"removeRelationID" (S/E) FirstName (S/E) SecondName - Same as removeRelation but with IDs instead
|
||||||
|
|
||||||
|
"prtRelatives" (S/E) PersonID - Print the relatives the person with the given ID in the console
|
||||||
|
|
||||||
|
"prtMember" (S/E) PersonID - Print the personal data of a member on the console
|
||||||
|
|
||||||
|
"prtCommonAncestor" (S/E) FirstPersonID (S/E) SecondPersonID (S/E)
|
||||||
|
|
||||||
|
"prtOldestAncestor" (S/E) PersonID (S/E)
|
||||||
@@ -0,0 +1,574 @@
|
|||||||
|
#include"tree.h"
|
||||||
|
#include"person.h"
|
||||||
|
#include"help.h"
|
||||||
|
#include<fstream>
|
||||||
|
|
||||||
|
|
||||||
|
Tree::Tree() :
|
||||||
|
numPeople(0)
|
||||||
|
{
|
||||||
|
treeName = new char[strLen("Unnamed") + 1];
|
||||||
|
strCopy(treeName, "Unnamed");
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree::Tree(const char *Name):
|
||||||
|
numPeople(0)
|
||||||
|
{
|
||||||
|
treeName = new char[strLen(Name) + 1];
|
||||||
|
strCopy(treeName, Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree::Tree(const Tree& other) :
|
||||||
|
numPeople(other.numPeople)
|
||||||
|
{
|
||||||
|
treeName = new char[strLen(other.treeName) + 1];
|
||||||
|
strCopy(treeName, other.treeName);
|
||||||
|
people = other.people;
|
||||||
|
relatives = other.relatives;
|
||||||
|
relations = other.relations;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree& Tree::operator= (const Tree& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
rename(other.treeName);
|
||||||
|
numPeople = other.numPeople;
|
||||||
|
people = other.people;
|
||||||
|
relatives = other.relatives;
|
||||||
|
relations = other.relations;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree::~Tree()
|
||||||
|
{
|
||||||
|
delete[] treeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Tree Tree::operator+ (const Tree& other)//
|
||||||
|
{
|
||||||
|
Tree result(mergeStr(treeName, other.treeName)); //The tree resulting from the addition
|
||||||
|
unsigned *newId = new unsigned[other.numPeople]; //The indexes members of the II tree will have in result
|
||||||
|
|
||||||
|
unsigned idCounter = numPeople;
|
||||||
|
for (unsigned i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in result
|
||||||
|
{
|
||||||
|
for (j = 0; j < numPeople; ++j)
|
||||||
|
{
|
||||||
|
if (other.people[i] == people[j])
|
||||||
|
{
|
||||||
|
newId[i] = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= numPeople)
|
||||||
|
newId[i] = ++idCounter;
|
||||||
|
}
|
||||||
|
result.numPeople = idCounter; //The number of members the resulting tree has
|
||||||
|
|
||||||
|
result.people.resize(result.numPeople);
|
||||||
|
result.people = people; //Adds the members of the I tree to the resulting tree
|
||||||
|
for (unsigned i=0; i < other.numPeople; ++i) //Adds the members of the II tree to the resulting tree
|
||||||
|
{
|
||||||
|
if (newId[i] >= numPeople)
|
||||||
|
result.people.push(other.people[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.relatives.resize(result.numPeople);
|
||||||
|
result.relations.resize(result.numPeople);
|
||||||
|
result.relatives = relatives;
|
||||||
|
result.relations = relations;
|
||||||
|
|
||||||
|
for (unsigned i=0; i < other.numPeople; ++i) //Adds the relatives from the II tree
|
||||||
|
{
|
||||||
|
if (newId[i] >= numPeople) //If the member is found in the II tree but not in the I
|
||||||
|
{
|
||||||
|
result.relatives.push(other.relatives[i]);
|
||||||
|
result.relations.push(other.relations[i]);
|
||||||
|
}
|
||||||
|
else //If he's found in both
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < other.people[i].numRel; ++j) //Adds the number of relatives from the II to the number in the I
|
||||||
|
{
|
||||||
|
if(newId[other.relatives[i][j]] > numPeople)
|
||||||
|
++result.people[newId[i]].numRel;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.relatives[newId[i]].resize(result.people[newId[i]].numRel);
|
||||||
|
result.relations[newId[i]].resize(result.people[newId[i]].numRel);
|
||||||
|
|
||||||
|
result.relatives[newId[i]] = relatives[newId[i]];
|
||||||
|
result.relations[newId[i]] = relations[newId[i]];
|
||||||
|
result.relatives[newId[i]] += other.relatives[i]; //The relatives from the II tree
|
||||||
|
result.relations[newId[i]] += other.relations[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[]newId;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree& Tree::operator+=(const Tree& other)
|
||||||
|
{
|
||||||
|
unsigned *newId = new unsigned[other.numPeople]; //The indexes people from II tree will have in I tree
|
||||||
|
|
||||||
|
unsigned idCounter = numPeople;
|
||||||
|
for (unsigned i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in I
|
||||||
|
{
|
||||||
|
for (j = 0; j < numPeople; ++j)
|
||||||
|
{
|
||||||
|
if (other.people[i] == people[j])
|
||||||
|
{
|
||||||
|
newId[i] = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= numPeople)
|
||||||
|
newId[i] = idCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
people.resize(idCounter);
|
||||||
|
for (unsigned i = 0; i < other.numPeople; ++i) //Adds the member personal data of II tree to I tree
|
||||||
|
{
|
||||||
|
if (newId[i] >= numPeople)
|
||||||
|
people.push(other.people[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
relatives.resize(idCounter);
|
||||||
|
relations.resize(idCounter);
|
||||||
|
for (unsigned i = 0; i < other.numPeople; ++i) //Merges the relative data
|
||||||
|
{
|
||||||
|
if (newId[i] >= numPeople)
|
||||||
|
{
|
||||||
|
relatives.push(other.relatives[i]);
|
||||||
|
for (unsigned j = 0; j < other.people[i].numRel; ++j)
|
||||||
|
relatives[newId[i]][j] = newId[ relatives[newId[i]][j] ];
|
||||||
|
relations.push(other.relations[i]);
|
||||||
|
}
|
||||||
|
else //If the member is present in both trees
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < other.people[i].numRel; ++j) //Adds the number of relatives from the II to the number in the I
|
||||||
|
{
|
||||||
|
if (newId[other.relatives[i][j]] >= numPeople)
|
||||||
|
++people[newId[i]].numRel;
|
||||||
|
}
|
||||||
|
relatives[newId[i]].resize(people[newId[i]].numRel);
|
||||||
|
relations[newId[i]].resize(people[newId[i]].numRel);
|
||||||
|
for (unsigned j = 0; j < other.people[i].numRel; ++j)
|
||||||
|
{
|
||||||
|
relatives[newId[i]][j + people[newId[i]].numRel - other.people[i].numRel] = newId[other.relatives[i][j]];
|
||||||
|
relations[newId[i]][j + people[newId[i]].numRel - other.people[i].numRel] = other.relations[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[]newId;
|
||||||
|
numPeople = idCounter; //Number of members in I tree
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree& Tree::operator-= (const Tree& other)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < other.numPeople; ++j)
|
||||||
|
{
|
||||||
|
if (people[i] == other.people[j])
|
||||||
|
{
|
||||||
|
removePerson(i);
|
||||||
|
--i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Tree::rename(const char* newName)
|
||||||
|
{
|
||||||
|
delete[] treeName;
|
||||||
|
treeName = new char[strLen(newName) + 1];
|
||||||
|
strCopy(treeName, newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Tree::findId(const char* name, const short year, const unsigned char month, const unsigned char day)const
|
||||||
|
{
|
||||||
|
//Person sought(name, day, month, year,)
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
{
|
||||||
|
if (strComp(name, people[i].name) && (year == people[i].year || !year || !people[i].year) && (month == people[i].month || !month || !people[i].month) && (day == people[i].day || !day || people[i].day))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return Nobody;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Tree::findOldestAncestor(const unsigned &id, const bool &isMale)const
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < people[id].numRel; ++i)
|
||||||
|
{
|
||||||
|
if (relations[id][i] == Son && people[ relatives[id][i] ].isMale == isMale)
|
||||||
|
return findOldestAncestor(relatives[id][i], isMale);
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Tree::findCommonAncestor(const unsigned firstId, const unsigned secondId)const
|
||||||
|
{
|
||||||
|
Array<char> visited(numPeople); //if a member is visited twice he's a common ancestor
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
visited[i] = 0;
|
||||||
|
commonAncestorRec(firstId, visited);
|
||||||
|
commonAncestorRec(secondId, visited);
|
||||||
|
|
||||||
|
unsigned oldestId = Nobody;
|
||||||
|
short oldestBday = SHRT_MAX;
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
{
|
||||||
|
if (visited[i] == 2 && people[i].year<oldestBday)
|
||||||
|
{
|
||||||
|
oldestBday = people[i].year;
|
||||||
|
oldestId = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oldestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::saveTree()const
|
||||||
|
{
|
||||||
|
char* fileName = mergeStr(treeName, ".people");
|
||||||
|
std::ofstream peopleFile(fileName, std::ios::binary);
|
||||||
|
delete[] fileName;
|
||||||
|
|
||||||
|
peopleFile.write(reinterpret_cast<const char*>(&numPeople), sizeof(numPeople));
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
people[i].save(peopleFile);
|
||||||
|
peopleFile.close();
|
||||||
|
|
||||||
|
fileName = mergeStr(treeName, ".relatives");
|
||||||
|
std::ofstream relativeFile(fileName, std::ios::binary);
|
||||||
|
delete[] fileName;
|
||||||
|
fileName = mergeStr(treeName, ".relations");
|
||||||
|
std::ofstream relationFile(fileName, std::ios::binary);
|
||||||
|
delete[] fileName;
|
||||||
|
|
||||||
|
/*relativeFile.write((char*)&numPeople, sizeof(numPeople));
|
||||||
|
relationFile.write((char*)&numPeople, sizeof(numPeople));*/
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
{
|
||||||
|
//relativeFile.write((char*)&people[i].numRel, sizeof(people[i].numRel));
|
||||||
|
for (unsigned j = 0; j < people[i].numRel; ++j)
|
||||||
|
relativeFile.write(reinterpret_cast<char*>(&relatives[i][j]), sizeof(relatives[i][j]));
|
||||||
|
|
||||||
|
//relationFile.write((char*)&people[i].numRel, sizeof(people[i].numRel));
|
||||||
|
for (unsigned j = 0; j < people[i].numRel; ++j)
|
||||||
|
relationFile.write(reinterpret_cast<char*>(&relations[i][j]), sizeof(relations[i][j]));
|
||||||
|
}
|
||||||
|
relativeFile.close();
|
||||||
|
relationFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tree::loadTree()
|
||||||
|
{
|
||||||
|
char* fileName = mergeStr(treeName, ".people");//c
|
||||||
|
std::ifstream peopleFile(fileName, std::ios::binary);
|
||||||
|
delete[] fileName;
|
||||||
|
if (peopleFile.peek() == std::char_traits<char>::eof())
|
||||||
|
{
|
||||||
|
peopleFile.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
peopleFile.read(reinterpret_cast<char*>(&numPeople), sizeof(numPeople));
|
||||||
|
people.resize(numPeople);
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
people[i].load(peopleFile);
|
||||||
|
people.sNum(numPeople);
|
||||||
|
peopleFile.close();
|
||||||
|
|
||||||
|
fileName = mergeStr(treeName, ".relatives");
|
||||||
|
std::ifstream relativeFile(fileName, std::ios::binary);
|
||||||
|
delete[] fileName;
|
||||||
|
fileName = mergeStr(treeName, ".relations");
|
||||||
|
std::ifstream relationFile(fileName, std::ios::binary);
|
||||||
|
delete[] fileName;
|
||||||
|
|
||||||
|
relatives.resize(numPeople);
|
||||||
|
relations.resize(numPeople);
|
||||||
|
for (unsigned i = 0; i < numPeople; ++i)
|
||||||
|
{
|
||||||
|
relatives[i].resize(people[i].numRel);
|
||||||
|
for (unsigned j = 0; j < people[i].numRel; ++j)
|
||||||
|
relativeFile.read(reinterpret_cast<char*>(&relatives[i][j]), sizeof(relatives[i][j]));
|
||||||
|
relatives[i].sNum(people[i].numRel);
|
||||||
|
|
||||||
|
relations[i].resize(people[i].numRel);
|
||||||
|
for (unsigned j = 0; j < people[i].numRel; ++j)
|
||||||
|
relationFile.read(reinterpret_cast<char*>(&relations[i][j]), sizeof(relations[i][j]));
|
||||||
|
relations[i].sNum(people[i].numRel);
|
||||||
|
}
|
||||||
|
relatives.sNum(numPeople);
|
||||||
|
relations.sNum(numPeople);
|
||||||
|
relativeFile.close();
|
||||||
|
relationFile.close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::addPerson(const char *name, short year, unsigned char month, unsigned char day, bool isMale, unsigned father, unsigned mother)
|
||||||
|
{
|
||||||
|
Person newPerson(name, day, month, year, isMale);
|
||||||
|
people.push(newPerson);
|
||||||
|
Array<unsigned> newRelative;
|
||||||
|
relatives.push(newRelative);
|
||||||
|
Array<Relation> newRelation;
|
||||||
|
relations.push(newRelation);
|
||||||
|
++numPeople;
|
||||||
|
addRelation(father, Father, numPeople - 1);
|
||||||
|
addRelation(mother, Mother, numPeople - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tree::addRelation(const char* firstName, const Relation type, const char* secondName)
|
||||||
|
{
|
||||||
|
|
||||||
|
return addRelation(findId(firstName), type, findId(secondName));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tree::addRelation(const unsigned firstId, const Relation type, const unsigned secondId, bool opposite)//
|
||||||
|
{
|
||||||
|
if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == Invalid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
for (; i < people[firstId].numRel; ++i) //If they are already relatives
|
||||||
|
{
|
||||||
|
if (relatives[firstId][i] == secondId)
|
||||||
|
{
|
||||||
|
relations[firstId][i] = type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= people[firstId].numRel)
|
||||||
|
{
|
||||||
|
relatives[firstId].push(secondId);
|
||||||
|
relations[firstId].push(type);
|
||||||
|
++people[firstId].numRel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opposite)
|
||||||
|
{
|
||||||
|
if (people[secondId].isMale)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Father:
|
||||||
|
case Mother:
|
||||||
|
addRelation(secondId, Son, firstId, 1);
|
||||||
|
break;
|
||||||
|
case Son:
|
||||||
|
case Daughter:
|
||||||
|
addRelation(secondId, Father, firstId, 1);
|
||||||
|
break;
|
||||||
|
case Brother:
|
||||||
|
case Sister:
|
||||||
|
addRelation(secondId, Brother, firstId, 1);
|
||||||
|
break;
|
||||||
|
case HalfBrother:
|
||||||
|
case HalfSister:
|
||||||
|
addRelation(secondId, HalfBrother, firstId, 1);
|
||||||
|
break;
|
||||||
|
case Wife:
|
||||||
|
addRelation(secondId, Husband, firstId, 1);
|
||||||
|
break;
|
||||||
|
case ExWife:
|
||||||
|
addRelation(secondId, ExHusband, firstId, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Father:
|
||||||
|
case Mother:
|
||||||
|
addRelation(secondId, Daughter, firstId, 1);
|
||||||
|
break;
|
||||||
|
case Son:
|
||||||
|
case Daughter:
|
||||||
|
addRelation(secondId, Mother, firstId, 1);
|
||||||
|
break;
|
||||||
|
case Brother:
|
||||||
|
case Sister:
|
||||||
|
addRelation(secondId, Sister, firstId, 1);
|
||||||
|
break;
|
||||||
|
case HalfBrother:
|
||||||
|
case HalfSister:
|
||||||
|
addRelation(secondId, HalfSister, firstId, 1);
|
||||||
|
break;
|
||||||
|
case Husband:
|
||||||
|
addRelation(secondId, Wife, firstId, 1);
|
||||||
|
break;
|
||||||
|
case ExHusband:
|
||||||
|
addRelation(secondId, ExWife, firstId, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::removeRelation(const char* firstName, const char* secondName)
|
||||||
|
{
|
||||||
|
removeRelation(findId(firstName), findId(secondName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::removePerson(const unsigned id)
|
||||||
|
{
|
||||||
|
unsigned relId; //Íoìåð íà òåêóùèÿ ðîäíèíàòà
|
||||||
|
for (unsigned i = 0; i < people[id].numRel; ++i) //Ïðåìàõâàò ñå âðúçêèòå íà ÷ëåíà çà ïðåìàõâàíå
|
||||||
|
{
|
||||||
|
relId = relatives[id][i];
|
||||||
|
for (unsigned j = 0; j < people[relId].numRel; ++j)
|
||||||
|
{
|
||||||
|
if (relatives[relId][j] == id)
|
||||||
|
{
|
||||||
|
relatives[relId].remove(j);
|
||||||
|
relations[relId].remove(j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--people[relId].numRel;
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < people[numPeople - 2].numRel; ++i) //Ïîñëåäíèÿò ÷ëåí âçåìà íîìåðà íà ïðåìàõíàòèÿ
|
||||||
|
{
|
||||||
|
relId = relatives[numPeople - 1][i];
|
||||||
|
for (unsigned j = 0; j < people[relId].numRel; ++j)
|
||||||
|
{
|
||||||
|
if (relatives[relId][j] == numPeople - 1)
|
||||||
|
{
|
||||||
|
relatives[relId][j] = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relatives.remove(id);
|
||||||
|
relations.remove(id);
|
||||||
|
people.remove(id);
|
||||||
|
--numPeople;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::removePerson(const char* personName, const short year, const unsigned char month, const unsigned char day)
|
||||||
|
{
|
||||||
|
removePerson(findId(personName, year, month, day));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < people[firstId].numRel; ++i)
|
||||||
|
{
|
||||||
|
if (relatives[firstId][i] == secondId)
|
||||||
|
{
|
||||||
|
relatives[firstId].remove(i);
|
||||||
|
relations[firstId].remove(i);
|
||||||
|
--people[firstId].numRel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < people[secondId].numRel; ++i)
|
||||||
|
{
|
||||||
|
if (relatives[secondId][i] == firstId)
|
||||||
|
{
|
||||||
|
relatives[secondId].remove(i);
|
||||||
|
relations[secondId].remove(i);
|
||||||
|
--people[secondId].numRel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Tree::printRel(const unsigned id)const
|
||||||
|
{
|
||||||
|
if (people[id].numRel == 0)
|
||||||
|
{
|
||||||
|
std::cout << "No relatives";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned relId;
|
||||||
|
std::cout <<people[id].name<< "'s relatives:\n";
|
||||||
|
for (unsigned i = 0; i < people[id].numRel; ++i)
|
||||||
|
{
|
||||||
|
relId = relatives[id][i];
|
||||||
|
std::cout << people[relId].name << " - ";
|
||||||
|
|
||||||
|
switch (relations[id][i])
|
||||||
|
{
|
||||||
|
case Father:
|
||||||
|
case Mother:
|
||||||
|
std::cout << (people[relId].isMale ? "son" : "daughter");
|
||||||
|
break;
|
||||||
|
case Son:
|
||||||
|
case Daughter:
|
||||||
|
std::cout << (people[relId].isMale ? "father" : "mother");
|
||||||
|
break;
|
||||||
|
case Brother:
|
||||||
|
case Sister:
|
||||||
|
std::cout << (people[relId].isMale ? "brother" : "sister");
|
||||||
|
break;
|
||||||
|
case HalfBrother:
|
||||||
|
case HalfSister:
|
||||||
|
std::cout << (people[relId].isMale ? "half brother" : "half sister");
|
||||||
|
break;
|
||||||
|
case Husband:
|
||||||
|
std::cout << "wife";
|
||||||
|
break;
|
||||||
|
case Wife:
|
||||||
|
std::cout << "husband";
|
||||||
|
break;
|
||||||
|
case ExHusband:
|
||||||
|
std::cout << "ex-wife\n";
|
||||||
|
break;
|
||||||
|
case ExWife:
|
||||||
|
std::cout << "ex-husband\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::printMember(const unsigned id)const
|
||||||
|
{
|
||||||
|
people[id].print();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::printOldestAncestors(const unsigned id)const
|
||||||
|
{
|
||||||
|
people[findOldestAncestor(id)].print();
|
||||||
|
people[findOldestAncestor(id, 1)].print();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned Tree::gNumP()const
|
||||||
|
{
|
||||||
|
return numPeople;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Tree::commonAncestorRec(const unsigned &id, const Array<char> &visited)const
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < people[id].numRel; ++i)
|
||||||
|
{
|
||||||
|
if (relations[id][i] == Son)
|
||||||
|
{
|
||||||
|
++visited[relatives[id][i]];
|
||||||
|
commonAncestorRec(relatives[id][i], visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <climits>
|
||||||
|
#include"array.h"
|
||||||
|
|
||||||
|
class Person;
|
||||||
|
|
||||||
|
enum Relation : char
|
||||||
|
{
|
||||||
|
Invalid = 0,
|
||||||
|
Father,
|
||||||
|
Mother,
|
||||||
|
Son,
|
||||||
|
Daughter,
|
||||||
|
Brother,
|
||||||
|
Sister,
|
||||||
|
HalfBrother,
|
||||||
|
HalfSister,
|
||||||
|
Wife,
|
||||||
|
Husband,
|
||||||
|
ExWife,
|
||||||
|
ExHusband
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned Nobody = UINT_MAX; //Òîçè íîìåð ùå áúäå çàïàçeí çà ëèïñà íà âðúçêà/÷îâåê
|
||||||
|
|
||||||
|
class Tree
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char *treeName;
|
||||||
|
unsigned numPeople;
|
||||||
|
Array<Person> people; //The data for each member
|
||||||
|
Array<Array<unsigned>> relatives; //The relatives of each member
|
||||||
|
Array<Array<Relation>> relations; //The type of relation each member has with his relatives
|
||||||
|
public:
|
||||||
|
Tree();
|
||||||
|
Tree(const char *Name);
|
||||||
|
Tree(const Tree&);
|
||||||
|
Tree& operator= (const Tree& other);
|
||||||
|
~Tree();
|
||||||
|
|
||||||
|
Tree operator+ (const Tree& other);
|
||||||
|
Tree operator- (const Tree& other);
|
||||||
|
Tree& operator+= (const Tree& other);
|
||||||
|
Tree& operator-= (const Tree& other);
|
||||||
|
|
||||||
|
void rename(const char* newName);
|
||||||
|
unsigned findId(const char*, const short year=0, const unsigned char month=0, const unsigned char day=0)const;
|
||||||
|
unsigned findOldestAncestor(const unsigned &id, const bool &sex = 0)const;//
|
||||||
|
unsigned findCommonAncestor(const unsigned firstId, const unsigned secondId)const; //oldest common ancestor ID
|
||||||
|
void saveTree()const;//
|
||||||
|
bool loadTree();
|
||||||
|
void addPerson(const char *, short year, unsigned char month, unsigned char day, bool sex, unsigned father = Nobody, unsigned mother = Nobody);
|
||||||
|
bool addRelation(const char* firstName, const Relation, const char* secondName); //Adds a new relation or edits an old one. 0 - failure 1 - success
|
||||||
|
bool addRelation(const unsigned firstId, const Relation, const unsigned secondId, bool opposite=0); //0 - failure 1 - success
|
||||||
|
void removePerson(const unsigned id); //Removes a member and the last one takes his ID
|
||||||
|
void removePerson(const char*, const short year = 0, const unsigned char month = 0, const unsigned char day = 0);
|
||||||
|
void removeRelation(const unsigned firstId, const unsigned secondId);
|
||||||
|
void removeRelation(const char* firstName, const char* secondName);
|
||||||
|
|
||||||
|
void printRel(const unsigned id)const; //Prints out close relatives
|
||||||
|
void printMember(const unsigned id)const;
|
||||||
|
void printOldestAncestors(const unsigned id)const;//
|
||||||
|
|
||||||
|
unsigned gNumP()const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void commonAncestorRec(const unsigned &id, const Array<char> &visited)const;
|
||||||
|
|
||||||
|
//Search, ect.
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user