Vector, Copy Constructor & C++



  • main.cpp

    #include <iostream>
    #include "kunde.h"
    #include "kundenkartei.h"
    
    using namespace std;
    
    int main() {
        char select;
        kundenkartei *kartei;
        kartei = new kundenkartei;
    
        do{
            cout << "\t(e) Eingabe eines neuen Kunden von Tastatur" << endl;
            cout << "\t(l) Löschen eines Kunden" << endl;
            cout << "\t(a) Ausgabe aller Kunden" << endl;
            cout << "\t(v) Eintrag verdoppeln" << endl; // Fehler hier
            cout << "\t(x) Beenden" << endl;
            cout << "Ihre Eingabe: ";
            cin >> select;
    
            switch(select){
                case 'e':
                    kartei->anlegenKunde();
                    break;
                case 'l':
                    cout << "Welcher Kunder (Kundennummer) soll gelöscht werden?" << endl;
                    int x;
                    cin >> x;
                    kartei->loeschenKunde(x);
                    break;
                case 'a':
                    kartei->ausgebenKunde();
                    break;
                case 'v':
                    cout << "Welcher Kunder (Kundennummer) soll gelöscht werden?" << endl;
                    int y;
                    cin >> y;
                    kartei->kopierenKunde(y);
                    break;
                case 'x':
                    cout << "Programm wird beendet." << endl;
                    delete kartei;
                    break;
            }
        }while(select != 'x');
    
        return 0;
    }
    

    kundenkartei.cpp

    #include "kundenkartei.h"
    #include "kunde.h"
    
    kundenkartei::kundenkartei() {
    }
    
    void kundenkartei::anlegenKunde(){
    
        string vorname, name, wohnort;
        int plz;
        /*
        cout << "Vorname: ";
        cin >> vorname;
        cout << "Nachname: ";
        cin >> name;
        cout << "PLZ: ";
        cin >> plz;
        cout << "Wohnort: ";
        cin >> wohnort;
        */
        vorname = "Max";
        name = "Mustermann";
        plz = 55555;
        wohnort = "Musterdorf";
        kk.push_back(kunde(vorname, name, plz, wohnort));
        vorname = "Detlef";
        name = "Müller";
        plz = 42231;
        wohnort = "Peschek";
        kk.push_back(kunde(vorname, name, plz, wohnort));
        vorname = "Stefan";
        name = "Rein";
        plz = 223187;
        wohnort = "Weilberg";
        kk.push_back(kunde(vorname, name, plz, wohnort));
    }
    
    void kundenkartei::loeschenKunde(int x){
        for(int i = 0; i < kk.size(); i++){
            if(kk[i].GetKundenNr() == x) {
                kk.erase(kk.begin()+i);
            } 
        }
    }
    
    void kundenkartei::ausgebenKunde(){
        for(int i = 0; i < kk.size(); i++){
            cout << "Kundennummer:\t" << kk[i].GetKundenNr() << endl;
            cout << "Name:\t\t" << kk[i].GetName() << ", " << kk[i].GetVorname() << endl;
            cout << "PLZ, Ort:\t" << kk[i].GetPlz() << ", " << kk[i].GetWohnort() << endl;
        }
    }
    
    void kundenkartei::kopierenKunde(int x){
        for(int i = 0; i < kk.size(); i++){
            if(kk[i].GetKundenNr() == x) {
                kk[i].switchCopyTrue();
                kk.push_back(kk[i]);
                for(int i = 0; i < kk.size(); i++){
                    kk[i].switchCopyFalse();
                }
            } 
        }
    }
    

    kundenkartei.h

    #ifndef KUNDENKARTEI_H
    #define KUNDENKARTEI_H
    
    #include <iostream>
    #include "kunde.h"
    #include <vector>
    using namespace std;
    
    class kundenkartei {
    public:
        kundenkartei();
    
        void anlegenKunde();
        void loeschenKunde(int x);
        void ausgebenKunde();
        void kopierenKunde(int x);
    
    private:
        vector<kunde> kk;
    };
    
    #endif /* KUNDENKARTEI_H */
    

    kunde.cpp

    #include "kunde.h"
    
    kunde::kunde() {
    }
    
    kunde::kunde(string vor, string nach, int p, string ort){
        vorname = vor;
        name = nach;
        plz = p;
        wohnort = ort;
        kundenNr = ++serienNr;
    }
    
    kunde::kunde(const kunde& x){
        name = x.name;
        plz = x.plz;
        wohnort = x.wohnort;
    
        if(x.copyAllowed == true){
            kundenNr = ++serienNr;
        } else if(x.copyAllowed == false) {
            kundenNr = x.kundenNr;
        }
    }
    
    void kunde::switchCopyTrue(){
        copyAllowed = true;
    }
    void kunde::switchCopyFalse(){
        copyAllowed = false;
    }
    
    void kunde::SetKundenNr(int kundenNr) {
        this->kundenNr = kundenNr;
    }
    
    int kunde::GetKundenNr() const {
        return kundenNr;
    }
    
    void kunde::SetPlz(int plz) {
        this->plz = plz;
    }
    
    int kunde::GetPlz() const {
        return plz;
    }
    
    void kunde::SetWohnort(string wohnort) {
        this->wohnort = wohnort;
    }
    
    string kunde::GetWohnort() const {
        return wohnort;
    }
    
    void kunde::SetVorname(string vorname) {
        this->vorname = vorname;
    }
    
    string kunde::GetVorname() const {
        return vorname;
    }
    
    void kunde::SetName(string name) {
        this->name = name;
    }
    
    string kunde::GetName() const {
        return name;
    }
    

    kunde.h

    #ifndef KUNDE_H
    #define KUNDE_H
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    static int serienNr = 0;
    
    class kunde {
    public:
        kunde();
        kunde(string vor, string nach, int p, string ort);
    
        kunde(const kunde& x);
    
        void SetKundenNr(int kundenNr);
        int GetKundenNr() const;
        void SetPlz(int plz);
        int GetPlz() const;
        void SetWohnort(string wohnort);
        string GetWohnort() const;
        void SetVorname(string vorname);
        string GetVorname() const;
        void SetName(string name);
        string GetName() const;
    
        void switchCopyTrue();
        void switchCopyFalse();
    
    private:
        string name, vorname, wohnort;
        int plz, kundenNr;
        bool copyAllowed;
    };
    
    #endif /* KUNDE_H */
    

    Problem:
    Eintrag verdoppeln funktioniert nur im 1. Durchlauf. Beim 2. Ausführen bekommt die zu kopierende Stelle eine andere Kundennummer.

    Meine Frage:
    Könnt ihr mir bitte helfen den Fehler ausfindig zu machen? Mit "Eintrag verdoppeln" möchte ich das der jeweilige Kunde kopiert wird aber dem Eintrag eine andere ID zugewiesen wird. Ich dachte das ich so richtig liege aber anscheinend hat sich da ein Fehler eingeschlichen...


  • Mod

    Ich kapiere nicht, was das mit dem copyAllowed überhaupt soll. Warum kopierst du ein Objekt nicht einfach, wenn du es kopieren möchtest?

    Dein Design ist ... nicht so gut. Angefangen von Kleinigkeiten, wie dass eine Postleitzahl trotz des Namens keine Zahl ist; weiter zu irreführenden Funktionsnamen (switch im Namen, aber nichts wird gewechselt); bis hin zu Implementierungsdetails an Stellen, wo sie nichts zu suchen haben (z.B. das genannte copyAllowed). Bei der Kundenklasse wurde mit viel Aufwand ein einfacher, funktionsloser Datenhalter geschaffen.



  • eine Postleitzahl trotz des Namens keine Zahl ist

    Siehe weshalb hier:
    https://deutschland-in-zahlen.de/postleitzahl.php?plz=0



  • SeppJ schrieb:

    Ich kapiere nicht, was das mit dem copyAllowed überhaupt soll. Warum kopierst du ein Objekt nicht einfach, wenn du es kopieren möchtest?

    Dein Design ist ... nicht so gut. Angefangen von Kleinigkeiten, wie dass eine Postleitzahl trotz des Namens keine Zahl ist; weiter zu irreführenden Funktionsnamen (switch im Namen, aber nichts wird gewechselt); bis hin zu Implementierungsdetails an Stellen, wo sie nichts zu suchen haben (z.B. das genannte copyAllowed). Bei der Kundenklasse wurde mit viel Aufwand ein einfacher, funktionsloser Datenhalter geschaffen.

    Ich muss/werde noch ein Sortierfunktion einbauen und dort werde ich auf temporäre Objekte zurückgreifen müssen. Wenn ich nicht falsch liege nutze ich bei einer Zuweisung zw. 2 Objekten den Kopierkonstruktor, oder Irre ich mich? (z.B. tmp = kk[1]). Da ich aber den Kopierkonstruktor verwendet habe um Einträge zu verdoppeln und den kopierten Einträgen eine eigene Kundennummer zuzuweisen... werde ich automatisch bei jedem temporären Objekt eine neue Kundennummer zuweisen.

    Um diesen Fehler zu beheben wollte ich dem Kopierkonstruktor sagen welche Einträge kopiert werden dürfen und welche nicht.

    Zudem funktioniert mein push_back() doch so das es ebenso den Kopierkonstruktor nutzt...


  • Mod

    Andrioshe schrieb:

    Ich muss/werde noch ein Sortierfunktion einbauen und dort werde ich auf temporäre Objekte zurückgreifen müssen.

    Du löst Probleme, die gar nicht da sind, bevor es sie gibt.

    Wurzel allen Übels ist natürlich der unsinnige globale Programmzustand und die schon erwähnte Schwäche im Design, die Details der Implementierung der Kundenkartei in die Kundenklasse selber auslagert. Wieso ist die Kundenklasse dafür zuständig, sich selber eine Identifikationsnummer zu besorgen? Es wäre doch Aufgabe der Kundenverwaltung, dem Kunden eine Nummer zuzuweisen. Wenn du dies vernünftig umsetzen würdest, dann würde das ganze Problem automatisch entfallen.

    Zum Sortieren muss man in der Regel nichts kopieren, sondern nur Vertauschen und/oder Verschieben. Du kannst eigene Vertauschungs- und Verschiebefunktionen anbieten, die deine Kundenidentifikationsnummern wie gewünscht behandeln, und die dann auch von den Standardsortierfunktionen (oder einer selbstgeschriebenen Sortierfunktion) benutzt werden. Aber ich empfehle dringend, die Designfehler zu beheben, anstatt um sie herum zu programmieren.



  • SeppJ schrieb:

    Andrioshe schrieb:

    Ich muss/werde noch ein Sortierfunktion einbauen und dort werde ich auf temporäre Objekte zurückgreifen müssen.

    Du löst Probleme, die gar nicht da sind, bevor es sie gibt.

    Wurzel allen Übels ist natürlich der unsinnige globale Programmzustand und die schon erwähnte Schwäche im Design, die Details der Implementierung der Kundenkartei in die Kundenklasse selber auslagert. Wieso ist die Kundenklasse dafür zuständig, sich selber eine Identifikationsnummer zu besorgen? Es wäre doch Aufgabe der Kundenverwaltung, dem Kunden eine Nummer zuzuweisen. Wenn du dies vernünftig umsetzen würdest, dann würde das ganze Problem automatisch entfallen.

    Zum Sortieren muss man in der Regel nichts kopieren, sondern nur Vertauschen und/oder Verschieben. Du kannst eigene Vertauschungs- und Verschiebefunktionen anbieten, die deine Kundenidentifikationsnummern wie gewünscht behandeln, und die dann auch von den Standardsortierfunktionen (oder einer selbstgeschriebenen Sortierfunktion) benutzt werden. Aber ich empfehle dringend, die Designfehler zu beheben, anstatt um sie herum zu programmieren.

    Tatsächlich.. Ich werde morgen mein Programm mal umschreiben und hoffen das ich diese Fehler beseitigen kann. Werde mich später noch mal hier melden. Danke das du mich darauf aufmerksam gemacht hast 👍


Log in to reply