rename files, sex-

This commit is contained in:
vrd
2022-08-20 15:43:58 +03:00
commit fbfe017284
12 changed files with 1325 additions and 0 deletions
+152
View File
@@ -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;
}
+16
View File
@@ -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
View File
@@ -0,0 +1 @@
g++ -Ofast -flto -fipa-pta -s *.cpp\
+1
View File
@@ -0,0 +1 @@
g++ *.cpp
+69
View File
@@ -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;
}
+9
View File
@@ -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);
+238
View File
@@ -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
View File
@@ -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");
}
+30
View File
@@ -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;
};
+72
View File
@@ -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)
+574
View File
@@ -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);
}
}
}
+71
View File
@@ -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.
};