PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++]Segmentation Fault



eXi
28.01.2015, 14:27:20
NEVERMIND

Das passiert, wenn man das Main Programm vom Prof kriegt und nicht genau
guckt was es tut. Der Patient p wird nur in dem Case erstellt und danach ist er
nicht mehr vorhanden. Da ich nur einen Pointer auf diesen Patient P eintrage
uebergebe, zeigt das Array danach auf nichts -> segmentation fault.

Naja immerhin bin ich schlau genug das dann zu raffen :ugly:

-----------------------------------------------------------------------------------------------------

Hey,

ich bräuchte mal Hilfe. Bin gerade dabei paar Übungsaufgaben für meine C++ Klausur
zu machen. Die aktuelle Aufgabe ist, eine Arztpraxis Verwaltungssoftware zu basteln.

Nicht kompliziertes, aber beim Ausgeben der Partientenliste kriege ich immer einen
segmentation fault. Ich verstehe allerdings nicht warum, da ich das gleiche Konzept
schon bei einer anderen Aufgabe benutzt habe.

In der Patienten Klasse hab ich den Ausgabe Operator überladen. Das funktioniert auch.
In der Patientenlisten Klasse hab ich ihn dann auch überladen und bin das Pointer Array
vom Typ "Patient" durchgegangen. Wenn ich einen Eintrag finde der nicht "nullptr" ist,
dann füge ich dem ostream *(PTL.Patienten[i]) hinzu. PTL ist eine const Patientenliste
Referenz.

Eigentlich sollte dies den << Operator der Patienten Klasse aufrufen und dazu bringen,
den Patienten auszugeben. Allerdings kriege ich auf meinem Windows Rechner nach
"Nachname:" nur noch irgendwelche Zeichen und Ordnernamen und auf Linux krieg ich
einen Segmentation fault -_-.

Hier mal die Klassen:



#ifndef PatientHeader
#define PatientHeader

#include <iostream>
#include <string>

using namespace std;

class Patient
{
private:

string Vorname;
string Nachname;
string KK_Kennung;

public:

Patient(string, string, string); // Allgemeiner Konstruktor
Patient(); // Standard Konstruktor

// Getter Funktionen
string getVorname() const;
string getNachname() const;
string getKK_Kennung() const;

// Ausgabe von Patienten

friend ostream& operator<<(ostream& os, const Patient&);


};

#endif // PatientHeader




#include "Patient.hpp"
#include <iomanip>

// Default Konstruktor ruft allgemeinen auf
Patient::Patient() : Patient("Mustermann", "Max", "1234567890")
{
return;
}

// Allgemeiner Konstruktor
Patient::Patient(string nachname, string vorname, string id) : Nachname(nachname), Vorname(vorname), KK_Kennung(id)
{
return;
}

/*
Getter Methoden fuer Variblen
*/

string Patient::getVorname() const
{
return Vorname;
}

string Patient::getNachname() const
{
return Nachname;
}

string Patient::getKK_Kennung() const
{
return KK_Kennung;
}

// Output fuer Patient

ostream& operator<<(ostream& os, const Patient& PT)
{
os << "Vorname: " << PT.Vorname << " Nachname: " << PT.Nachname << " KK_Kennung: " << PT.KK_Kennung;
return os;
}




#ifndef PListeHeader
#define PListeHeader

#include "Patient.hpp"

const int n = 50;

class Patientenliste
{
private:

Patient* Patienten[50];

public:

// Default Konstruktor
Patientenliste();

// Hinzufuegen von Patienten zur Liste
Patientenliste& operator+=(Patient&);

// Einen Patienten Suchen. Gibt Patient zurück (Vielleicht Pointer oder Ref?)
Patient* suchen(string);

friend ostream& operator<<(ostream& os, const Patientenliste&);

};

#endif // PListeHeader





#include "Patientenliste.hpp"

