Mini Taschenrechner



  • Hi Helenchen,

    helenchen schrieb:

    erweiterte Grammatik implemenieren:
    Primary :
    Number
    '(' Expression ')'
    '-' Primary
    '+' Primary
    Ein Rechenausdruck wie -7*3 soll auch so eingegeben werden können

    -7+3 kann auch mit der bisherigen Version so eingegeben werden. Auf meinem Computer rechnet der das richtig, weil das System schon selber erkennt, was alles zu einer Zahl gehört.

    Jetzt wird lediglich erwartet, das an Stelle einer direkten Zahl auch ein geklammerter Ausdruck stehen kann, der eine Zahl ergibt.
    Das vorhandene Programm ist dafür schon eine gute Grundlage, muss nur noch ein wenig überarbeitet werden.
    Die Berechnung kann nicht mehr direkt in Main erfolgen, sondern muss in einer extra Funktion Rechne erfolgen, die am Ende ihr Ergebnis zurück gibt.

    Main gibt nur in einem geschützten Block die Eingabeaufforderung aus, ruft Rechne auf und gibt anschließend das von Rechne gelieferte Ergebnis auf cin aus. Anschließend folgt nur noch der catch-Bock um Fehler abzufangen.

    In Rechne wird zuerst lval ermittelt und dann in einer Endlosschleife jeweils der Operator und danach wenn der Operator nicht ';' und nicht ')' ist rval ermittelt und rval entsprechend dem Operator auf lval angewendet.
    Ist der Operator ';' oder ')' dann wird ohne weitere Rechnung mit
    return lval;
    zurückgesprungen.

    Die beiden Operanden lval und rval kannst Du nicht mehr direkt einlesen, sondern must eine Funktion GetOperand erstellen. Die muss zuerst das 1. Zeichen des Operanden einlesen.
    Wenn es eine öffnende Klammer '(' ist, ruft sie Rechne auf und gibt deren Ergebnis zurück.
    Ist das eingelesene kein '(', dann muss das Zeichen mit unget (oder eventuell pushback) in die Eingabe zurückgestellt werden und danach ganz normal der nächste Zahlen-Wert von cin gelesen und zurückgegeben werden.
    Mehr ist aus meine Sicht nicht erforderlich.

    Gruß Mümmel



  • muemmel schrieb:

    Hi Helenchen,

    Ist das eingelesene kein '(', dann muss das Zeichen mit unget (oder eventuell pushback) in die Eingabe zurückgestellt werden.

    Gruß Mümmel

    wie funktioniert das mit unget bzw push_back ...cin.unget(op)? 🙄
    habe es mit putback() gemacht ,weil push_back bei mir nicht akzeptiert wurde.

    Hier ist mein Code, es funktioniert aber total falsch.

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    
    void warte()
    {
        string x;
    
        cin.ignore();
        getline(cin, x);
        getline(cin, x);
    }
    int addiere(int a, int b)
    {
    
        int add = a + b;
        return add;
    }
    int substract(int a, int b)
    {
    
        unsigned int sub = a - b;
        return sub;
    }
    int multiply(int a, int b)
    {
    
        int mult = a * b;
        return mult;
    }
    int division(int a, int b)
    {
        int div = a / b;
        return div;
    }
    
    int rechne(signed int lval, signed rval)
    {
        char op{ ' ' };
        // signed int lval{0};
        //signed int rval{0};
        signed int result = lval;
        while (cin >> op && op != ';', ')') {
            switch (op) {
    
            case '+':
                result = addiere(lval, rval);
                break;
            case '-':
                result = substract(lval, rval);
                break;
            case '*':
                result = multiply(lval, rval);
                break;
            case '/':
                result = division(lval, rval);
                break;
            }
        }
        return result;
    }
    
    char getOperand(char op)
    {
        cin >> op;
        if (op == '(') {
            rechne;
        }
        else {
        }
        cin.putback(op);
    }
    int main()
    {
    
        string x;
        try {
    
            cout << "Rechenausdruck (mit +,-,*,/, Ende mit ;) " << endl; // wie z.B. 2*3+4;
    
            cout << "Ergebnis: " << rechne << endl;
            warte();
    
            return 0;
        }
    
        catch (const runtime_error& re) {
            cerr << "Fehler: " << re.what() << endl;
            warte();
            return -1;
        }
    }
    


  • Hi Helenchen,

    Du hast so ziemlich alles falsch gemacht und nichts beachet, was ich geschrieben habe.
    Gehen wir der Reihe nach durch.

    warte:
    hier reicht ignore und 1 getline

    Addire, subtrct...:
    die Funktionen sind eigentlich überflüssig
    die alte Version mit
    lval -= rval;
    war kürzer und besser

    getoperand:
    getoperand hat keine Parameterm sondern locale variablen int operand und char operator.
    wenn der eingelesene operator = '(' ist wird rechne() zurückgegeben
    ansonsten wird operator mit unget() zurückgestellt, Operand von cin eingelesen und zurückgegeben
    Getoperand ist vom typ int

    rechne:
    rechne hat keine parameter sondern die (bei Dir) auskommentierten variablen lval und rval.
    Zuerst wird rval mit
    rval = getoperator();
    eingelesen.
    Dann kommt eine Endlosschleife
    while ( 1 )
    oder
    for (;;)

    in der Schleife wird zuerst op von cin eingelesen

    dann wird über die switch-Anweisung op ausgewertet.
    wenn op = ')' oder op = ';' dann wird lval zurückgegeben

    bei +,-,/,* wird das ergebnis der jeweiligen funktion an lval gegeben.
    zB.

    rval =getoperator();
    lval = addiere( lval, rval );
    break;

    oder kürzer und besser

    rval =getoperator();
    lval += rval;
    break;

    So, Helenchen, nun versuchs noch mal.

    Gruß Mümmel



  • bei mir funktioniert getoperator nicht wenn ich schreibe:

    case '+': rval = getoperator(); lval += rval ;  break;
    

    auch wenn ich es vordefiniere 😞



  • Hi Helenchen,

    helenchen schrieb:

    bei mir funktioniert getoperator nicht wenn ich schreibe:

    case '+': rval = getoperator(); lval += rval ;  break;
    

    auch wenn ich es vordefiniere 😞

    und wie sieht getoperator bei Dir aus?

    Gruß Mümmel



  • Hi Helenchen,

    Wie sieht Dein gesamter Quelltext jetzt aus?

    Gruß Mümmel



  • muemmel schrieb:

    Hi Helenchen,

    Wie sieht Dein gesamter Quelltext jetzt aus?

    Gruß Mümmel

    Katastrophal, muss noch da weiterarbeiten.
    Schicke ich dir, heute Abend noch.



  • muemmel schrieb:

    Hi Helenchen,

    Wie sieht Dein gesamter Quelltext jetzt aus?

    Gruß Mümmel

    Bitte nicht Ohnmacht fallen, so sieht mein Code aus :

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    
    void warte()
    {
        string x;
    
        cin.ignore();
        getline(cin, x);
    }
    
    int rechne()
    {
        char op{ ' ' };
        signed int lval{ 0 };
        signed int rval{ 0 };
    
        int getoperator()
        {
            rval = getoperator();
            return rval;
        }
    
        while (cin >> op && op != ';', ')') {
            switch (op) {
    
            case '+':
                rval = getoperator;
                lval += rval;
                break;
            case '-':
                rval = getoperator;
                lval -= rval;
                break;
            case '*':
                rval = getoperator;
                lval *= rval;
                break;
            case '/':
                rval = getoperator;
                lval /= rval;
                break;
            }
        }
        return lval;
    }
    }
    
    int getoperand(int operand, char op)
    {
        cin >> op;
        if (op == '(') {
            rechne();
        }
        else {
            int operand;
            cin.unget();
            cin >> operand;
        }
        cin >> operand;
        return operand;
    }
    
    int main()
    {
    
        try {
    
            cout << "Rechenausdruck (mit +,-,*,/, Ende mit ;) " << endl; // wie z.B. 2*3+4;
    
            cout << "Ergebnis: " << rechne << endl;
            warte();
    
            return 0;
        }
    
        catch (const runtime_error& re) {
            cerr << "Fehler: " << re.what() << endl;
            warte();
            return -1;
        }
    }
    


  • Sind die Fehler in der Signatur Absicht?



  • helenchen ist sogar zu faul, um den Code kurz zu kompilieren, bevor sie ihn hier hinkotzt. Mal ganz davon abgesehen, dass sie die Ratschläge ALLER konstant ignoriert und stattdessen lieber selbst ein bisschen erfolglos 'rumfrickelt.
    Ferner ist auch ihre Rechtschreibung und Zeichensetzung auf dem Niveau eines Grundschülers und die Kommunikation allgemein wäre mit einer Wand geradeso gut; geht auf die Posts ihrer eifrigen Helfer kaum ein und drei vollständige Sätze sind dann auch schon die Ausnahme.
    Aber keine Bange, gleich kommt mümmel wieder mit einem weiteren zwei Seiten langen Walkthough, wovon helenchen wieder gar nichts umsetzt. Das unterstützt sie nur weiter in ihrem parasitären Verhaltensmuster.
    Es schmerzt nur schon beim Zusehen. 🙄



  • Kenner der Parasiten schrieb:

    [...]

    Amen.



  • Kenner der Parasiten schrieb:

    helenchen ist sogar zu faul, um den Code kurz zu kompilieren, bevor sie ihn hier hinkotzt. Mal ganz davon abgesehen, dass sie die Ratschläge ALLER konstant ignoriert und stattdessen lieber selbst ein bisschen erfolglos 'rumfrickelt.

    Nur weil ich fehlerhaften Code poste heißt es nicht ,dass ich faul bin.
    Ja ich mache zu viele Fehler auch in Rechtschreibung und werde noch viele machen :D. Ich bin ein Anfänger, deswegen bin ich hier um das Programmieren in C++ richtig zu lernen.
    PS: Kenner der Tatsachen oder Parasiten oder wie du dich morgen auf immer nennst, erzähl mal was über dich. Du scheinst dich Woll mit der Programmierung gut auszukennen, oder bist du nur da um über die Anfänger lustig zu machen?



  • Es geht nicht darum sich ueber Anfaenger lustig zu machen, hat er auch nicht. Er hat lediglich mal seine die Gedanken vieler zusammengefasst.

    helenchen schrieb:

    Nur weil ich fehlerhaften Code poste heißt es nicht ,dass ich faul bin.

    Doch, genau das heisst es. Denn du weisst genau, dass muemmel gleich wieder vorbeikommt und dir das Flaeschchen gibt. Haettest du
    deinen code einfach mal selbst durch den compiler gejagt, haette er dir naemlich** tmp.cpp:21:5: error: function definition is not allowed here **gesagt.

    helenchen schrieb:

    [...] deswegen bin ich hier um das Programmieren in C++ richtig zu lernen.

    Das halte ich ebenfalls fuer ein starkes Geruecht, waere dem so, wuerdest du auch mal was davon umsetzten was muemmel dir zuwirft.
    Sobald ein bisschen eigeninitiative deinerseits notwendig ist, passiert nichts; und muemmel posted dir den kompletten code.



  • habe alles ausgegoogelt verstehe nicht warum Compiler mit getOperator Funktion Probleme hat . Er sagt:

    main.cpp:48:16: error: invalid conversion from 'int (*)()' to 'int' [-fpermissive
    

    ]

    int rechne()
    {
        char op{ ' ' };
        signed int lval{ 0 };
        signed int rval{ 0 };
        int getOperator();
    
        while (cin >> op && op != ';', ')') {
            switch (op) {
    
            case '+':
                rval = getOperator;
                lval += rval;
                break;
            case '-':
                rval = getOperator;
                lval -= rval;
                break;
            case '*':
                rval = getOperator;
                lval *= rval;
                break;
            case '/':
                rval = getOperator;
                lval /= rval;
                break;
            }
            return lval;
        }
    }
    

    PS: Keinen fertigen Code posten sondern nur Ratschlag 😉
    bin übrigens ne Russin aus Kasachstan, deswegen Grammatikprobleme 🙄



  • Hi Helenchen,

    eigentlich hast Du meine Hinweise nicht beachtet, sonst würde Dein Programm jetzt laufen.
    Daher noch mal die Fehler zusammengefasst:

    warte ist jetzt OK.

    Main müsste auch OK sein.

    Getoperator:
    Die Funktion ist überflüssig, und Du kannst auch nicht in einer Funktion eine weitere definieren.

    Getoperand:
    Keine Parameter für Getoperand nehmen. die beiden Variablen am Anfang der Funktion definieren.
    wenn of ='(' dann return rechne();
    sonst operand von cin einlesen und mit return zurückgeben.
    Nach dem else-Zweig nichts weiter

    rechne:
    int Getoperator(){...} muss weg.
    die schleife als reine Endlosschleife gestalten while( 1 ) oder for( ; ; )
    in der while-Schleife zuerst op von cin einlesen.
    in der switch-Auswahl 6 Fälle:
    neben +, -, * und / noch
    ';' und ')', da nur einfach return lval;
    Nach switch nichts mehr.

    und benutze endlich mal das von mir vorgeschlagene Formatiertool oder formatiere selbst von Hand richtig. Du kannst nicht erwarten, dass ich mir sonen unformatierten Müll reinziehe. Wenn Du in Zukunft nicht formatierst werde ich mir das nicht mehr angucken.

    Gruß Mümmel



  • Hi alle anderen,

    nein, ich liefere nicht gleich wieder einen fertigen Quelltext.
    Am Anfang war das erst mal notwendig, damit Helenchen begreift, was ich meine.
    Aber ich will mir nicht nur selbst auf die Schulter klopfen, sondern Helenchen helfen, dass sie die nächsten Prüfungen hinbekommt. Da kann ich nicht nur fertige Arbeit rüberreichen. Für den Anfang hab ich ihr eine Vorlage gemacht, und nun muss sie das selber hinbekommen, Ich meckere da nur was noch falsch ist und gebe Hinweise wie es (aus meiner Sicht) sein müsste.
    Spätestens wenn es über den Rand den ich noch im Kopf habe hinaus geht, kann ich ihr sowieso nicht mehr allzu viel helfen. Also muss sie bis dahin so weit sein, dass sie sich dann selber helfen kann. Aber dabei kann ich ihr nur helfen. Den entscheidenden Schritt muss sie selber tun. Ich hoffe, wenn ich meine Grenze erreicht habe (bin seit über 10 Jahren überwiegend Delphi-Programmierer), werden sich hoffentlich andere finden die dann mit mehr Wissen weiterhelfen. Aber auch dazu muss Helenchen noch selber was beitragen.
    Da ich schon vorher wusste, dass sie nicht aus Deutschland ist hab ich über das eine oder andere hinweggesehen. Das hätten aber auch andere am Stil ihres Deutsch erkennen können.

    Gruß Mümmel



  • Meine Lösung mit code formater formatiert , bisschen selbst schön nachgerückt.
    Hoffe es geht, wenn nicht bescheid sagen 😉 .

    Das Programm selbst gibt 1 ständig aus.
    Ich nehme an etwas mit der Funktion Rechne stimmt nicht bzw ich habe etwas missverstanden. 😞
    Suche morgen wieder nach dem Fehler.

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    
    void warte() {
    
        string x;
    
        cin.ignore();
        getline(cin, x);
    
    }
    
    int rechne() {
    
        char op{ ' ' };
        signed int lval{ 0 };
        signed int rval{ 0 };
    
        while (cin >> op && op != ';', ')') {
    
              switch (op) {
    
              case '+':
    
                lval += rval;
    
                break;
    
              case '-':
    
                lval -= rval;
    
                break;
    
             case '*':
    
                lval *= rval;
    
                break;
    
             case '/':
    
                lval /= rval;
    
                break;
    
            case ';': break;
    
            case ')': break;
    
                return lval;
    
            }
        }
    }
    
    int getoperand() {
    
           int operand;
           char op;
           cin >> op;
           if (op == '(')
    
     {
           rechne();
    
        }  else {
    
           int operand;
           cin.unget();
           cin >> operand;
    
        }
    
           return operand;
    
    }
    
    int main()
    
    {
    
        try {
    
            while (1) {
    
                cout << "Rechenausdruck (mit +,-,*,/, Ende mit ;) " << endl; // wie z.B. 2*3+4;
    
                cout << "Ergebnis: " << rechne << endl;
    
                warte();
    
            }
    
               return 0;
    
        }
    
          catch (const runtime_error& re) {
    
              cerr << "Fehler: " << re.what() << endl;
              warte();
    
              return -1;
        }
    }
    


  • Hi Helenchen,

    Du hast keinen meiner Tips berücksichtigt. Ich hatte geschrieben, was Du wo ändern sollst.
    Und formatieren mit der Einstellung file damit die öffnende Klammer vorne steht.

    Gruß Mümmel



  • Hi Helenchen,

    wenn Du meine Hinweise von 23:28 Uhr auf Deine Version von 17:44 Uhr anwendest, dann läuft das Programm.
    Noch ein Hinweis: in main nicht rechne sondern rechne( ) nach cout ausgeben

    Gruß Mümmel



  • Hier ist mein Code mit File formatiert und per Hand, hoffe es gefällt ihnen 😃

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    
    void warte()
    
    {
        string x;
    
        cin.ignore();
        getline(cin, x);
    }
    
    int rechne()
    
    {
    
        char op{ ' ' };
        signed int lval{ 0 };
        signed int rval{ 0 };
    
        while (1)
        {
            while (cin >> op)
            {
                switch (op)
                {
    
                    case '+':
    
                        lval += rval;
                        break;
    
                    case '-':
    
                        lval -= rval;
                        break;
    
                    case '*':
    
                        lval *= rval;
                        break;
    
                    case '/':
    
                        lval /= rval;
                        break;
    
                    case ';':
                        return lval;
                        break;
    
                    case ')':
                        return lval;
                        break;
                }
            }
        }
    }
    
    int getoperand(int operand, char op)
    
    {
    
        cin >> op;
        if (op == '(')
    
        {
    
            rechne();
    
        }
        else
        {
    
            cin.unget();
            cin >> operand;
    
            return operand;
        }
    
        return operand;
    }
    
    int main()
    
    {
    
        try
    
        {
    
            while (1)
    
            {
                cout << "Rechenausdruck (mit +,-,*,/, Ende mit ;) " << endl; // wie z.B. 2*3+4;
    
                cout << "Ergebnis: " << rechne() << endl;
                warte();
    
            }
    
            return 0;
        }
    
        catch (const runtime_error& re)
    
        {
    
            cerr << "Fehler: " << re.what() << endl;
            warte();
    
            return -1;
    
        }
    }
    

    leider das Ergebnis ist nicht korrekt, liefert nach Eingabe immer Null.
    Nach Ursache habe ich gesucht , habe versucht mich an die Hinweise zu halten.
    Irgendwo vermute im rechne Funktion in switch case Block ist mir ein Fehler unterlaufen. Letzen beiden cases mit zwei mal return lval gefallen mir nicht.

    Kann es vielleicht sein, das die beiden returns sich gegenseitig auslöschen? 😕


Anmelden zum Antworten