Bedingung vereinfachen / leere cin-Eingabe auswerten



  • #include <iostream>
    #include <cmath>
    #include <stdlib.h>
    
    using namespace std; 
    
    double calc(double zahl1, double zahl2, char rechenzeichen) 
    { 
         switch (rechenzeichen) 
         { 
             case '+': 
                 return zahl1 + zahl2; 
                 break; 
             case '-': 
                 return zahl1 - zahl2; 
                 break; 
             case '*': 
                 return zahl1 * zahl2; 
                 break; 
             case '/': 
                 return zahl1 / zahl2; 
                 break; 
    
         } 
    } 
    
    int main()
    {
    	hauptmenue:
    	cout << "Wieviele Bausteine hat die Rechnung die sie loesen wollen?" <<endl;
    	cout << endl;
    	cout << "Die Rechnung hat '2' Bausteine: 2" <<endl;
    	cout << "Die Rechnung hat '3' Bausteine: 3" <<endl;
    	cout << "Die Rechnung hat '4' Bausteine: 4" <<endl;
    	cout << endl;
    	cout << "Ich moechte keine weitere Rechnung mehr loesen: 5" <<endl;
    
    	int zahlbausteine;
    	cin >> zahlbausteine;
    
        if (zahlbausteine == 2) //Rechnung für 2 Bausteine
        {
          double zahl1, zahl2, ergebnis;
    	  char rz;
    
    	  cout << "Welche Rechenaufgabe wollen sie loesen?" <<endl;
    	  cin >> zahl1 >> rz >> zahl2; 
    
    	  ergebnis = calc(zahl1,zahl2,rz);
    
    	cout << "Die Loesung ihrer Rechenaufgabe lautet: " << ergebnis <<endl;
    	system ("pause"); system ("cls"); goto hauptmenue;
    	}	
    
    	else if (zahlbausteine ==3) //Rechnung für 3 Bausteine
    	{
    		double zahl1, zahl2, zahl3, ergebnis;
    	  char rz1, rz2;
    
    	  cout << "Welche Rechenaufgabe wollen sie loesen?" <<endl;
    	  cin >> zahl1 >> rz1 >> zahl2 >> rz2 >> zahl3; 
    
    	   if ((rz2 == '*' || rz2 == '/'))
             ergebnis = calc(zahl1, calc(zahl2, zahl3, rz2), rz1); 
           else 
             ergebnis = calc(calc(zahl1, zahl2, rz1), zahl3, rz2);
    
    	  cout << "Die Loesung ihrer Rechenaufgabe lautet: " << ergebnis <<endl;
    	  system ("pause"); system ("cls"); goto hauptmenue;
        } 
    
    	else if (zahlbausteine ==4) //Rechnung für 4 Bausteine
    	{
    		double zahl1, zahl2, zahl3, zahl4, ergebnis; 
         char rz1, rz2, rz3; 
    
         cout << "Welche Rechenaufgabe wollen sie loesen?" << endl; 
         cin >> zahl1 >> rz1 >> zahl2 >> rz2 >> zahl3 >> rz3 >> zahl4; 
    
         if ((rz2 == '*' || rz2 == '/') && (rz3 == '*' || rz3 == '/'))
             ergebnis = calc(zahl1,calc(calc(zahl2,zahl3,rz2),zahl4,rz3),rz1); 
    
         else if ((rz1 == '*' || rz1 == '/') && (rz3 =='*' || rz3 == '/'))
             ergebnis = calc(calc(zahl1,zahl2,rz1),calc(zahl3,zahl4,rz3),rz2);
    
         else if ((rz2 == '*' || rz2 == '/')) 
             ergebnis = calc(calc(zahl1, calc(zahl2, zahl3, rz2), rz1),zahl4,rz3);
    
         else if ((rz3 == '*' || rz3 == '/'))
             ergebnis = calc(zahl1,calc(zahl2,calc(zahl3,zahl4,rz3),rz2),rz1); 
    
         else 
    	     ergebnis = calc(calc(calc(zahl1,zahl2,rz1),zahl3,rz2),zahl4,rz3);
    
         cout << "Die Loesung ihrer Rechenaufgabe lautet: " << ergebnis <<endl;
         system ("pause"); system ("cls"); goto hauptmenue;
    	}
    
    	else if (zahlbausteine == 5) //Programm beenden
    	{ 
    	cout << "Das Programm wird beendet" <<endl;
    
        return 0;
    	}
    	}
    

    Ich habe dieses Programm jetzt so geschrieben, dass man zunächst eingeben muss, ob die Rechnung 2,3 oder 4 Bausteine hat und das Programm dann dementsprechend weiter geht.
    Da ich nun versuche das Programm zu vereinfach oder besser zu gestalten, bin ich auf die Idee gekommen, dass man einfach die Rechnung eingibt (egal ob 2,3 oder 4 Bausteine) und das Programm dann automatisch erkennt welche Bedingung erfüllt wird und was es tun muss. Ist das möglich?

    Ich hatte mir das so vorgestellt, dass ich z.B.

    cin >> zahl1 >> rz1 >> zahl2 >> rz2 >> zahl3 >> rz3 >> zahl4
    

    bestimmen kann, und wenn dann nichts für die jeweiligen Variablen eingegeben wird fallen sie quasi weg...



  • if ((rz2 == '*' || rz2 == '/'))
             ergebnis = calc(zahl1, calc(zahl2, zahl3, rz2), rz1); 
           else 
             ergebnis = calc(calc(zahl1, zahl2, rz1), zahl3, rz2);
    

    Das ist nicht ganz richtig, wenn rz2 punkt ist, aber rz1 auch dann muss rz1 trotzdem vor rz2 ausgewertet.
    Ich verweise mal hierauf:
    https://www.c-plusplus.net/forum/336688

    Zu deiner Frage: wenn die Rechnungen umfangreicher werden kommst du um einen Parser nicht drumherum, hier gibts dazu auch mehrere interessante Artikel (z.B. Interpreterbau)

    Übrigens: system ("pause"); system ("cls");
    ist Plattformabhängig und system + goto sollte man generell nicht verwenden.



  • Ah natürlich, dieses kleine Fehlerchen ist mir bisher noch gar nicht aufgefallen.. 🙂

    Hört sich kompliziert an, aber dann werd ich mir das mal anschauen!

    Plattformabhängig? Bedeutet?
    Ja, das mit goto habe ich bereits im Forum gelesen, aber was kann ich anstelle dessen verwenden?



  • helloworldc++ schrieb:

    Plattformabhängig? Bedeutet?

    system("cls") funktioniert z.B. nur unter Windows

    helloworldc++ schrieb:

    Ja, das mit goto habe ich bereits im Forum gelesen, aber was kann ich anstelle dessen verwenden?

    Eine (do)-while Schleife



  • Bitmapper schrieb:

    system("cls") funktioniert z.B. nur unter Windows

    Achso ok, aber das stört mich nicht.

    Bitmapper schrieb:

    Eine (do)-while Schleife

    Ist doch aber viel komplizierter..



  • Bitmapper schrieb:

    if ((rz2 == '*' || rz2 == '/'))
             ergebnis = calc(zahl1, calc(zahl2, zahl3, rz2), rz1); 
           else 
             ergebnis = calc(calc(zahl1, zahl2, rz1), zahl3, rz2);
    

    Das ist nicht ganz richtig, wenn rz2 punkt ist, aber rz1 auch dann muss rz1 trotzdem vor rz2 ausgewertet.
    Ich verweise mal hierauf:
    https://www.c-plusplus.net/forum/336688

    Ohje damit hast mich jetzt völlig aus der Bahn geworfen... 😃

    Hab ewig daran rumgemacht, bis mir aufgefallen ist, dass es völlig egal ist, in welcher Reihenfolge multipliziert wird, da immer das gleiche rauskommt. Man nennt das auch Assoziativgesetz der Multiplikation 😛



  • Ja, aber das gilt nicht für die Division.



  • Das hier ist noch nicht schlimm, aber spätestens wenn verschachtelte Schleifen benötigt werden wird's mit goto sehr hässlich.

    Hier mal eine Gegenüberstellung, es wird ein Feld auf dem Bildschirm ausgegeben:

    #include <iostream>
    
    // Gibt ein Feld auf dem Bildschirm aus
    int main()
    {
        int field[10][10] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
                              {10,11,12,13,14,15,16,17,18,19},
                              {20,21,22,23,24,25,26,27,28,29},
                              {30,31,32,33,34,35,36,37,38,39},
                              {40,41,42,43,44,45,46,47,48,49},
                              {50,51,52,53,54,55,56,57,58,59},
                              {60,61,62,63,64,65,66,67,68,69},
                              {70,71,72,73,74,75,76,77,78,79},
                              {80,81,82,83,84,85,86,87,88,89},
                              {90,91,92,93,94,95,96,97,98,99} };
        int i, j = 0;
    
        start:;
        i = 0;
        start2:;
        std::cout << field[j][i] << ' ';
        i++;
        if (i > 9)
            goto start2_ende;
        else goto start2;
    
        start2_ende:;
        std::cout << '\n';
        j++;
        if (j < 10)
            goto start;
    }
    

    vs

    #include <iostream>
    
    // Gibt ein Feld auf dem Bildschirm aus
    int main()
    {
        int field[10][10] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
                              {10,11,12,13,14,15,16,17,18,19},
                              {20,21,22,23,24,25,26,27,28,29},
                              {30,31,32,33,34,35,36,37,38,39},
                              {40,41,42,43,44,45,46,47,48,49},
                              {50,51,52,53,54,55,56,57,58,59},
                              {60,61,62,63,64,65,66,67,68,69},
                              {70,71,72,73,74,75,76,77,78,79},
                              {80,81,82,83,84,85,86,87,88,89},
                              {90,91,92,93,94,95,96,97,98,99} };
    
        for (int j = 0; j < 10; j++)
        {
            for (int i = 0; i < 10; i++)
                std::cout << field[j][i] << ' ';
            std::cout << '\n';
        }
    }
    

    Und, was meinst du ? 🙂

    helloworldc++ schrieb:

    Hab ewig daran rumgemacht, bis mir aufgefallen ist, dass es völlig egal ist, in welcher Reihenfolge multipliziert wird, da immer das gleiche rauskommt. Man nennt das auch Assoziativgesetz der Multiplikation 😛

    Bei der Multiplikation schon, aber bei: 3/3*4 ist es z.B wichtig, dass das erste zuerst ausgewertet wird.



  • Bitmapper schrieb:

    Das hier ist noch nicht schlimm, aber spätestens wenn verschachtelte Schleifen benötigt werden wird's mit goto sehr hässlich.

    Hier mal eine Gegenüberstellung, es wird ein Feld auf dem Bildschirm ausgegeben:

    Danke! 🙂

    Bitmapper schrieb:

    Und, was meinst du ? 🙂

    Bei der Multiplikation schon, aber bei: 3/3*4 ist es schon wichtig, dass das erste zuerst ausgewertet wird.

    Na dann rechne mal:
    3/3=1 14=4
    3
    4=12 12/3=4
    :p



  • Das Kommutativgesetz gilt bei der Division natürlich auch nicht.



  • 3/3*4:

    3/3 = 1
    1*4 = 4
    

    vs

    3*4 = 12
    3/12 = 0,25
    


  • Was passiert, wenn ich mich vertippe und ausversehen 5#6 eingebe?



  • Ich habe mal etwas rumgefrickelt, das hier nimmt eine Rechnung von bis zu anzahl Operatoren:

    #include <iostream>
    
    double calc(double v1, double v2, char op);
    int const anzahl = 19;
    
    int main()
    {
        double v[anzahl+1] = { 0 };
        char op[anzahl]  = { 0 };
        double ergebnis = 0;
    
        std::cout << "Welche Rechenaufgabe wollen sie loesen?" << std::endl;
    
        int i;
        std::cin >> v[0];
        for (i = 1; i < anzahl+1; i++)
        {
            if (std::cin >> op[i-1])
            {
                if (!(std::cin >> v[i]))
                {
                    std::cout << "Fehler, ein Operator zu viel!" << std::endl;
                    return 0;
                }
            }
            else
            {
                i--;
                break;
            }
        }
    
        if (i == 0)
        {
            std::cout << "Ungueltige Rechenaufgabe!" << std::endl;
            return 0;
        }
        if (i == anzahl+1) i = anzahl;
    
        for (int j = 0; j < i; j++)
        {
            if (op[j] == '*' || op[j] == '/')
            {
                v[j+1] = calc(v[j], v[j+1], op[j]);
                v[j] = 0;
    
                if (j > 0 && (op[j-1] == '-'))
                    op[j] = '-';
                else
                    op[j] = '+';
            }
        }
    
        int j;
        for (j = 0; j < i; j++)
        {
            v[j+1] = calc(v[j], v[j+1], op[j]);
        }
        ergebnis = v[j];
    
        std::cout << "Ergebnis:" << ergebnis << std::endl;
    }
    
    double calc(double v1, double v2, char op)
    {
        switch (op)
        {
            case '+':
                return v1 + v2;
                break;
            case '-':
                return v1 - v2;
                break;
            case '*':
                return v1 * v2;
                break;
            case '/':
                return v1 / v2;
                break;
            default:
                {
                    //Fehler
                }
        }
        return 0;
    }
    

    Wenn du eine Rechnung von weniger als anzahl Operatoren berechnen willst, kannst du die Schleife mit Strg+Z (unter Windows) beenden.
    Der nächste Schritt wäre dann alles dynamisch zu machen, also beliebig viele Operatoren zu akzeptieren.
    Edit: Fehler gefixt.


Anmelden zum Antworten