??Zeiger auf Feld von Klassen-elementen??



  • Hallo !!
    Ich hofffe hier kann mir jemand weiterhelfen...

    Ich habe folgende Aufgabestellung bekommen...

    HINWEIS:
    Ab dieser Übung ist folgendes bei der Erstellung der Aufgabe zu beachten:

    1. Klasse Münze
    Im Euroland kennt man 8 unterschiedliche Münzen: 1,2,5,10,20,50 Cent,1 Euro und
    2 Euro. Erstellen Sie eine Klasse class Muenze mit den privaten Datenmember
    string Art, um die Münzsorte, z.B. 1 CENT oder 50 CENT, abzulegen und int
    Wert, um den Wert der Münze in Cent zu hinterlegen.
    Versehen Sie die Klasse mit einer Methode string muenzwurf(int start);.
    Diese soll zufällig generiert das Wort „Kopf“ oder „Zahl“ zurückgeben. Überladen
    Sie den Schiebeoperator << zur Ausgabe einer Münze.

    2. Klasse Kleingeld
    Eine Ansammlung von Münzen befindet sich üblicherweise als Kleingeld in einem
    Portemonnaie. Erstellen Sie zur Verwaltung dieser Münzen eine Klasse Kleingeld

    class Kleingeld{
    private:
    Muenze *M[100]; <=========<===<===<===<====<===Zugriff auf... ***
    int Anzahl; //Anzahl der Muenzen
    public:
    // Elementfunktionen
    //. . .
    };

    Ein Objekt dieser Klasse kann bis zu 100 Münzen aufnehmen. Programmieren Sie
    geeignete Konstruktoren, Destruktoren und eine passende Ausgabefunktion. Die
    Münzen sollen Objekte im Freispeicher sein. Schreiben Sie ein kleines
    Testprogramm.

    Weiterhin sind folgende Funktionen zu programmieren:

    a. Erstellen sie eine Elementfunktion bool empty(), die überprüft, ob
    Kleingeld vorhanden ist. Eine Methode double wert()const soll den
    Gesamtwert der Münzen in Cent zurückgeben.

    b. Erstellen Sie eine Methode Kleingeld &pop(int i), die die i-te
    Münze aus der Kleingeldbörse eliminiert.

    c. Erstellen Sie folgende Operatorüberladungen

    i. Kleingeld &operator>>(Muenze &Muenze), um die oberste
    Münze herauszunehmen.

    ii. Kleingeld &operator<<(const Muenze &neu), um eine neue
    Münze aufzunehmen.

    iii. Kleingeld &operator=(const Kleingeld &K) für Kleingeld-
    Zuweisungen

    ***das Problem liegt jetzt in dieser Zeile wie benutze ich die Zeiger oder weise ich ihnen was zu...

    ___________________________________________________________________________
    Mainprogramm :

    #include "muenze.h"
    #include "kleing.h"

    using namespace std;

    // Zeit für die Zufallsfunktion...
    time_t time(), zp;
    struct tm *localtime(), *tp;

    int main() {

    int auswahl,empt,zufall;

    Kleingeld boerse;

    do{
    cout << endl << endl;
    empt=boerse.empty();
    if (empt == 0) cout << "Es sind keine Muenzen in der Geldboerse !" << endl;
    if (empt == 1) cout << "Es es sind " << boerse.anzahle() << " Muenzen in der Geldboerse !" << endl;
    cout << "\nWelche Aktion soll ausgefuehrt werden ?" << endl;
    cout << "(1)Neue Muenze (2)Muenze entfernen (3)Inhalt anzeigen " << endl;
    cout << "(4)Muenze werfen (5)Summe des Geldes (6)Inhalt sortieren " << endl;
    cout << "(0)Beenden : ";
    cin >> auswahl;

    if (auswahl == 1) {
    cout << "\n\nNeue Muenze wird hinzufuegen :" << endl;
    //cin << boerse.*M[0];
    }
    if (auswahl == 2) {
    cout << "\n\nMuenze entfernen :" << endl;
    }
    if (auswahl == 3) {
    cout << "\n\nInhalt anzeigen :" << endl;
    }
    if (auswahl == 4) {
    cout << "\n\nMuenze werfen :" << endl;
    // Zeit holen
    zp=time(0);
    tp=localtime(&zp);
    //cout << "In Sekunde " << tp->tm_sec << " wurde " << Kleingeld::muenzwurf(tp->tm_sec) << " geworfen !";
    }
    if (auswahl == 5) {
    cout << "\n\nSumme des Geldes :" << endl;
    cout << endl;
    }
    if (auswahl == 6) {
    cout << "\n\nInhalt sortieren :" << endl;
    }
    }while(auswahl);

    cout << "\n\nProgramm wurde beendet!" << endl;
    return 1;
    }

    _________________________________________________________________________
    kleing.h

    class Kleingeld {
    friend ostream &operator<<(ostream &o, Muenze &Muenze);

    private:
    class Muenze *M[100];
    int Anzahl; //Anzahl der Muenzen

    public:
    Kleingeld(){
    Anzahl = 0;
    for (int i=0; i<=99 ; i++){
    }

    cout << "K-Konstrukt";
    }

    ~Kleingeld(){
    cout << "K-Destrukt";
    }

    int anzahle() {
    return Anzahl;
    }

    bool empty() {
    if (Anzahl >= 1) return 1;
    else return 0;
    }

    Kleingeld &operator=(const Kleingeld &K) {
    //Anzahl=K;
    return *this;
    }

    Kleingeld &operator<<(const Muenze &neu) {

    cout << "\nBitte geben Sie den Wert der Muenze ein :";
    cin >> Anzahl;
    cout << "\nBitte geben Sie die Art der Muenze ein :";
    //cin >> *M[0];
    // Muenz Anzahl erhoehen
    Anzahl++;
    }

    };

    // ausgabe als friend
    ostream &operator<<(ostream &o, const Muenze &Muenze) {
    o << Muenze << " wurde geworfen! " << endl;
    return o;
    }

    ___________________________________________________________________________
    Muenze.h

    class Muenze {
    friend istream &operator>>(istream &i, class Muenze &neu);

    private:
    string art;
    int wert;

    public:
    //Standardkonstruktor: Wert=0, Art=""
    Muenze(){
    art ="";
    wert =0;
    cout << "M-Konstrukt";
    }

    ~Muenze(){
    cout << "\nM-Destrukt";

    }

    };

    istream &operator>>(istream &i1, Muenze &neu){

    cout << "\nBitte den Wert der Muenze in Cent eingeben :";
    cin >> neu.wert;
    if (neu.wert >= 99 ) neu.art="Euro";
    else neu.art="Cent";
    return i1;
    }

    _________________________________________________________________________

    Wäre schön wenn mir da jemand weiter helfen kann...
    Danke schon mal...



  • Es wäre schön, wenn du deim Probelm genauer beschreiben könntest/würdest. Ich habe es also jetzt so verstanden, dass du nicht weißt, wie man auf Die Array-Elemente eines Arrays aus Zeigern zugreift, stimmts?

    Also:

    [cpp]
    // eine Testkalsse:
    class test
    {
    public:
    void Machwas()
    {
    cout << "MachWas()" << endl;
    };
    }

    //main:
    int main()
    {
    // erstmal etwas einfaches:
    test* obj; // Einen Zeiger auf Test
    // Der Zeiger zeigt jetzt erstmal irgendwo hin, aber noch nciht auf ein test-
    // obj, deshalb eines erstellen:
    obj = new test;

    // so, nun haben wir einen fertigen Zeiger auf ein test-objekt.
    // Auf dieses greift man mit dem ->Operaot zu:
    obj->Machwas();

    // mit einem Array ist das auch nciht anders, nur dass dort eben mehrere
    // Objekte gespeichert sind

    // Dies sind 3 Zeiger, die noch ins nichts zeigen, deshalb mit new Objekte
    // erzeugen:
    test* ar[3]; // Dies ist ein Array aus Zeigern auf test-objekte
    for(int i = 0; i < 3; i++)
    ar[i] = new test; // Objekte erstellen

    // Auf diese greift man jetzt genau so wie auf normale Zeiger zu, nur eben mit Index:
    ar[0]->Machwas()
    for(i = 0; i < 3; i++)
    ar[i]->Machwas();

    // Zum Schluss musst du die Objekte unbedingt wieder löschen, mit delete:

    delete obj;
    for(i = 0; i < 3; i++)
    delete ar[i];

    return 1;
    }



  • Es wäre schön, wenn du deim Probelm genauer beschreiben könntest/würdest. Ich habe es also jetzt so verstanden, dass du nicht weißt, wie man auf Die Array-Elemente eines Arrays aus Zeigern zugreift, stimmts?

    Also:

    // eine Testkalsse:
    class test
    {
    public:
      void Machwas()
      {
        cout << "MachWas()" << endl;
      };
    }
    
    //main:
    int main()
    {  
      // erstmal etwas einfaches:
      test* obj;   // Einen Zeiger auf Test
      // Der Zeiger zeigt jetzt erstmal irgendwo hin, aber noch nciht auf ein test-
      // obj, deshalb eines erstellen:
      obj = new test;
    
      // so, nun haben wir einen fertigen Zeiger auf ein test-objekt.
      // Auf dieses greift man mit dem ->Operaot zu:
      obj->Machwas();
    
      // mit einem Array ist das auch nciht anders, nur dass dort eben mehrere 
      // Objekte gespeichert sind
    
      // Dies sind 3 Zeiger, die noch ins nichts zeigen, deshalb mit new Objekte 
      // erzeugen:
      test* ar[3];   // Dies ist ein Array aus Zeigern auf test-objekte
      for(int i = 0; i < 3; i++) 
        ar[i] = new test;    // Objekte erstellen
    
      // Auf diese greift man jetzt genau so wie auf normale Zeiger zu, nur eben mit Index:
      ar[0]->Machwas()
      for(i = 0; i < 3; i++)
        ar[i]->Machwas();
    
      // Zum Schluss musst du die Objekte unbedingt wieder löschen, mit delete:
    
      delete obj;
      for(i = 0; i < 3; i++)
       delete ar[i];
    
      return 1;
    }
    

    Das über dem hier, da hab ich das /cpp vergessen ...



  • Das mit Zeigerarrays ist bei 100 Einträgen unschön langsam, nimm doch std::vector<Muenze*> irgendeinname(100); aus <vector>.

    mfg
    Glamdring



  • Ich kann mir nicht vorstellen, dass das länger dauert mit Arrays als mit vector... aber ich lass mich gerne besser belehren



  • Ich kann mir nicht vorstellen, dass das länger dauert mit Arrays als mit vector... aber ich lass mich gerne besser belehren



  • 100 Konstruktoren nicht langsam ???

    Gruß
    Glamdring



  • Wie soll ein Vektor schneller als ein statisches Array sein? Und was haben Konstruktoren damit zu tun?
    Ein vector<Muenze> mit reserve hingegen wäre wohl schneller als das ständige Allokieren mit new und technisch gesehen sind die Muenzen ja auch im Freispeicher, aber ob der Lehrer das so will? 🙂 Außerdem wird das Löschen an einer bestimmten Stelle dann wieder langsamer...



  • Vielleicht denk ich falsch, aber das wär meine Begründung:
    Wenn mans mit Pointern macht muss man mit new Speicher allokieren. vector<> kann mit den Instanzen arbeiten, muss entsprechend nicht allokieren, ausserdem muss nicht sofort der Wert zugewiesen werden und Vecotren sind erweiterbar.

    mfg
    Glamdring



  • Wie macht es denn vector? Irgendwie muss ja der auch seine Sachen speichern , oder? Aufm Stack?? glaub ich nciht. Außerdem muss man ja nur einmal mit new die Instanzen erstellen und ncith bei jedem Aufruf.
    Ich denk, dass das Array schneller ist, denn da stehen eben nur die Pointer drin und der Comp greift darauf zu. Bei vector(so stell ich mirs vor) muss erst noch die Adresse davon rausgekramt werden oder so, denk ich mal 🙂



  • Stimmt, Vector arbeitet mit den bereits erzeugten Objekten, wobei auch ein konstruktor aufgerufen wird. Ich glaube aber, dass es mehr arbeit ist die Pointer zu dereferenzieren, weis aber net genau.

    mfg
    Glamdring



  • vector<T*> und T*[n] sind beides Container für T*. Wo man die Zeiger herbekommt (in diesem Fall wohl über new) hat damit nichts zu tun. Ein statisches Array braucht sogar eine Allokierung auf dem Heap weniger (im Idealfall also gar keine, wenn man ein Kleingeld-Objekt auf dem Stack erstellt).



  • also ist das Array schneller?

    Und die Dereferenzierung ist doch kein Problem...

    int *ar;
    ar = new int[100];
    ar[10] = 12;



  • mhhh, überzeugt, aber ich wollte Vector<T> satt Vector<T*>

    mfg
    Glamdring



  • Nein, das ist jetzt ein dynamisches Array. Das ist nur noch minimal schneller als ein Vektor (und dafür unkomfortabler). Der Vergleich war hier zwischen:

    // Original und so, wie es laut OP sowieso sein _muss_
    class Kleingeld
    {
        Muenze* muenzen[100];
    ...
    };
    

    und

    // vector<T*>-Version
    class Kleingeld
    {
        vector<Muenze*> muenzen; // Wird entsprechend vergrößert
    ...
    };
    


  • Ja, klar, aber irgendwo muss auch vector<T> seine Ts ablegen. Und dass das auf dem Stack passiert, glaub ich weniger, also auch mit new ( oder malloc() ), aber das tut ja hier auch nciths zur Sache 🙂 Der Threadersteller hat sich ja auch nicht mehr gemeldet 🙂

    Gruß, maxi



  • Jupp



  • Hi...
    Ich danke euch erstmal über die Zahlreichen antworten!!!

    Bin jetzt auch so weit gekommen...
    nur ralle ich es jetzt wieder nicht wie ich den ganzen krempel ausgebe...
    ich rufe eine methode aus kleingeld auf...
    was mache ich in dem überladenen operator<< falsch?

    Kleingeld &operator=(const Kleingeld &K) <--- dies Methode soll ich in Kleingeld schreiben, nur wie?

    ? ist es möglich im main-programm das private objekt Anzahl auszugeben, oder ist es so wie ich es gemacht habe schon gar nicht so verkehrt?

    Fällt euch irgendwas auf in dem Programm was ich noch falsch mache?
    Ich danke für jede Antwort...

    ___________________________________________________________________________
    Mainprogramm :

    #include "muenze.h"
    #include "kleing.h"

    using namespace std;

    // Zeit für die Zufallsfunktion...
    time_t time(), zp;
    struct tm *localtime(), *tp;

    int main() {

    int auswahl,empt,zufall;

    Kleingeld boerse;
    Muenze neue;

    do{

    cout << endl << endl << endl;
    empt=boerse.empty();
    if (empt == 0) cout << "Es sind keine Muenzen in der Geldboerse !" << endl;
    if (empt == 1) cout << "Es es sind " << boerse.anzahle() << " Muenze(n) in der Geldboerse !" << endl;
    cout << "__________________________________________________________________";
    cout << "\nWelche Aktion soll ausgefuehrt werden ?" << endl;
    cout << "(1)Neue Muenze (2)Muenze entfernen (3)Inhalt anzeigen " << endl;
    cout << "(4)Muenze werfen (5)Summe des Geldes (6)Inhalt sortieren " <<endl;
    cout << "(0)Beenden : ";
    cin >> auswahl;

    if (auswahl == 1) {
    cout << "__________________________________________________________________";
    cout << "\n\nMuenze Nr. " << (boerse.anzahle())+1 << " wird hinzufuegen :";
    boerse >> neue;

    }
    if (auswahl == 2) {
    cout << "__________________________________________________________________";
    cout << "\n\nMuenze entfernen :" << endl;

    }
    if (auswahl == 3) {
    cout << "__________________________________________________________________";
    cout << "\n\nInhalt anzeigen :" << endl;
    boerse.ausgabe();

    }
    if (auswahl == 4) {
    cout << "__________________________________________________________________";
    cout << "\n\nMuenze werfen :" << endl;
    // Zeit holen
    zp=time(0);
    tp=localtime(&zp);
    cout << "\nIn Sekunde " << tp->tm_sec << " wurde " << neue.muenzwurf(tp->tm_sec) << " geworfen !"<<endl;

    }
    if (auswahl == 5) {
    cout << "__________________________________________________________________";
    cout << "\n\nSumme des Geldes :" << endl;

    cout << endl;

    }
    if (auswahl == 6) {
    cout << "__________________________________________________________________";
    cout << "\n\nInhalt sortieren :" << endl;

    }
    }while(auswahl);

    cout << "\n\nProgramm wurde beendet!" << endl;

    return 1;
    }

    _________________________________________________________________________
    kleing.h

    class Kleingeld {
    friend class Muenze;
    friend ostream &operator<<(ostream &o, Muenze *m);

    private:
    class Muenze *M[100];
    int Anzahl; //Anzahl der Muenzen

    public:
    Kleingeld(){ // Konstruktor von Kleingeld
    Anzahl = 0;
    cout << "\t-> K-Konstrukt";
    }

    ~Kleingeld(){ // Destruktor von Kleingeld
    for (int i=0; i<=Anzahl ; i++){
    delete M[i];
    }
    cout << "\t-> K-Destrukt";
    }

    int anzahle() { // Gibt die Anzahl der muenzen zurueck, da Anzahl private
    return Anzahl;
    }

    bool empty() {
    if (Anzahl >= 1) return 1;
    else return 0;
    }

    Kleingeld &operator=(const Kleingeld &K) {

    //Anzahl=K;
    return *this;
    }

    Kleingeld &operator>>(Muenze &neu){
    int nwert,ok;
    M[Anzahl] = new Muenze;
    *M[Anzahl] = neu;
    Anzahl++;

    do {
    cout << "\n\nWert der Muenze in Cent eingeben :";
    cin >> nwert;
    if ( (nwert == 1) || (nwert == 2) || (nwert == 5) || (nwert == 10)
    || (nwert == 20) || (nwert == 50) ) {
    neu.wert = nwert;
    neu.art = "Cent";
    ok = 0;
    }
    if ((nwert == 100) || (nwert == 200)) {
    neu.wert = nwert;
    neu.art = "Euro";
    ok = 0;
    }

    } while(ok);

    return *this;
    }

    void ausgabe(){
    for(int i=0;i<Anzahl;i++){
    cout << *M[i];
    cout << endl;
    }
    }

    };

    // ausgabe als friend
    ostream &operator<<(ostream &o, const Muenze *m){
    o << m???wert << " " << m???art << " Muenze" << endl;

    return o;
    }

    ___________________________________________________________________________
    Muenze.h

    class Muenze {
    friend class Kleingeld;

    private:
    string art;
    int wert;

    public:

    //Standardkonstruktor: Wert=0, Art=""
    Muenze(){
    art ="";
    wert =0;
    cout << "\t\t-> M-Konstrukt";
    }

    ~Muenze(){
    cout << "\n-> M-Destrukt";

    }

    string muenzwurf(int start) {
    int zufall;
    string koza;
    srand(start);
    // Zufallszahl aus zweien...
    zufall=rand()%2;
    if (zufall == 1) koza="Kopf";
    else koza="Zahl";
    return koza;

    }

    };



  • ... Es wäre besser, wenn du nur die Teile deines Prgrammes zeigen würdest, wo noch Problemem entstehen. Außer dem ist es besser lesbar, wenn du die Code-Tags benutzt (C/C++) ganz unten.

    Also: Kleingeld &operator=(const Kleingeld &K) ist der Zuweisungsoperator, damit kannst du zB sowas machen:

    Kleingeld K1, K2;
    K1.Machwas();
    K2 = K1 // <-- hier wird der Zuweisungsoperator aufgerufen.
    Ich denke du sollst das Kleingeld in eine andere Instanz kopieren, also musst du jedes Element der Klasse in das Ausgabeobjekt(K2) kopieren, in dem operator-Aufruf.
    Wenn der Operator direkt zur Klasse gehört, dann musst du das so machen:

    Kleingeld& Kleingeld::operator=(const Kleingeld&)
    {
    // Anweisungen
    }

    ich denke, ostream-operaot soll ja den Inhalt von Kleingeld ausgeben, oder?
    Dann müsste das ja dann in etwa so sein, aber ich kenn mich mit operatoren nicht so gut aus 🙂

    ostream& Kleingeld::operator<<(ostream& o, Kleingeld K)
    {
    // Gib den Inhalt aus etwa so:
    o << "Inhalt" << endl;
    }

    So, zur dritten Frage:
    Das mit KLeingeld::Anzahele() ist richtig so, denn eine Klasse soll ihre eigenen Elemente nicht von anderen verändern lassen dürfen. Sie soll nur über Schnittstellen(Methoden) mit der Außenwelt kommunizieren. Daher ist das schon richtig so.

    Gruß, Maxi



  • danke erstmal...
    Ok, wer das nächste mal versuchen dran zu denken die c/c++ tags zu setzen...

    was aber meine eigentliche frage ist wie rufe ich in...

    ostream &operator<<(ostream &o, const Muenze *m){
    	o << mwert << " " << m*.art << " Muenze" << endl;	
    
    	return o;
    }
    

    die objekte (m??wert und m??art) auf?


Anmelden zum Antworten