Lagerverwaltung erstellen | Bin Ich auf dem Holzweg?



  • Hallo liebe Cplusplus Gemeinde,

    Erstmal ein Lob an diese geballte Wissenssammlung hier, Ich habe schon die ein oder andere Hilfreiche Sache hier gefunden.

    Ich belege derzeit über ILS einen C++ Kurs und mir wurde Folgende Aufgabe gestellt:

    Erstellen Sie eine Lagerverwaltung, die folgende Daten für Kisten speichern kann:
    • eine eindeutige Nummer zur Identifikation jeder einzelnen Kiste,
    • die Breite, Länge und Höhe jeder Kiste sowie
    • das Volumen der Kiste.
    Die Nummer zur Identifikation der Kiste können Sie nach einem beliebigen Schema selbst vergeben. Stellen Sie aber durch geeignete Verfahren sicher, dass bei der Eingabe einer neuen Kiste nicht eine bereits vergebene Nummer benutzt wird.
    Das Volumen der Kiste soll automatisch vom Programm anhand der Breite, Länge und Höhe berechnet werden können.
    Das Programm soll maximal Daten von 50 Kisten verwalten können und folgende Funktionen anbieten:
    • Eingabe einer neuen Kiste,
    • Löschen der Daten einer vorhandenen Kiste,
    • Ändern der Daten einer vorhandenen Kiste,
    • Anzeigen der Daten einer vorhandenen Kiste und
    • eine Listenfunktion, die die Daten aller vorhandenen Kisten anzeigt.
    Beim Löschen, Ändern und Anzeigen soll der Zugriff auf die Daten der Kiste über die Nummer der Kiste erfolgen.
    Für die Umsetzung gelten folgende Vorgaben:
    • Speichern Sie die Daten in einer Struktur und legen Sie ein Feld in der erforderlichen Größe für diese Struktur an. Erstellen Sie dieses Feld lokal in der Funktion main(). Verwenden Sie kein globales Feld.
    • Stellen Sie sicher, dass beim Zugriff auf die Daten der Kisten die Feldgrenzen nicht verlassen werden können.
    • Erstellen Sie für das Eingeben, Löschen, Ändern, Anzeigen und Auflisten jeweils eigene Funktionen.

    • Sorgen Sie dafür, dass beim Löschen, Ändern, Anzeigen und Auflisten nur auf Einträge zugegriffen werden kann, für die bereits Daten erfasst wurden. Dazu können Sie zum Beispiel beim Start des Programms die Nummer jeder Kiste zunächst auf den Wert 0 setzen und beim Zugriff überprüfen, ob die Nummer der Kiste noch den Wert 0 hat. Um eine Kiste zu löschen, reicht es dann, die Nummer der Kiste wieder auf den Wert 0 zu setzen.
    • Erstellen Sie in der Funktion main() ein Auswahlmenü für den Zugriff auf die einzelnen Funktionen der Lagerverwaltung.

    So meine Frage ist nun ob Ich im groben schon mal in der richtigen Richtung unterwegs bin. Da es mir etwas schwer fällt die einzelnen Elemente zu Verknüpfen.(Ich weiß es sind noch Fehler drin aber Ich bin noch nicht ganz Fertig)

    Der Code bisher:

    /*#############################################
    Einsendeaufgabe 4
    #############################################*/
    
    #include <iostream>
    
    using namespace std;
    
    struct kisten {
    
        int lagernummer;
        int breite;
        int laenge;
        int hoehe;
        int volWert;
        bool aktiv;
    };
    
    //Einlesefunktion
    kisten einlesen(kisten werte[50]) {
    
        cout << "Geben Sie die Kisten Identifikations Nummer ein: " << endl;
        cin >> werte[50].lagernummer;
    
        if (werte[50].lagernummer <= 50) {
    
            cout << "Bitte geben Sie die Breite der " << werte[50].lagernummer << " Kiste in m an.";
            cin >> werte[50].breite;
    
            cout << "Bitte geben Sie die Laenge der " << werte[50].lagernummer << " Kiste in m an.";
            cin >> werte[50].laenge;
    
            cout << "Bitte geben Sie die Hoehe der " << werte[50].lagernummer << " Kiste in m an.";
            cin >> werte[50].hoehe;
    
            werte[50].aktiv = true;
            //Volumen berechnung
            werte[50].volWert = werte[50].breite * werte[50].laenge * werte.hoehe;
    
        }
        else {
            cout << "Sie haben die Anzehl der Kisten Überschritten." << endl;
        }
        return werte[50];
    }
    
    //Löschen funktion
    kisten loeschen(kisten werte[50]) {
    
        cout << "Bitte geben Sie die Nummer der Kiste an: " << endl;
        cin >> werte[50].lagernummer;
    
        if (werte[50].lagernummer != 0 && werte[50].aktiv != false)
        {
            werte[50].lagernummer = 0;
            werte[50].hoehe = 0;
            werte[50].laenge = 0;
            werte[50].breite = 0;
            werte[50].volWert = 0;
            werte[50].aktiv = false;
    
        }
        else {
            cout << "Die angegebene Kiste existiert nicht!" << endl;
        }
        return werte[50];
    }
    //Aendern Funktion
    kisten aendern(kisten werte[50]) {
        cout << "Bitte geben Sie die Nummer der Kiste ein die Sie aendern wollen: " << endl;
        cin >> werte[50].lagernummer;
    
        if (werte[50].lagernummer != 0 && werte[50].aktiv != false) {
            kisten loeschen();
            kisten einlesen();
        }
        else {
            cout << "Die angegebene Kiste existiert nicht." << endl;
        }
    
        return werte[50];
    }
    //Anzeigen Funktion
    kisten anzeigen(kisten werte[50]) {
        cout << "Bitte geben Sie die Nummer der Kiste ein die Sie anzeigen wollen: " << endl;
        cin >> werte[50].lagernummer;
    
        if (werte[50].lagernummer != 0 && werte[50].aktiv != false) {
    
            cout << "Kiste Nr.: " << werte[50].lagernummer << endl;
            cout << "Hoehe der Kiste: " << werte[50].hoehe << endl;
            cout << "Laenge der Kiste: " << werte[50].laenge << endl;
            cout << "Breite der Kiste: " << werte[50].breite << endl;
            cout << "Volumen der Kiste: " << werte[50].volWert << endl;
        }
        else {
            cout << "Die angegebene Kiste existiert nicht." << endl;
        }
    
        return werte[50];
    }
    
    //Auflistungsfunktion für Alle werte
    kisten liste(kisten werte[50]) {
        for (int index = 0; index < werte[50].lagernummer; index++)
        {
            cout << "Kiste Nr.: " << werte[50].lagernummer << endl;
            cout << "Hoehe der Kiste: " << werte[50].hoehe << endl;
            cout << "Laenge der Kiste: " << werte[50].laenge << endl;
            cout << "Breite der Kiste: " << werte[50].breite << endl;
            cout << "Volumen der Kiste: " << werte[50].volWert << endl;
    
        }
        return werte[50];
    }
    
    int main()
    {
        int menuewahl;
        kisten werte[50];
    
        do {
    
            cout << "---LAGERVERWALTUNG---" << endl;
            cout << "Was moechten Sie tun? Bitte waehlen Sie aus.";
            cout << endl;
            cout << "[1] - Eingabe - " << endl;
            cout << "[2] - Loeschen - " << endl;
            cout << "[3] - Aendern - " << endl;
            cout << "[4] - Anzeigen - " << endl;
            cout << "[5] - Liste - " << endl;
            cout << "[6] - Beenden - " << endl;
            cin >> menuewahl;
    
            switch (menuewahl) {
    
            case '1':
                einlesen();
                break;
            case '2':
                loeschen();
                break;
            case '3':
                aendern();
                break;
            case '4':
                anzeigen();
                break;
            case '5':
                liste();
                break;
            case '6':
                cout << "Das Menue wird Beendet."
                    exit(0);
                break;
    
            }
        } while (menuewahl != 6);
    
        return 0;
    }
    

    Und noch die Nächste Frage:
    Bei der Volumenberechnung in Zeile 40 wird mir vom Compiler folgender Fehler angezeigt: Fehler:request for member 'hoehe' in 'werte', which is of pointer type 'kisten*' (maybe you meant to use '->' ?)

    Ich verstehe dabei nicht was er bemängelt. Ich habe doch keinen Zeiger bzw. Zeiger-Typen im Code.
    Muss Ich die Volumenberechnung als Separate Funktion erstellen und Sie in der Funktion "einlesen()" wieder Aufrufen?

    //Volumen berechnung
     werte[50].volWert = werte[50].breite * werte[50].laenge * werte.hoehe;
    


  • Schau dir mal den Unterschied an, wie du an die 3 verschiedenen Werte eines Elements kommst. Die müssten doch eigentlich alle gleich aussehen, nüch? 😉

    werte[50].breite * werte[50].laenge * werte.hoehe;
    

    Ohne jetzt irgend jemandem ans Bein pinkeln zu wollen, aber dieser ILS Kurs schein ein wenig veraltet. Ich würde dir empfehlen, statt "normalen" arrays auf std::array zurück zu greifen. Das würde dir auch ein wenig aussagekräftigere Meldungen verschaffen. In deinem Fall ist "werte" vom Prinzip her ein Zeiger auf das erste Element des arrays, daher diese Compiler Meldung. Du machst es schon einmal richtig, und nimmst nicht blind den -> operator, sondern machst dir Gedanken. Daher schonmal ein Lob von mir. Dennoch wäre std::array geeigneter.
    Generell hast du einige out-of-bound access Stellen. Wenn dein Array 50 Elemente hat, kannst du nicht auf den Index 50 zugreifen (was prinzipiell das 51. Element wäre).



  • Ich danke dir.
    Das mit den Arrays habe Ich schon in einem Buch mit dem Ich nebenbei noch Arbeite auch schon gelesen wie auch in Tutorials gesehen. Aber es ist leider so Gefordert aber danke für den Tipp.

    Und die out-of-bound access Stellen werde Ich auch noch mal Überarbeiten.



  • Du solltest dir übrigens dringend anschauen, wie man ein raw-array per Referenz übergibt, oder dir eine andere Variante des Übergebens aussuchen (z.B. Zeiger auf erstes Element und eine Size). So wie du es machst, kopierst du ständig alles, was unnötig ist.

    Außerdem solltest du dein struct im Singular benennen und nicht im Plural.



  • Ich darf aber bis hier hin leider nur mit dem Arbeiten was bis dato gelernt wurde. 😞
    Pointer, Referenzen und co kommen erst im Nächsten Heft.



  • anti-freak schrieb:

    Ohne jetzt irgend jemandem ans Bein pinkeln zu wollen,

    Mittlerweile denke ich, diese Einstellung ist falsch.

    anti-freak schrieb:

    aber dieser ILS Kurs schein ein wenig veraltet.

    Dies ist offensichtlich ein Kurs "C, dann C++" und damit völliger Schrott. Siehe auch CppCon 2015: Kate Gregory “Stop Teaching C"



  • struct kisten
    

    Die Struktur beschreibt eine Kiste. Das sollte der Name auch ausdrücken.

    kisten einlesen(kisten werte[50]) {
    

    Warum liefert die Funktion etwas zurück?
    Warum ist das eine Kiste?
    Der Compiler nimmt die 50 zwar so an, so funktionieren Arrays als Funktionsparameter aber nicht. Verwende kisten werte[] oder kisten* werte.

    Es gibt keine Magie beim Arrayzugriff, d.h. werte[50] zaubert dir nicht das passende Element herbei. Du wirst schon Schleifen und Index verwenden müssen.



  • anti-freak schrieb:

    So wie du es machst, kopierst du ständig alles,

    Äh, nein, da wird nichts kopiert.



  • Ich habe das Gefühl das in eurem Kurs C++ Programmierung im Stile der 90er Jahre gelehrt wird.



  • manni66 schrieb:

    anti-freak schrieb:

    So wie du es machst, kopierst du ständig alles,

    Äh, nein, da wird nichts kopiert.

    Ach, nein?

    kisten einlesen(kisten werte[50]);
    kisten loeschen(kisten werte[50]);
    kisten aendern(kisten werte[50]);
    kisten anzeigen(kisten werte[50]);
    kisten liste(kisten werte[50]);
    

    Muss ich mich verguckt haben. Wenn er natürlich im Aufruf keine Parameter übergibt, wird auch nix kopiert, weil es schlicht nicht compiled...



  • anti-freak schrieb:

    manni66 schrieb:

    anti-freak schrieb:

    So wie du es machst, kopierst du ständig alles,

    Äh, nein, da wird nichts kopiert.

    Ach, nein?

    Nein.



  • manni66 schrieb:

    anti-freak schrieb:

    manni66 schrieb:

    anti-freak schrieb:

    So wie du es machst, kopierst du ständig alles,

    Äh, nein, da wird nichts kopiert.

    Ach, nein?

    Nein.

    Du hast Recht, da hab ich mich geirrt. Danke für deine ausführliche Richtigstellung! Immer wieder eine Freude mit dir zu kommunizieren 😉
    Jedenfalls 1 Grund mehr auf meiner Liste, warum ich raw arrays meide.


Anmelden zum Antworten