Anfängerprogramm "Wechselgeld"



  • Hallo zusammen,
    in meinem Buch ist die Aufgabe ein Programm zu schreiben, dass berechnet wieviele Scheine bzw. Münzen vom Kassier auszugeben sind.
    Die Rahmenbedingen sind:
    a) Verwendung von Schleifen
    b) effizienter Einsatz von Variablen
    c) Endpreis ist statisch
    d) Berechnung von 500€ bis 1 cent

    Hier ist mein Code:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        // Variablen definieren
        float fGeldwerte[] = {500,200,100,50,20,10,5,2,1,0.50,0.20,0.10,0.05,0.02,0.01}; 
        float fPreis = 48.87;
        float fWechselgeld = 0.0;
        float fRest = 0.0;
    
        // Benutzereingabe
        cout<<"Ihr Produkt kostet: "<<fPreis<<endl;
        cout<<"Bitte geben Sie einen Betrag ein: ";
        cin>> fWechselgeld;
        fRest = fWechselgeld - fPreis;
    
        // Schleife zur Berechnung der Scheine/Münzen
        for (int i=0; i<sizeof(fGeldwerte)/sizeof(fGeldwerte[0]); i++)
        {
          short anzahl = 0; //temporär, zählt die Scheine/Münzen
            while (fRest>=fGeldwerte[i])
            {
                fRest = fRest - fGeldwerte[i];
                anzahl++;
                cout<<"Sie erhalten: "<<anzahl<<"x "<<fGeldwerte[i]<<" Euro"<<endl;
            }
        }
        return 0;
    }
    

    Was haltet Ihr davon... passt das soweit oder wo würdet Ihr es besser machen?

    Grüße und einen schönen Sonntag
    Speer



  • Fast. Konstanten sollten auch als const deklariert sein und statt der while-Schleife solltest du eine Division verwenden.

    Zudem ist

    sizeof(fGeldwerte)/sizeof(fGeldwerte[0])
    

    hässlich. Ich würde da std::array oder range based for verwenden. Das ist aber nicht so wichtig, weil man das als Anfänger noch nicht hatte.



  • Teste mal mit

    fPreis = 0.1;
    

    und gib dann 1 (Euro) ein.



  • speer schrieb:

    Was haltet Ihr davon...

    Das "f"-Präfix ist unnötig.

    Ausserdem solltest du Variablen dann deklarieren, wenn du sie brauchst, und nicht am Anfang der Funktion. Zum Beispiel:

    float wechselgeld;
    cin >> wechselgeld;
    
    float rest = wechselgeld - preis;
    


  • Hallo zusammen,
    vielen Dank für die Antworten.

    Marthog schrieb:

    Fast. Konstanten sollten auch als const deklariert sein und statt der while-Schleife solltest du eine Division verwenden.

    Mit der Division ist mir nicht ganz klar. Dann müsste ich mich aber um "krumme" Zahlen kümmern die eine Endlichkeit haben können. Das wollte ich mir mit der While Schleife verhindern.

    Danke an DirkB, meine Wahl mit float war wohl nicht so toll. Ich verwende Codeblocks und im Debugger ist float als 0.99000001 deklariert. Daher kommt es zu einer falschen Berechnung. Ich darf also nur zwei Nachkommastellen zulassen.

    @Nexus, in meinem Buch steht, man solle sich vor der Programmierung gedanken über das Ziel, den Ablauf und die Variablen machen. Daher deklarierte ich diese immer im Vorfeld. Bin halt noch blutiger Anfänger und möchte am Anfang möglichst wenig Fehler machen. Wenn es schlechter Stil ist, dann deklariere ich die Variablen bei Bedarf.

    Danke für alle Leser und Antwort schreiber
    Speer


  • Mod

    speer schrieb:

    Danke an DirkB, meine Wahl mit float war wohl nicht so toll. Ich verwende Codeblocks und im Debugger ist float als 0.99000001 deklariert. Daher kommt es zu einer falschen Berechnung. Ich darf also nur zwei Nachkommastellen zulassen.

    Das ist die absolut falsche Schlussfolgerung. Du sagst doch selbst, was richtig gewesen wäre:

    meine Wahl mit float war wohl nicht so toll.

    Nimm für diskrete Größen, wie Geld, auch Datentypen, die dies darstellen. Zum Beispiel Integer (und dann in Cent rechnen). Ein Fließkommatyp hingegen modelliert ein Kontinuum, was denkbar schlecht zur Darstellung von Geld geeignet ist.



  • ...



  • speer schrieb:

    @Nexus, in meinem Buch steht, man solle sich vor der Programmierung gedanken über das Ziel, den Ablauf und die Variablen machen. Daher deklarierte ich diese immer im Vorfeld.

    Ebenfalls falsche Schlussfolgerung. Deklarationen lokal zu halten hat den Vorteil, dass du den entsprechenden Code gleich im Kontext hast, wo du ihn brauchst (du musst also nicht unnötig lange nach der Deklaration suchen), ausserdem verhinderst du, dass Variablen zu früh oder ausserhalb ihres Gültigkeitsbereichs verwendet werden. Schleifenvariablen wie i deklarierst du ja auch innerhalb des Schleifenkopfs und nicht am Anfang der Funktion.



  • Guten Morgen zusammen,
    wegen dem Problem habe ich mir heute einige Gedanken gemacht. Allerdings sehe ich aufgrund meines geringen C++ Kenntnisstands hier ein paar Probleme. Das beginnt bereits bei der Eingabe durch den Benutzer. Dieser müsste Vor- und Nachkomma Stellen separat eingeben. Das wiederum ist unschön.
    Als alternative könnte ich den float Datentyp nehmen, die beiden Nachkommastellen über eine Schleife auslesen und einem Datentyp int zuweisen. Somit hätte ich eine quasi "runden" Funktion geschrieben.

    Wäre es die richtige Vorgehensweise oder verirre ich mich irgendwo?

    Speer



  • Die Eingabe kannst du noch verbessern, wenn dein Programm richtig rechnet.

    Probier es mit dem einlesen von float aus. Aber eine Multiplikation mit 100 sollte reichen.
    Wenn nicht, dann nützt dir die Schleife auch nichts.
    Und nimm double statt float . Aber nur für die Eingabe!
    Rechnen tust du in Cent und als int .

    Es gibt bei der Eingabe einige Fallstricke, wenn du die Nachkommstellen einzeln betrachtest.
    Soll die 3 bei 12.3 jetzt 3 Cent oder 30 Cent bedeuten? Wie kannst du das feststellen denn 03 oder 3 ist für den Compiler gleich.



  • Arg, klar, multipliert mit 100 verschiebt das Komma. An das dachte ich überhaupt nicht!
    Wäre es möglich, anstatt im Dezimalsystem die Zahlen in Hex umzurechnen?



  • Ich würde auf keinen Fall die Zahl als float oder double einlesen, da gibts Rundungsfehler. Lese die Zahl als int ein und sage dem Nutzer er soll den Betrag in Cent eingeben. Supermarktkassen machen das auch so. Ansonsten lese einen std::string ein und wandle die Zahl vor dem Komma in ein int * 100 + die Zahl nach dem Komma um. Das ist etwas anstrengend, weil man aufpassen muss, ob überhaupt ein Komma da ist und wie viele Nachkommaziffern es gibt usw.

    Der Rechner rechnet eh immer binär. Du kannst aber Zahlen in Hex ausgeben. Warum es keine Binärvariante gibt werde ich wohl nie verstehen.


Log in to reply