I'm basically working on a program that allows you to make simple genograms, using C++ in a Linux environment. Here's the entire code I've made for now: genogram.h
#include <cstddef>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
namespace genogram
{
typedef string Name;
typedef char Relationship;
struct personNode; // to be defined in genogram.cpp
typedef personNode* Genogram; // a genogram is identified by the pointer to the first person entered
const Genogram emptyGenogram = nullptr;
Genogram createEmptyGenogram();
bool addPerson(Name, char, string, string, Genogram&);
Genogram getMother(Name, const Genogram&);
bool hasMother(Name, const Genogram&);
Genogram getFather(Name, const Genogram&);
bool hasFather(Name, const Genogram&);
Genogram getPartner(Name, const Genogram&);
bool hasPartner(Name, const Genogram&);
bool arePartners(Name, Name, const Genogram&);
bool hasSons(Name, const Genogram&);
bool isSon(Name, Name, const Genogram&);
bool areBrothers(Name, Name, const Genogram&);
bool areRelated(Name, Name, const Genogram&);
bool addRelMother(Name, Name, Genogram&);
bool addRelFather(Name, Name, Genogram&);
bool addRelCouple(Name, Name, Genogram&);
bool addRelChildToCouple(Name, Name, Name, Genogram&);
void printGenogram(Genogram);
bool deletePerson(Name, Genogram&);
}
genogram.cpp
#include "genogram.h"
using namespace genogram;
void debugg(int n)
{
cout << n << endl;
}
struct son
{
personNode* person;
son* nextSon;
};
son* emptySon = nullptr;
struct genogram::personNode
{
Name name;
char sex;
string birthDate;
string deathDate;
personNode* mother;
personNode* father;
personNode* partner;
son* linkSons;
personNode* nextPerson;
bool visited;
};
//**************************************************//
//Returns an empty Genogram
Genogram genogram::createEmptyGenogram()
{
return emptyGenogram;
}
//**************************************************//
Genogram createPerson(Name n, char sex, string bDate, string dDate)
{
personNode* p = new personNode;
p->name = n;
if(sex=='M'||sex=='F')
p->sex = sex;
else
return emptyGenogram;
p->birthDate = bDate;
p->deathDate = dDate;
p->mother = emptyGenogram;
p->father = emptyGenogram;
p->partner = emptyGenogram;
p->linkSons = emptySon;
p->visited = false;
return p;
}
son* createSon(personNode* p)
{
son* s = new son;
s->person = p;
s->nextSon = emptySon;
return s;
}
personNode* getPerson(Name n, Genogram g)
{
Genogram aux = g;
while (aux!=emptyGenogram)
{
if(aux->name==n)
return aux;
aux=aux->nextPerson;
}
return emptyGenogram;
}
bool member(Name n, Genogram g)
{
return (getPerson(n,g)!=emptyGenogram);
}
bool genogram::addPerson(Name n, char sex, string bDate, string dDate, Genogram& g)
{
if(member(n,g))
return false;
Genogram aux = createPerson(n,sex,bDate,dDate);
if(aux==emptyGenogram)
return false;
aux->nextPerson = g;
g = aux;
return true;
}
//**************************************************//
Genogram genogram::getMother(Name n, const Genogram& g)
{
if(member(n,g))
return getPerson(n,g)->mother;
return emptyGenogram;
}
bool genogram::hasMother(Name n, const Genogram& g)
{
return getMother(n,g)!=emptyGenogram;
}
Genogram genogram::getFather(Name n, const Genogram& g)
{
if(member(n,g))
return getPerson(n,g)->father;
return emptyGenogram;
}
bool genogram::hasFather(Name n, const Genogram& g)
{
return getFather(n,g)!=emptyGenogram;
}
Genogram genogram::getPartner(Name n, const Genogram& g)
{
if(member(n,g))
return getPerson(n,g)->partner;
return emptyGenogram;
}
bool genogram::hasPartner(Name n, const Genogram& g)
{
return getPartner(n,g)!=emptyGenogram;
}
bool genogram::arePartners(Name n1, Name n2, const Genogram& g)
{
if(hasPartner(n1,g))
return (getPartner(n1,g)->name==n2);
else
return false;
}
son* getSonList(Name n, const Genogram& g)
{
if(member(n,g))
return getPerson(n,g)->linkSons;
return emptySon;
}
bool genogram::hasSons(Name n, const Genogram& g)
{
return getSonList(n,g)!=emptySon;
}
bool genogram::isSon(Name s, Name p, const Genogram& g)
{
if(hasSons(p,g))
{
son* sonAux = getSonList(p,g);
while(sonAux!=emptySon)
{
if(sonAux->person->name==s)
return true;
sonAux = sonAux->nextSon;
}
}
return false;
}
bool genogram::areBrothers(Name n1, Name n2, const Genogram& g)
{
son* sonAux = emptySon;
if(hasMother(n1,g))
{
sonAux = getSonList(getMother(n1,g)->name,g);
while(sonAux!=emptySon)
{
if(sonAux->person->name==n2)
return true;
sonAux = sonAux->nextSon;
}
}
if(hasMother(n1,g))
{
sonAux = getSonList(getFather(n1,g)->name,g);
while(sonAux!=emptySon)
{
if(sonAux->person->name==n2)
return true;
sonAux = sonAux->nextSon;
}
}
return false;
}
bool genogram::areRelated(Name n1, Name n2, const Genogram& g)
{
if(hasMother(n1,g))
{
Genogram aux = getMother(n1,g);
//when here, segment. fault
if(aux->name==n2)
return true;
}
if(hasMother(n2,g))
if(getMother(n2,g)->name==n1)
return true;
if(hasFather(n1,g))
if(getFather(n1,g)->name==n2)
return true;
if(hasFather(n2,g))
if(getFather(n2,g)->name==n1)
return true;
if(arePartners(n1,n2,g))
return true;
if(isSon(n1,n2,g))
return true;
if(isSon(n2,n1,g))
return true;
if(areBrothers(n1,n2,g))
return true;
return false;
}
//**************************************************//
bool genogram::addRelMother(Name s, Name m, Genogram& g)
{
if(hasMother(s,g)||!member(s,g)||!member(m,g)||s==m)
return false;
personNode* aux = getPerson(s,g);
aux->mother = getPerson(m,g);
personNode* aux2 = getPerson(m,g);
son* sonAux = createSon(getPerson(s,g));
sonAux->nextSon = aux2->linkSons;
aux2->linkSons = sonAux;
return true;
}
bool genogram::addRelFather(Name s, Name f, Genogram& g)
{
if(hasFather(s,g)||!member(s,g)||!member(f,g)||s==f)
return false;
personNode* aux = getPerson(s,g);
aux->father = getPerson(f,g);
personNode* aux2 = getPerson(f,g);
son* sonAux = createSon(getPerson(s,g));
sonAux->nextSon = aux2->linkSons;
aux2->linkSons = sonAux;
return true;
}
bool genogram::addRelCouple(Name n1, Name n2, Genogram& g)
{
if(arePartners(n1,n2,g))
return true;
if(areRelated(n1,n2,g)||hasPartner(n1,g)||hasPartner(n2,g)||!member(n1,g)||!member(n2,g)||n1==n2)
return false;
personNode* aux = getPerson(n1,g);
aux->partner = getPerson(n2,g);
personNode* aux2 = getPerson(n2,g);
aux2->partner = getPerson(n1,g);
return true;
}
bool genogram::addRelChildToCouple(Name s, Name m, Name f, Genogram& g)
{
if(!arePartners(m,f,g))
return false;
return (addRelMother(s,m,g) && addRelFather(s,f,g));
}
//**************************************************//
void genogram::printGenogram(Genogram g)
{
Genogram aux = g;
son* sonAux = emptySon;
while (aux!=emptyGenogram)
{
cout << "-----------------\n";
cout << "Name: " << aux->name << "; sex: " << aux->sex << "; born: " << aux->birthDate << "; dead: " << aux->deathDate;
cout << ";\n - mother: ";
if(aux->mother!=emptyGenogram)
cout << aux->mother->name << ";";
cout << "\n - father: ";
if(aux->father!=emptyGenogram)
cout << aux->father->name << ";";
cout << "\n - partner: ";
if(aux->partner!=emptyGenogram)
cout << aux->partner->name << ";";
cout << "\n - sons: ";
sonAux = aux->linkSons;
if(aux->linkSons!=emptySon)
{
while(sonAux!=emptySon)
{
cout << sonAux->person->name << "; ";
sonAux = sonAux->nextSon;
}
cout << "\b\b.";
}
aux = aux->nextPerson;
cout << "\n";
}
cout << "-----------------\n";
}
//**************************************************//
bool genogram::deletePerson(Name n, Genogram& g)
{
return true;
}
And then here's the main.cpp where I did some tests:
#include <cstdlib>
#include <iostream>
////////////////////////////////////////////////////////////////////////
// Test main
////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
#include "genogram.h"
using namespace std;
int main()
{
genogram::Genogram g = genogram::createEmptyGenogram();
genogram::addPerson("Mark",'M',"25/09/2001","29/07/2020",g);
genogram::addPerson("Elizabeth",'F',"31/02/2003","-",g);
genogram::addPerson("Karl",'M',"04/03/2020","-",g);
genogram::addRelCouple("Elizabeth","Mark",g);
genogram::addRelMother("Karl","Elizabeth",g);
if(genogram::areRelated("Elizabeth","Karl",g)) // true)//
cout << "Test1: success" << endl;
else
cout << "Test1: no success" << endl;
if(genogram::areRelated("Karl","Mark",g))
cout << "Test2: success" << endl;
else
cout << "Test2: no success" << endl;
}
Basically, the problem I'm having is that, after I use addRelMother("sonName","motherName",g)
to create the relationship between the son and the mother, when I try to see if "sonName"
is related in any way to "anotherName"
using the function areRelated("sonName","anotherName",g)
, a segmentation fault (core dumped) error occurs. More specifically, when this function is executed, it first checks if "sonName"
already has a mother assigned to him using the function hasMother("sonName",g)
(which basically simply checks if the function getMother("sonName",g)
returns emptyGenogram
, which is an alias for nullptr, or not). After it has returned true in the if statement, it tries to point to the mother's name, but even though getMother("sonName",g)
doesn't return an emptyGenogram
, if I point to the name field a segmentation fault (core dumped) error happens.
bool genogram::areRelated(Name n1, Name n2, const Genogram& g)
{
if(hasMother(n1,g))
{
Genogram aux = getMother(n1,g);
//when here, segment. fault
if(aux->name==n2)
return true;
}
Can somebody help me find the reason of why this happens?