Hmjaaa.... naja. Ein bißchen was allgemeines:
Euer Lehrer hat euch vermutlich was von "Objektorientierung" erzählt - das ist in diesem Programm aber nicht so umgesetzt, wie es gedacht ist. Es werden ja einzelne Objekte für die Personen angelegt. Auf diesen Objekten kann man Methoden aufrufen. Z.B. die Methode "ausgeben".
Stell dir vor, du hättest zwei Kunden-Objekte anlegt:
Kunde kunde1();
Kunde kunde2();
Wenn man bei EINEM Objekt die Methode "ausgeben" aufruft, werden ALLE Personen ausgegeben. Das macht ja eigentlich keinen Sinn. Gewünscht wäre eigentlich, daß die Methode
kunde1.ausgeben();
wirklich NUR die Daten von kunde1 ausgibt:
void CKunde::ausgeben()
{
cout << " " << Vorname << " " << Nachname << " # " << endl;
}
Wenn man ALLE Kunden-Daten ausgeben wollte, würde man sich dafür eine eigene Klasse oder zumindest eine eigene Methode anlegen. Die Methoden und Eigenschaften (also z.B. auch "Dateiname") sollten sich IMMER nur auf das Objekt beziehen, auf dem sie aufgerufen werden. Andernfalls macht die ganze Objektorientierung ja keinen Sinn...
Wenn man dieses Konzept konsequent berücksichtigt, hat das aber noch Vorteile, die WEIT darüber hinausgehen, daß es "irgendwie logischer klingt". Man könnte z.B. die ausgeben()-Methode für Kunden definieren:
void CKunde::ausgeben(ostream &output) {
output << " " << Vorname << " " << Nachname << " # " << endl;
}
Nun kann man den Kunden da hin ausgeben, wo man will:
ofstream datei("datei.txt", ios::app);
kunde.ausgeben(datei); // Schreibt den Kunden in die Datei
kunde.ausgeben(cout); // Schreibt den Kunden auf den Bildschirm
Abgesehen davon kann man dann auch Polymorphie einsetzen (mal in Google oder Wikipedia nachlesen!). Das bedeutet, vereinfacht gesagt, daß man für alle CPerson-Objekte (egal ob Personal oder Kunde) die gleichen Methoden verwenden kann. Man brächte also z.B. nicht VIER Methoden
schreibeKundenInDatei
schreibePersonalInDatei
schreibeKundenAufBildschirm
schreibePersonalAufBildschirm
sondern nurnoch diese EINE Methode:
void alleAusgeben(vector<CPerson*> personen, ostream &output) {
for (int i=0; i
personen[i]->ausgeben(output);
}
}
Diese Methode könnte entweder Personal oder Kunden in eine Datei oder auf den Bildschirm schreiben. Es wird automatisch die richtige ausgeben()-Funktion aufgerufen, je nachdem, ob es Personal oder Kunden sind. Mit Operatorenüberladung wäre die Anwendung dann sogar noch einfacher...
However.
Genug gemotzt ;-)
Ich habe festgestellt, daß man die lies-Funktion garnicht unbedingt braucht, weil char[]s in diesem Fall genauso behandelt werden, wie 'string's. Hier mal dein Code mit einer Funktion "verwaltung", die im Moment nicht viel macht, aber als Basis für die notwendigen Erweiterungen dienen könnte. Kommentare und Änderungen sind mit XXX markiert.
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <vector>
using namespace std;
// ********** Basisklasse CPerson *************************
class CPerson
{
protected:
char Vorname[30];
char Nachname[30];
char Dateiname[30];
public:
void eingeben();
void ausgeben();
void suchen();
};
// ********** Abgeleitete Klasse CPersonal ****************
class CPersonal : public CPerson
{
private:
int PersNr;
public:
void eingeben();
void speichern();
CPersonal(char*, char*, int); // XXX Hier haben die Sternchen * gefehlt
CPersonal(); // XXX Den alten Konstruktor gibt's immernoch
//void lies(ifstream&, char*);// XXX Das nicht hierhin
void gibMichAus(); // XXX siehe Kommentare im Post
};
// ********** Methoden der Basisklasse CPerson ************
void CPerson::eingeben()
{
cout<<"Vorname = ";
cin>>Vorname;
cout<<"Nachname = ";
cin>>Nachname;
}
void CPerson::ausgeben()
{
char zeichen;
ifstream datei;
//system("clear");
datei.open(Dateiname);
if(!datei)
cout<<"Fehler";
else
{
cout<<"Personaldatei\n";
while(!datei.eof())
{
zeichen=datei.get();
if(zeichen=='#')
cout<<endl;
else
cout.put(zeichen);
}
datei.close();
}
//getch();
}
void CPerson::suchen()
{
char suchname[30],zeichenkette[30];
int i=0;
bool vorhanden=false;
ifstream datei;
cout<<"Suchname = ";
cin>>suchname;
datei.open(Dateiname);
while(!datei.eof())
{
zeichenkette[i]=datei.get();
if (zeichenkette[i]!=' ')
i++;
else
{
zeichenkette[i]='\0';
if(strcmp(zeichenkette,suchname)==0)
vorhanden=true;
i=0;
}
}
datei.close();
if(vorhanden==true)
cout<<endl<<suchname<<" ist in der Datei vorhanden"<<endl;
else
cout<<endl<<suchname<<" ist in der nicht Datei vorhanden"<<endl;
//getch();
}
// ********** Methoden der abgeleiteten Klasse CPersonal **
// XXX Das ist der alte Konstruktor
CPersonal::CPersonal()
{
strcpy(Dateiname,"personal.txt");
}
// XXX Das ist der neue Konstruktor:
// XXX Es müssen die Argumente "vor", "nach" und "nummer" übergeben werden
CPersonal::CPersonal(char *vor, char *nach, int nummer)
{
strcpy(Dateiname,"personal.txt");
strcpy(Vorname, vor);
strcpy(Nachname, nach);
PersNr = nummer;
}
void CPersonal::eingeben()
{
cout<<"Personaldaten \n";
CPerson::eingeben();
cout<<"Personalnummer = ";
cin>>PersNr;
CPersonal::speichern();
}
void CPersonal::speichern()
{
ofstream datei;
datei.open(Dateiname,ios::app);
if(!datei)
cout<<"\nDatei kann nicht geoeffnet werden";
else
datei<< PersNr <<" "<<Vorname<<" "<<Nachname<<" # " << endl;
datei.close();
}
// XXX Siehe Kommentare im Post
void CPersonal::gibMichAus()
{
cout << PersNr <<" "<<Vorname<<" "<<Nachname<<" # " << endl;
}
// XXX Die liesPersonal-Funktion gehört zu keiner Klasse
void liesPersonal(vector<CPersonal*> &personal) {
char vorname[30],nachname[30],nummerString[30];
ifstream datei("personal.txt");
while(!datei.eof())
{
// eine Zeile lesen
datei >> nummerString;
datei >> vorname;
datei >> nachname;
datei.ignore(INT_MAX, '\n'); // Zeilenende-Zeichen ignorieren
if (datei.eof()) break;
int nummer = atoi(nummerString);
// Personal erstellen und in vector legen:
CPersonal *pers = new CPersonal(vorname, nachname, nummer);
personal.push_back(pers);
}
datei.close();
}
// XXX Eine neue Funktion, für die neuen Funktionen
void verwaltung()
{
// XXX Einen Vector erstellen
vector<CPersonal*> personal;
// XXX Personal lesen
liesPersonal(personal);
// XXX Personal ausgeben:
cout << "Personal: " << endl;
for (int i=0; i<personal.size(); i++) {
personal[i]->gibMichAus();
}
// XXX Zwei Personen vertauschen, und neu ausgeben
if (personal.size()>=2) {
CPersonal *tmp = personal[0];
personal[0] = personal[1];
personal[1] = tmp;
cout << "Personal, 0 und 1 vertauscht: " << endl;
for (int i=0; i<personal.size(); i++) {
personal[i]->gibMichAus();
}
}
}
// ********** Menue mit Hauptprogramm *********************
// XXX Ein paar kleine Hilfs-Funktionen - machen die
// XXX menue-Funktion übersichtlicher :-)
void personaldaten() {
char auswahl;
cout<<"\n\n*********Personaldaten********\n";
cout<<"Neueingabe von Daten ........n";
cout<<"\nAusgabe aller Daten .........a";
cout<<"\nSuchen einzelner Daten ......f";
cout<<"\nEnde ........................q";
cout<<"\nIhre Wahl = ";
cin>>auswahl;
CPersonal meinPersonal;
switch(auswahl)
{
case 'n':
case 'N': meinPersonal.eingeben(); break;
case 'a':
case 'A': meinPersonal.ausgeben(); break;
case 'f':
case 'F': meinPersonal.suchen(); break;
case 'q':
case 'Q': exit(-1); break;
}
}
void kundendaten()
{
char auswahl;
cout<<"\n\n*********Kundendaten**********\n";
cout<<"Neueingabe von Daten ........n";
cout<<"\nAusgabe aller Daten .........a";
cout<<"\nSuchen einzelner Daten ......f";
cout<<"\nEnde ........................q";
cout<<"\nIhre Wahl = ";
cin>>auswahl;
/*
CKunde meinKunde;
switch(auswahl)
{
case 'n':
case 'N': meinKunde.eingeben(); break;
case 'a':
case 'A': meinKunde.ausgeben(); break;
case 'f':
case 'F': meinKunde.suchen(); break;
case 'q':
case 'Q' :exit(-1); break;
}
*/
}
void menue()
{
char auswahl;
// XXX Eine Schleife um's menü...
do {
//system("clear");
cout<<"\n\n********Dateiverwaltung*******\n";
cout<<"Kundendaten .................k";
cout<<"\nPersonaldaten ...............p";
cout<<"\nVerwalung....................v";
cout<<"\nEnde ........................q";
cout<<"\nIhre Wahl = ";
cin>>auswahl;
if(auswahl=='p'||auswahl=='P') personaldaten();
if(auswahl=='k'||auswahl=='K') kundendaten();
if(auswahl=='v'||auswahl=='V') verwaltung();
}while(auswahl != 'q' && auswahl!='Q');
// XXX ... besser als hier nochmal "menue" aufzurufen!
//menue();
}
int main()
{
menue();
return 0;
}
bye
P.S: Die [Tags mit den eckigen Klammern] funktionieren hier nicht. Wenn man code postet, sollte man den in
<pre>
// Code
</pre>
Tags einschließen.
geschrieben von Marco13 , 18.11.2005, 17:36 Uhr , 65 mal gelesen