Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Hilfe mit einer Aufgabe: Vererbung, string, pointer

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
12.01.2014, 17:24 Uhr
~Ranny
Gast


Hallo
Ich sitze nun schon seit zwei Tagen an einem Programm, das mir immer mehr Schwierigkeiten bereitet... vielleicht aber bevor ich mit meinem Problem beginne, hier erst einmal die Aufgabenstellung:

Code:
Leiten Sie mittels Vererbung von der angegebene Klasse Person die Klasse Student ab. Erweitern Sie die Klasse Student so, dass sie zusätzlich die Matrikelnummer und das Studienfach aufnehmen kann.
class Person {
private:
char * vorname;
char * nachname;
public:
Person ( char * vn, char * nn)
{
vorname = vn;
nachname = nn;
}
virtual void info ()
{
cout << "Vorname: " << vorname << ", Nachname: " << nachname << endl;
}
};
Schreiben Sie ein Programm, dass mittels cin die Datensätze von zwei Studenten einliest und anschließend mit der Methode info ausgibt.


Nun das von mir geschriebene Programm:

C++:
# include <iostream>
# include <string.h>
# include <stdio.h>

using namespace std;

class Person {
    protected:
        char * vorname;
        char * nachname;
    public:    
        Person (char * vn, char * nn)
        {
            vorname = vn;
            nachname = nn;
        }

    virtual void info ()
    {
        cout << "Vorname: " << vorname << ", Nachname: " << nachname /* << ", Matrikelnummer: " << matikelnummer << ", Studienfach: " << studienfach*/ << endl;
    }    
};

class Student : public Person
{
    private:
        long matrikelnummer;
        char * studienfach;
    public:    
        Student (char * vn, char * nn, long mn, char * sf) : Person (vn, nn)
        {
            matrikelnummer = mn;
            studienfach = sf;
        }
        
        void eingabe () {
            cout << "Erster Student:";
            cin >> vorname >> nachname >> matrikelnummer >> studienfach;
        }
            
};

int
main ()
{
    char * vn = "abc";
    char * nn = "def";
    char * sf = "ghi";

    Student a(vn, nn, 123, sf);
    a.eingabe();
    a.info();
}


Nun folgt immer wieder folgende Warnung: [Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings] in den Zeilen 46, 47 und 48 und ich habe nicht die Geringste Ahnung, wie ich diese wegbekomme. An sicht startet auch das Programm (zumindest mit DevC++, bei Linux nicht...) aber sobald ich dann eine Eingabe macht, stürzt es einfach ab.
Ich hoffe, ihr könnt mir helfen, denn so langsam bin ich wirklich am Verzweifeln.

Liebe Grüße und vielen Dank im Vorraus
Ranny
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
12.01.2014, 23:32 Uhr
~f.-th.
Gast


sollt ihr das zu Übungszwecken echt noch in dem Stil verfassen?
Solche Aufgaben werden heut meist mittels Container gelöst.

Wenn ihr das so lösen sollt, hast du die Speicherverwaltung vergessen?
Stichwort: new u.s.w.

MfG f.-th.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
13.01.2014, 01:09 Uhr
~Ranny
Gast


Also, vielleicht sollte ich noch erwähnen, dass ich keine Informatik-Studentin bin. Ich studiere Mathematik und wir lernen lediglich die Grundlagen von C und C++, wobei C++ wir erst seit zwei Wochen machen.
Folglich habe ich weder etwas von einem Container, noch von den Stichwort new etwas gehört oder gelesen... Könntest du mir das vielleicht etwas genauer erklären oder evtl. auch zeigen? Wäre sehr freundlich

LG
Ranny
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
13.01.2014, 09:41 Uhr
~f.-th.
Gast


Okay Container ist dann noch ein wenig früh.

Die Seite C++ Reference zeigt schon mal brauchbare Infos, wenn ihr sonst wenig passendes habt: www.cplusplus.com/reference/new/operator%20new/

Noch eine Seite:
http://stackoverflow.com/
da den C++ Bereich suchen und viel lesen.
Meist gute Diskussionen und Bewertung der Antworten.

