Datenbank aus Objekten?



  • Wie willst du denn einen Datensatz anlegen, wenn nicht einzeln?

    Was du brauchst ist z.B. so etwas:

    std::vector<Kunde> kunden
    

    In einer Funktion kannst du dann deine Kundendaten einlesen:

    Kunde neuerKunde;
    std::string name;
    // weitere Variablen für die restlichen Daten
    
    cout << "Name des Kunden: "
    cin >> name;
    
    // weitere Daten eingeben
    
    neuerKunde.name = name;
    
    // weitere Daten dem Kundenobjekt zuweisen
    datenbank.neuerKunde(neuerKunde); // Kunde in die Datenbank schreiben.
    

    Dann liest du dir den von wob angebenen Beitrag durch, damit weißt du dann wie du deine Kunden speichern und lesen kannst.

    Bezogen auf deinen Wunsch nach einer Datenbank:

    class Datenbank
    {
       public:
          void neuerKunde(const Kunde& kunde)
          void ladeAusDatei(const std::string& dateiname);
          void speicherInDatei(const std::string& dateiname);
          // weitere Funktionen
       private:
          std::vector<Kunde> kunden;
    }
    
    void Datenbank::neuerKunde(const Kunde& kunde)
    {
        kunden.push_back(kunde);
    }
    
    void Datenbank::ladeAusDatei(const std::string& dateiname)
    {
        // Code, um "kunden" aus einer Datei zu befüllen
    }
    
    void Datenbank::speicherInDatei(const std::string& dateiname);
    {
        // code, um "kunden" in eine Datei zu schreiben
    }
    

    Deine Kundenklass solltest du noch etwas überarbeiten und sinnvollerweise über geeignete Methoden auf die privaten Daten zugreifen:

    class Kunde
    {
        public:
            Kunde(const std::string& name); // ctor weitere Parameter wie Umsatz usw. noch erweitern
            std::string getName();
            // weitere Methoden
        private:
            std::string name;
            // weitere Daten
    }
    


  • verstehe ich das richtig.
    Die komplette Datenbank wäre dann ein Vektor ?
    -> Wie passt das mit dem 2. Code zusammen.
    Wie ich ihn verstanden habe:
    1. Es wird ein neues Objekt der Klasse Kunde angelegt
    2. Der Benutzer gibt die Daten ein
    3. Die eingegebenen Daten werden dem in 1. erstellten Objekt übergeben
    und jetzt.. wird dieses Objekt in den erstellten Vektor "gepusht" ?

    Wenn ich das richtig verstanden habe.
    Heißen alle Objekte gleich (also neuerKunde?) oder wie wird die Bezeichnung vergeben?
    Und wie könnte ich auf einen bestimmten Kunden zugreifen.
    Wenn ich also Kunde Müller haben will, woher weiß ich wo im Vektor dieser gespeichert ist oder geschieht der zugriff nicht über den Vektor, sonder über die Datei?

    Danke für die Hilfe 🙂



  • weil ich das gerade wieder in dem Code gesehen habe:
    Was genau bedeutet "Kunde& kunde"



  • kaiuwe schrieb:

    verstehe ich das richtig.
    Die komplette Datenbank wäre dann ein Vektor ?

    Ja.

    kaiuwe schrieb:

    -> Wie passt das mit dem 2. Code zusammen.
    Wie ich ihn verstanden habe:
    1. Es wird ein neues Objekt der Klasse Kunde angelegt
    2. Der Benutzer gibt die Daten ein
    3. Die eingegebenen Daten werden dem in 1. erstellten Objekt übergeben
    und jetzt.. wird dieses Objekt in den erstellten Vektor "gepusht" ?

    Richtig.

    kaiuwe schrieb:

    Wenn ich das richtig verstanden habe.
    Heißen alle Objekte gleich (also neuerKunde?) oder wie wird die Bezeichnung vergeben?

    Die Bezeichnung des Objektes ist ziemlich egal, dir geht es doch um die Daten.

    kaiuwe schrieb:

    Und wie könnte ich auf einen bestimmten Kunden zugreifen.
    Wenn ich also Kunde Müller haben will, woher weiß ich wo im Vektor dieser gespeichert ist oder geschieht der zugriff nicht über den Vektor, sonder über die Datei?

    Die Datei dient nur der Persistenz. Du musst den Vektor durchsuchen, bis du den richtigen Datensatz gefunden hast.

    for (auto kunde : kunden)
    {
        if (kunde.getName() == name)
        {
            // gefunden!
        }
    }
    

    Lies dir die Dokumentation von Vector durch! Möglicherweise ist auch ein anderer Containertyp (wie std::map) besser geeignet, falls du immer nach dem Namen suchst (Schlüssel!).



  • kaiuwe schrieb:

    weil ich das gerade wieder in dem Code gesehen habe:
    Was genau bedeutet "Kunde& kunde"

    Referenz auf Kunde, um eine unnötige Kopie zu vermeiden (Performance).

    Du könntest schreiben:

    void neuerKunde(Kunde kunde);
    

    dann:

    Kunde einKunde;
    
    datenbank.neuerKunde(einKunde);
    

    Das führt dann dazu, dass "einKunde" in den Parameter "kunde" kopiert wird. Durch die Referenz wird das vermieden. Das "const" zuvor stellt sicher, dass die Funktion das übergebene Objekt nicht verändert.



  • Du musst auch eine Referenz des Typ Kunde zurückgeben.

    Kunde& neuer_kunde(const Kunde& k){
        return kunden.push_back(k), kunden.back();
    }
    


  • holly321 schrieb:

    Du musst auch eine Referenz des Typ Kunde zurückgeben.

    Kunde& neuer_kunde(const Kunde& k){
        return kunden.push_back(k), kunden.back();
    }
    

    Naja, müssen tut er ja nicht, aber er könnte, wenn er denn wollte.

    Allerdings kommt mir der Code fehlerhaft vor, oder täusche ich mich?

    Kunde& neuerKunde(const Kunde& k)
    {
        kunden.push_back(k); // Kunden am Ende anhängen
        return kunden.back(); // Referenz auf das letzte Element zurückgeben
    }
    


  • [EDIT] Hat sich alles erledigt mit den vermeintlichen Laufzeitfehler (war in Wirklichkeit nur ein Breakpoint den ich ausersehen selbst gesetzt habe ;D)

    Sooo ich habe jetzt mal versucht das alles zu ordnen und zumindest mal einen Kunden zu erstellen und im Vector zu speichern. Leider kommt es zu einem Laufzeitfehler, den ich aber nicht nachvollziehen kann 😞
    Ich weiß dass die Hilfe Mühe macht und weiß sie wirklich zu schätzen 🙂
    Was ich bis jetzt habe. Was neu ist habe ich kommentiert.
    main.cpp

    #include <iostream>
    #include <fstream>
    #include <string>
    #include "main.hpp"
    #include "classKunde.hpp"
    #include "classDatenbank.hpp"
    #include "infilestream.hpp"
    
    using namespace std;
    
    void loadKundeInDatabase(const kunde& createdKunde){    /* soll eine objekt der Klasse  datenbank erstellen und
                                                             und dann mit der funktion neuerKunde den Kunden in den Vektor pushen*/
        datenbank database;
        database.neuerKunde(createdKunde);
    }
    
    void erstelleKunde(){
        string name, vorname, firmenname;
        int umsatz, kundennr;
    
        cout << "Name des Kunden: ";
        cin >> name;
    
        cout << "Vorname des Kunden: ";
        cin >> vorname;
    
        cout << "Firmenname des Kunden: ";
        cin >> firmenname;
    
        cout << "Umsatz des Kunden: ";
        cin >> umsatz;
    
        cout << "Kundennummer des Kunden: ";
        cin >> kundennr;
    
        kunde erstellterKunde;                              //muss ich ja machen, wenn ich die eingaben übergeben will, oder?
    
        erstellterKunde.setfirmenName(firmenname);
        erstellterKunde.setnachName(name);
        erstellterKunde.setvorName(vorname);
        erstellterKunde.setjahresUmsatz(umsatz);
        erstellterKunde.setkundenNummer(kundennr);
    
        loadKundeInDatabase(erstellterKunde);               /*erstellter Kunde wird wie oben beschrieben gespeichert
                                                             --> hier entsteht der Laufzeitfehler :( */
    
    }
    
    int main() {
    
        erstelleKunde();
    
        return 0;
    }
    

    classKunde.cpp

    #include "classKunde.hpp"
    #include <iostream>
    
    using namespace std;
    
    void kunde::setRabatt(){                                             //Hier frage ich mich ob ich das "this" richtig benutze
        if (jahresUmsatz < 10000) {
            this -> rabattKategorie = 0;
        } else if (jahresUmsatz >= 10000 && jahresUmsatz < 20000) {
            this -> rabattKategorie = 1;
        } else if (jahresUmsatz >= 20000 && jahresUmsatz < 40000) {
            this -> rabattKategorie = 2;
        } else if (jahresUmsatz >= 40000 && jahresUmsatz < 100000) {
            this -> rabattKategorie = 4;
        } else if (jahresUmsatz >= 100000) {
            this -> rabattKategorie = 10;
        } else
            this -> rabattKategorie = -1;
    }
    
    void kunde::setfirmenName(const string& firmenName){                  //Referenz richtig benutzt???
        this -> firmenName = firmenName;
    }
    
    void kunde::setnachName(const string& nachName){
        this -> nachName = nachName;
    }
    
    void kunde::setvorName(const string& vorName){
        this -> vorName = vorName;
    }
    
    void kunde::setjahresUmsatz(const int& jahresUmsatz){
        this -> jahresUmsatz = jahresUmsatz;
    }
    
    void kunde::setkundenNummer(const int& kundenNummer){
        this -> kundenNummer = kundenNummer;
    }
    
    int kunde::getKundenNummerByName(){
        return kundenNummer;
    }
    
    int kunde::getRabatt(){
        return rabattKategorie;
    }
    

    classDatenbank.cpp

    #include "classDatenbank.hpp"
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    void datenbank::neuerKunde(const kunde& kunde){
        kunden.push_back(kunde);
    }
    
    void datenbank::getSizeOfVector(){
        cout << kunden.size() << endl;
    }
    
    void datenbank::ladeDatei(const string& dateiPfad)
    {
        // Code, um "kunden" aus einer Datei zu laden
    }
    
    void datenbank::speicherDatei(const string& dateiPfad)
    {
        // code, um "kunden" in eine Datei zu schreiben
    }
    
    void datenbank::getAll(const kunde& kunde){                 /*Hier habe ich versucht das gespeicherte Objekt 
                                                                 aus dem Vektor wieder auszugeben*/
        kunden[0].getKundenNummerByName();
    }
    


  • Ich hab gleich noch eine Frage.
    Wenn ich bei der Funktion erstelleKunde keinen Wert zurückgebe kann ich ja nichts damit anfangen.
    Dementsprechend müsste ich doch den erstelltenKunden zurück geben.
    Wie kann ich Objekte zurück geben.
    Der Code:

    kunde erstelleKunde(){
    
        kunde erstellterKunde;                              //muss ich ja machen, wenn ich die eingaben übergeben will, oder?
    
        string name, vorname, firmenname;
        int umsatz, kundennr;
    
        cout << "Name des Kunden: ";
        cin >> name;
    
        cout << "Vorname des Kunden: ";
        cin >> vorname;
    
        cout << "Firmenname des Kunden: ";
        cin >> firmenname;
    
        cout << "Umsatz des Kunden: ";
        cin >> umsatz;
    
        cout << "Kundennummer des Kunden: ";
        cin >> kundennr;
    
        erstellterKunde.setfirmenName(firmenname);
        erstellterKunde.setnachName(name);
        erstellterKunde.setvorName(vorname);
        erstellterKunde.setjahresUmsatz(umsatz);
        erstellterKunde.setkundenNummer(kundennr);
    
        return erstellterKunde;
    }
    

    funktioniert nicht.
    Fehler: Functions that differ only in their return type cannot be overloaded

    [EDIT] Hat sich erledigt. Ich habe nur vergessenen in der Header Datei void auf kunde zu wechseln.



  • Der Compiler wird wohl noch etwas mehr sagen.



  • [EDIT] Hat sich erledigt

    Ich hab gerade nochmal geguckt. Es gib keine Buildtime und auch keine Runtime Fehler.

    Ich benutze Xcode Wenn ich das Programm starte wird Zeile 20 (kunde erstellterKunde;) grün markiert und daneben steht: Thread 1: breakpoint 2.1
    In der Konsole wird (11db) angezeigt.

    Keine Ahnung was das ist.

    aktualisierter Code:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include "main.hpp"
    #include "classKunde.hpp"
    #include "classDatenbank.hpp"
    #include "infilestream.hpp"
    
    using namespace std;
    
    void loadKundeInDatabase(const kunde& createdKunde){    /* soll eine objekt der Klasse  datenbank erstellen und
                                                             und dann mit der funktion neuerKunde den Kunden in den Vektor pushen*/
        datenbank database;
        database.neuerKunde(createdKunde);
    }
    
    kunde erstelleKunde(){
    
        kunde erstellterKunde;                              //muss ich ja machen, wenn ich die eingaben übergeben will, oder?
    
        string name, vorname, firmenname;
        int umsatz, kundennr;
    
        cout << "Name des Kunden: ";
        cin >> name;
    
        cout << "Vorname des Kunden: ";
        cin >> vorname;
    
        cout << "Firmenname des Kunden: ";
        cin >> firmenname;
    
        cout << "Umsatz des Kunden: ";
        cin >> umsatz;
    
        cout << "Kundennummer des Kunden: ";
        cin >> kundennr;
    
        erstellterKunde.setfirmenName(firmenname);
        erstellterKunde.setnachName(name);
        erstellterKunde.setvorName(vorname);
        erstellterKunde.setjahresUmsatz(umsatz);
        erstellterKunde.setkundenNummer(kundennr);
    
        return erstellterKunde;
        }
    
    int main() {
    
        loadKundeInDatabase(erstelleKunde());
    
        return 0;
    }
    


  • So jetzt noch eine Sinnvolle Frage.

    Nehmen wir mal an ein Kunde wird in dem Vektor "kunden" gespeichert.
    Wie findet der zugriff auf eines der Objekte statt.

    Ich möchte jetzt mit kunde.getKundenNummerByName(); die Kundennummer erhalten

    kunden[0] = kunde 1
    kunden[1] = kunde 2
    ...

    wenn ich jetzt die kundeNummer von Kunde 2 ausgeben will.
    Ich kann ja nicht auf den Vector zugreifen, weil dieser private ist.
    also: kunden[1].getKundenNummerByName geht nicht.



  • Du hast im Debugger einen Breakpoint gesetzt und das Programm wird jetzt dort angehalten. Du wirst dich wohl mal mit der XCode Dokumentation auseinandersetzen müssen.



  • Ja hab ich schon gemerkt 😉



  • kaiuwe schrieb:

    So jetzt noch eine Sinnvolle Frage.

    Nehmen wir mal an ein Kunde wird in dem Vektor "kunden" gespeichert.
    Wie findet der zugriff auf eines der Objekte statt.

    Ich möchte jetzt mit kunde.getKundenNummerByName(); die Kundennummer erhalten

    kunden[0] = kunde 1
    kunden[1] = kunde 2
    ...

    wenn ich jetzt die kundeNummer von Kunde 2 ausgeben will.
    Ich kann ja nicht auf den Vector zugreifen, weil dieser private ist.
    also: kunden[1].getKundenNummerByName geht nicht.

    Ich würde der Klasse Datenbank eine öffentliche Methode "getKundeByName" spendieren, die hat ja Zugriff auf die privaten Daten.

    Kunde getKundeByName(const std::string& name);
    

    In dieser Funktion gehst du durch alle Elemente (die Kunden) im Vector bis du den gesuchten gefunden hast und diesen gibst du zurück.

    In deinem Programm kannst du dann schreiben:

    auto gesuchterKunde = datenbank.getKundeByName("Mustermann");
    
    auto kundennummer = gesuchterKunde.getKundennummer();
    
    // oder zusammen, wenn du von dem Kunden wirklich NUR die Kundennummer brauchst
    
    auto kundennummer = datenbank.getKundeByName("Mustermann").getKundennummer();
    


  • Du weißt schon, dass die Datenbank nicht lange Bestand hat, weil am Ende der Routine der Gültigkeitsbereich der Variablen endet?

    void loadKundeInDatabase(const kunde& createdKunde){    /* soll eine objekt der Klasse  datenbank erstellen und
                                                             und dann mit der funktion neuerKunde den Kunden in den Vektor pushen*/
        datenbank database;
        database.neuerKunde(createdKunde);
    } // hier wird "database" wieder zerstört
    


  • kaiuwe schrieb:

    void erstelleKunde(){
        string name, vorname, firmenname;
        int umsatz, kundennr;
        
        cout << "Name des Kunden: ";
        cin >> name;
        
        cout << "Vorname des Kunden: ";
        cin >> vorname;
        
        cout << "Firmenname des Kunden: ";
        cin >> firmenname;
        
        cout << "Umsatz des Kunden: ";
        cin >> umsatz;
        
        cout << "Kundennummer des Kunden: ";
        cin >> kundennr;
        
        kunde erstellterKunde;                              //muss ich ja machen, wenn ich die eingaben übergeben will, oder?
        
        erstellterKunde.setfirmenName(firmenname);
        erstellterKunde.setnachName(name);
        erstellterKunde.setvorName(vorname);
        erstellterKunde.setjahresUmsatz(umsatz);
        erstellterKunde.setkundenNummer(kundennr);
        
        loadKundeInDatabase(erstellterKunde);
    }
    

    Stimmt schon so. Es wäre geschickter einen Konstruktor für "Kunde" zu schreiben, damit du direkt ein gültiges Kundenobjekt erzeugen kannst.

    // variablen cin cout usw. was oben schon steht
    
    Kunde kunde{name, vorname, firmenname, umsatz, kundennummer};
    
    return kunde;
    


  • temi schrieb:

    Du weißt schon, dass die Datenbank nicht lange Bestand hat, weil am Ende der Routine der Gültigkeitsbereich der Variablen endet?

    void loadKundeInDatabase(const kunde& createdKunde){    /* soll eine objekt der Klasse  datenbank erstellen und
                                                             und dann mit der funktion neuerKunde den Kunden in den Vektor pushen*/
        datenbank database;
        database.neuerKunde(createdKunde);
    } // hier wird "database" wieder zerstört
    

    wäre es ratsam die Datenbank direkt im Hauptprogramm du erstellen?

    wie hier:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include "main.hpp"
    #include "classKunde.hpp"
    #include "classDatenbank.hpp"
    #include "infilestream.hpp"
    
    using namespace std;
    
    datenbank database;
    
    void loadKundeInDatabase(const kunde& createdKunde){
    
        database.neuerKunde(createdKunde);
    }
    
    int main() {
    
        return 0;
    }
    


  • kaiuwe schrieb:

    Wäre es ratsam die Datenbank direkt im Hauptprogramm du erstellen?

    Ja.

    Warum nicht so?

    int main()
    {
        Datenbank db;
        db.loadFromFile("db.dat");    
    
        // irgendwelcher Code
    
        db.neuerKunde(erstelleKunde());
    
        // noch mehr Code
    
        db.saveToFile("db.dat");
    } // hier wird "db" ungültig, aber hier endet ja auch das Programm
    

Anmelden zum Antworten