Patientenliste::Patientenliste()
{
for(int i = 0; i < n; i++)
{
Patienten[i] = nullptr;
}
return;
}

Patientenliste& Patientenliste::operator+=(Patient& PT)
{
int i = 0;

while(Patienten[i] != nullptr)
{
if(Patienten[i]->getKK_Kennung() == PT.getKK_Kennung())
{
cout << "Patient schon vorhanden!" << endl;
return *this;
}
i++;
}
if(i >= n)
{
cout << "Kein Platz mehr im System fuer neuen Patient!" << endl;
}
else
{
Patienten[i] = &PT;
}
return *this;
}

Patient* Patientenliste::suchen(string id)
{
int i = 0;
while(Patienten[i] != nullptr)
{
if(Patienten[i]->getKK_Kennung() == id)
{
return Patienten[i];
}
i++;
}

return nullptr;
}

ostream& operator<<(ostream& os, const Patientenliste& PTL)
{
cout << "DEBUG: Vor For" << endl;
for(int i = n - 1; i >= 0 ; i--)
{
cout << "DEBUG: In for i = " << i << endl;
if(PTL.Patienten[i] != nullptr)
{
cout << "DEBUG: In for in if i = " << i << endl;
os << " > " << *(PTL.Patienten[i]) << endl; // Hier gehts dann immer kaputt >.<
}
}
return os;
}



Krieg da echt keinen Kopf dann, da das gleiche vorher in einem anderen Projekt
tadellos funktioniert hat.

PS: Hier mal zum Vergleich. Eingabe + direkte Ausgabe von Patient durch seinen << Operator:


<<< Neuen Patienten anlegen >>>
Nachname: Neukirchen
Vorname: Cedric
KrankenkassenID: 1234
Vorname: Cedric Nachname: Neukirchen KK_Kennung: 1234


Ausgabe der Liste auf Linux System durch den << Operator der Liste:


<<< Patientenliste >>>
> Vorname: Cedric1▒k▒▒▒▒1234rchA▒▒▒▒Neukirchen1▒▒▒▒121

PS2: Wenn ich die Liste direkt bei der Eingabe wieder ausgebe, dann funktioniert der Listen << Operator.
Was zur Hölle passiert in der Zwischenzeit?!

Hier ist die Ein und Ausgabe in der Main durch einen switch bei Eingabe von N bzw D.



case 'n': {
string nachname, vorname, id;
cout << "<<< Neuen Patienten anlegen >>>" << endl;
cout << "Nachname: ";
cin >> nachname;
cout << "Vorname: ";
cin >> vorname;
cout << "KrankenkassenID: ";
cin >> id;
Patient p(nachname, vorname, id);
cout << p << endl;
pListe += p;
cout << pListe << endl;
break;
}
case 'D':
case 'd': {
cout << "<<< Patientenliste >>>" << endl;
cout << pListe << endl;
break;
}

Das cout vom p und pListe im ersten Case funktioniert. Drücke ich danach "d" passiert der Quatsch da oben.

eMo
28.01.2015, 16:21:28
Buh, da fällt mir was auf, ist es möglich, dem Code-Tag direkt einen Sprachen-Code mitzugeben, der Farbgebung aktiviert. Finde es unglaublich nervig, "farblosen" Code zu lesen, insbesondere in einer Sprache, die man nicht wirklich gut kann. :/
Ansonsten hast du ja die Lösung :)
Java ist trotzdem schöner :P

Meine Fragen:
Warum nutzt du nicht wirklich eine Liste als Datentyp für Patienten? Oder muss das ein Array sein?
Gelöst hast du das ganze jetzt, indem du Pointer und Objekt selbst abgespeichert hast? - Pointer und Objektunterschied ist übrigens ein Grund, warum ich mich mit c nie anfreunden konnte, ich finde das erschwert den Einstieg ungemein, löst aber Referenzierungsprobleme, die man bei der Zuweisung von Objekten in Java bekommen kann (Stichwort clone()) :ugly:

eXi
28.01.2015, 16:54:58
Buh, da fällt mir was auf, ist es möglich, dem Code-Tag direkt einen Sprachen-Code mitzugeben, der Farbgebung aktiviert.


:( Keine Ahnung. Wäre aber cool.




Meine Fragen:
Warum nutzt du nicht wirklich eine Liste als Datentyp für Patienten? Oder muss das ein Array sein?


Naja die Übungsblätter sind an den jeweiligen Stoff der VL angepasst. Da hier noch keine Listen dran waren,
will ich das ohne machen.



Gelöst hast du das ganze jetzt, indem du Pointer und Objekt selbst abgespeichert hast?


Das Problem war, dass bei dem anderen Programm, was ich vorher gemacht habe, die Objekt nur einmal erzeugt
und dann direkt verwendet wurden. Es wurde zB der Patient erzeugt, ein Pointer hat auf diesen Patienten gezeigt
und dann konnte man in ein und dem selben Block weiter mit ihm arbeiten. Es gab in dem Programm keine
weiteren Blöcke.

Hier allerdings, ist der Patient, welche mit Patient P in dem Case für N erzeugt wird, nur innerhalb dieses Cases
vorhanden. Zeige ich also nur mit einem Pointer darauf, zeigt der Pointer nach dem Case auf Nichts mehr, da das
Objekt danach wieder zerstört wird. Also hab ich für die Liste kein Pointer Array erstellt, sondern ein Array vom Typ Patient.
Dann hab ich auch nicht die Adresse übergeben, sondern den ganzen Patienten und den einfach an eine Freie stelle im Array
gepackt.

Dadurch ist das Array richtig gefüllt und zeigt nicht nur auf den Patienten. Wird der Patient P dann nach dem Case Block wieder
deconstructed, ist das Array diesmal aber noch mit Werten gefüllt.

Hatte einfach nicht gesehen, dass mein Prof den Patienten im Case Block erstellt hat. Dachte er hat den im Main Block erstellt.




- Pointer und Objektunterschied ist übrigens ein Grund, warum ich mich mit c nie anfreunden konnte, ich finde das erschwert den Einstieg ungemein, löst aber Referenzierungsprobleme, die man bei der Zuweisung von Objekten in Java bekommen kann (Stichwort clone()) :ugly:



Naja, ich hab die Pointer Geschichte mit c halt direkt gelernt. Deshalb ist C++ eigentlich nichts neues und auch nicht schwer.





Patientenliste& Patientenliste::operator+=(Patient& PT)
{
int i = 0;

while(Patienten[i].getKK_Kennung() != "")
{
if(Patienten[i].getKK_Kennung() == PT.getKK_Kennung())
{
cout << "Patient schon vorhanden!" << endl;
return *this;
}
i++;
}
if(i >= n)
{
cout << "Kein Platz mehr im System fuer neuen Patient!" << endl;
}
else
{
Patienten[i] = PT;
}
return *this;
}

eMo
28.01.2015, 17:40:30
Also so gelöst, wie ich dachte, super, ty :)

Naja, ich habe halt erst Java gelernt und dann C und da fiel mir das mit den Pointern halt negativ auf, andersrum wäre es vermutlich nicht ins Gewicht gefallen :D

eXi
28.01.2015, 18:04:34
Also so gelöst, wie ich dachte, super, ty :)

Naja, ich habe halt erst Java gelernt und dann C und da fiel mir das mit den Pointern halt negativ auf, andersrum wäre es vermutlich nicht ins Gewicht gefallen :D

Ich finde die Pointer auch schlimm für den Anfang. Muss das ja den Erstis in Info 1 beibringen und das zu erklären ist gar nicht so einfach.
Hab das Praxis Programm mit Terminplan und so nem Quatsch jetzt fertig. :ugly: Auf zum nächsten Übungsblatt.