MfG f.-th.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
13.01.2014, 09:42 Uhr
ao

(Operator)


Moin.

Ich traue meinen Augen nicht. Diese Aufgabenstellung ist ein perfektes Anti-Beispiel, wie man es nicht machen soll. Dieser Konstruktor:

C++:
Person ( char * vn, char * nn)
{
vorname = vn;
nachname = nn;
}


verlangt die Hereingabe von Speicher für die eigenen Membervariablen, d.h. das, was eigentlich den Kern der OO-Programmierung ausmacht (jedes Objekt kümmert sich selbst um die eigenen Daten), wird nach außen verlagert und dem Anwender überlassen. Völlig falscher Ansatz. Der, der sich das ausgedacht hat, hat grundlegende OO-Prinzipien nicht verstanden.

Mit solchen Beispielen wird es sehr schwer, den Studenten die Vorzüge von OO zu verdeutlichen. Wer keine OO lehren will oder kann, der soll es bleiben lassen, aber dann soll er auch ganz bei C bleiben und seine Studenten nicht mit dem Wort "class" belästigen.

Hier ist ein funktionierendes Demo für die Klasse Person mit Zuweisung von Vorname und Nachname über cin. Kannst du, wenn du willst, auf Student übertragen, dann hast du eine im Sinne der Aufgabenstellung richtige Lösung.

C++:
#include <iostream>

using namespace std;

class Person
{
    private:
    char * vorname;
    char * nachname;
    public:
    Person ( char * vn, char * nn)
    {
    vorname = vn;
    nachname = nn;
    }
    virtual void info ()
    {
    cout << "Vorname: " << vorname << ", Nachname: " << nachname << endl;
    }
};

int main (int argc, char * argv[])
{
    char vn [32];
    char nn [32];

    Person p (vn, nn);

    cout << "Vorname: ";
    cin >> vn;
    cout << "Nachname: ";
    cin >> nn;

    p.info();
    
    return 0;
}



Es ist aber großer Schweinkram, dass die äußere Funktion main sich um die Bereitstellung des Speichers für Vor- und Nachname kümmert, und hat nicht das Geringste mit OO zu tun, aber nur so funktioniert das mit cin bei diesem Klassendesign.

So, genug gelästert, jetzt entwickeln wir eine ordentliche Lösung.

"Richtiges" C++ wäre, den Namen in C++-Strings (Datentyp string bzw. std::string) zu speichern, das meinte f-th vermutlich mit "Container". Ist dir dieser Datentyp schon mal begegnet?

Andere Möglichkeit (weniger schön, aber immer noch brauchbar): Den Speicher selber verwalten, aber nicht in main, sondern innerhalb von Person. Das macht man mit new oder malloc. Irgendwas davon schon mal gehört?

Dieser Post wurde am 13.01.2014 um 12:11 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
13.01.2014, 13:06 Uhr
~Ranny
Gast


Oh je, echt so schlimm? Ich wusste ja, dass meine Dozenten inkompetent sind, aber gleich derart übertrieben?
Nun gut, ich hatte gestern noch etwas rumprobiert und merkwürdigerweise hat das Programm funktioniert, als ich Folgendes geändert habe:


C++:
int
main ()
{
    char * vn = new char;
    char * nn = new char;
    char * sf = new char;


Also zumindest liest er dann richtig ein und gibt auch das Richtige aus: immerhin, mehr wollte ich erst einmal nicht (die Aufgabe ist so nicht ganz vollstädig, ich muss noch Einiges zusätzlich machen aber ich dacht mir, ich müsste erst einmal mit dem Grundgerüst zurecht kommen.)

Gerne probiere ich gleich mal aus deinen Quellcode zu erweitern, ao
Und um auf deine Fragen zu antworten: string hatten wir in C und auch malloc... das mit dem new habe ich versucht gestern nachzulesen, allerdings war ich da schon etwas zu müde für
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
13.01.2014, 15:31 Uhr
ao

(Operator)



Zitat von ~Ranny:
Oh je, echt so schlimm? Ich wusste ja, dass meine Dozenten inkompetent sind, aber gleich derart übertrieben?

Leider ja, wie es scheint. Diese Person-Klasse enthält gleich mehrere richtig böse Fallen. Der Segmentation-Fault-Absturz beim cin ist nur eine davon (und darauf hat die "Deprecated-Conversion"-Warnung sogar noch hingewiesen - ihr Erstis habt das natürlich nicht verstanden, aber euer Dozent hätte es merken müssen). Eine andere kommt hier: Probier mal das Programm unten aus, die Aufgabe war ja, zwei Studenten einzugeben. Lass es laufen, gib zwei verschiedene Namen ein und lass dich von der Ausgabe in der letzten Zeile überraschen:

C++:

// Klasse Person wie oben definiert hier einfügen

int main (int argc, char * argv[])
{
    char vn [32];
    char nn [32];

    cout << "Erster Student" << endl;
    cout << "Vorname: ";
    cin >> vn;
    cout << "Nachname: ";
    cin >> nn;

    Person p1 (vn, nn);
    p1.info();
    
    cout << "Zweiter Student" << endl;
    cout << "Vorname: ";
    cin >> vn;
    cout << "Nachname: ";
    cin >> nn;

    Person p2 (vn, nn);
    p2.info();
    
    cout << "Und jetzt noch mal zur Kontrolle den ersten:" << endl;
    p1.info ();
    
    return 0;
}



Wie kommt das? Klar, Person kopiert die Namen nicht, sondern behält nur die Verweise. Und sobald sich der verpointerte Speicher ändert, ändert sich auch der Name der Person. Netter Seiteneffekt :-( Eigentlich ist diese ganze Objekt-Denke mal erfunden worden, um sich sowas vom Halse schaffen zu können. Und dann kommt euer Dozent und serviert euch "Klassen", die solche elementaren Dinge nicht können.


Zitat:
Und um auf deine Fragen zu antworten: string hatten wir in C und auch malloc... das mit dem new habe ich versucht gestern nachzulesen, allerdings war ich da schon etwas zu müde für

string hattet ihr in C ... als Synonym für char*?

Es gibt in der C++-Standardbibliothek eine Klasse namens string, die dir das Hantieren mit char*, malloc, free und den ganzen restlichen Mist abnimmt. Und die auch keine Längenbegrenzung kennt - um in C Strings einzulesen, von denen man nicht im Voraus weiß, wie lang sie maximal werden können, muss man sich schon etwas anstrengen (blockweise lesen und bei Bedarf Speicher nach-allozieren). Auf einen C++-String kannst du einfach cin machen und lostippen, und um den Rest kümmert sich die Klasse selber.

Daher gibts schon fast eine moralische Verpflichtung, sobald man "C++" sagt, auch "string" zu sagen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
13.01.2014, 15:48 Uhr
~Ranny
Gast


Okay.......
jetzt bin ich vollkommen verwirrt ~.~ Ich verstehe schon so fast gar nichts, weil mir das Programmieren einfach nicht liegt und dann erfahre ich hier mal eben, dass das alles Mist ist Nun gut, ändert ja nichts an der Tatsache, dass ich die Aufgabe dennoch machen muss, um die Punkte zu bekommen, sonst wird das nichts mit der Prüfung (brauche 50% für die Zulassnung...)
Also könntest du mir vielleicht in dieser Hinsicht noch einmal helfen? Also ich habe jetzt versucht deine Person-Klasse auf die Student-Klasse zu erweitern, was eigentlich geklappt hat, bis auf die Matrikelnummer. Da nimmt er wohl irgendeinen Wert, den ich da gar nicht haben möchte.... hier mal der Quellcode:


C++:
#include <iostream>

using namespace std;

class Person
{
    private:
    char * vorname;
    char * nachname;
    public:
    Person ( char * vn, char * nn)
    {
    vorname = vn;
    nachname = nn;
    }
    virtual void info ()
    {
    cout << "Vorname: " << vorname << ", Nachname: " << nachname << endl;
    }
};

class Student : public Person
{
    private:
        long matrikelnummer;
        char * studienfach;
    public:
        Student (char * vn, char * nn, long mn, char * sf) : Person (vn, nn)
        {
            matrikelnummer = mn;
            studienfach = sf;
        }
        
    
    virtual void info_()
    {
        cout << "Matrikelnummer: " << matrikelnummer << ", Studienfach: " << studienfach << endl;
    }
};

int main (int argc, char * argv[])
{
    char vn [32];
    char nn [32];
    char sf [32];
    long mn;

    Student p (vn, nn, mn, sf);

       cout << "Vorname: ";
    cin >> vn;
    cout << "Nachname: ";
    cin >> nn;
    cout << "Matrikelnimmer: ";
    cin >> mn;
    cout << "Studienfach: ";
    cin >> sf;
    
    p.info();
    p.info_();
    
    return 0;
}



Egal ob ich eine Matrikelnummer-Eingabe mache oder nicht, da kommt immer ein konstanter Wert raus, und ich sehe einfach nicht, woran das liegt. Vielleicht erkannt das ja dein geschultes Programmierauge
Und wie genau soll ich jetzt das Problem mit der zweiten Eingabe lösen?? Da bin ich auch echt ratlos :/
Vielleicht hilft ja die ganze Aufgabenstellung etwas weiter.....?


Zitat:
Vererbung, cin - cout, exception handling (12 Punkte)
Leiten Sie mittels Vererbung von der angegebene Klasse Person die Klasse Student ab. Erweitern Sie die Klasse
Student so, dass sie zus¨atzlich die Matrikelnummer und das Studienfach aufnehmen kann.
class Person {
private:
char * vorname;
char * nachname;
public:
Person ( char * vn, char * nn)
{
vorname = vn;
nachname = nn;
}
virtual void info ()
{
cout << "Vorname: " << vorname << ", Nachname: " << nachname << endl;
}
};
Schreiben Sie ein Programm, dass mittels cin die Datens¨atze von zwei Studenten einliest und anschließend mit
der Methode info ausgibt.
U¨ berwachen Sie das Programm mittels Exception handling. Definieren Sie hierzu fu¨r die die folgenden Fa¨lle
eigene Fehlerklassen:
1. Die Matrikelnummer ist 0
2. Die Matrikelnummer ist negativ
3. Die Matrikelnummer hat nicht genau 7 Stellen.


Ich bin dir jetzt schon unheimlich dankbar für die Hilfe
Aber noch dankbarer wäre ich, wenn du mich auch für den Rest der Aufgabe nicht im Stich lässt :P
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
14.01.2014, 10:48 Uhr
ao

(Operator)



Zitat von ~Ranny:
Egal ob ich eine Matrikelnummer-Eingabe mache oder nicht, da kommt immer ein konstanter Wert raus, und ich sehe einfach nicht, woran das liegt.

Ja, das liegt an diesem blödsinnigen Klassenentwurf, anders kann man das wirklich nicht nennen. Die Matrikelnummer wird tatsächlich in die Student-Instanz hineinkopiert, während die Zeichenketten draußen liegenbleiben und die Instanz nur die Zeiger darauf festhält.

Du musst einfach die Reihenfolge ändern, so dass die Nummer eingelesen wird, bevor die Student-Instanz erzeugt wird. Dann passt das:


C++:
    cout << "Vorname: ";
    cin >> vn;
    cout << "Nachname: ";
    cin >> nn;
    cout << "Matrikelnimmer: ";
    cin >> mn;
    cout << "Studienfach: ";
    cin >> sf;

    Student p (vn, nn, mn, sf);



Und für die zweite Eingabe brauchst du zwei Instanzen vom Typ Student und zwei Sätze String-Variablen. Das ist ja grad das Absurde an dieser Aufgabe. Stell dir vor, du solltest so dein ganzes Semester abbilden, Hunderte von Studenten.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: