C Code Korrekturlesen bitte, besonders Menüstruktur! einfacher "Taschenrechner"



  • So, ich habe den Code jetzt nochmal ganz anders aufgezogen und würde gerne wissen ob das jetzt besser ist bzw. was verbesserungswürdig ist. Vielen Dank im Voraus!

    Anmerkung: "Subtraktion" ist absolut identisch vom Aufbau etc. wie "Addition"

    #include <stdio.h>
    #include <stdlib.h>
    
    int Hauptmenue();
    int Addition();
    int Subtraktion();
    
    int main()
    {
      int status = 1 ;
    
      printf("Taschenrechner Version 2\n\n");
    
      while (status != 0)
      {
            status = Hauptmenue();
            } 
    
      system("PAUSE");	
      return 0;
    }
    
    int Hauptmenue()
    {
        char auswahl;
    
        printf("Hallo, bitte waehlen Sie eine Funktion:\n\n");
        printf("[a] - Addition\n");
        printf("[b] - Subtraktion\n\n");
        printf("[c] - Beenden\n\n");
        printf("Ihr Auswahl: ");
    
        scanf("%c",&auswahl);
        getchar();
    
        if (auswahl == 'a')
        {
                    Addition();
                    }
                    else if(auswahl == 'b')
                    {
                         Subtraktion();
                         }
                         else if (auswahl == 'c')
                         {
                              printf("Auf Wiedersehen\n\n");
                              return 0;
                              }
                              else 
                              {
                                   printf("Falsche Eingabe\n\n");
                                   return 0;
                                   }
        return 1;
    
    }
    
    int Addition()
    {
        int zahl1=0, zahl2=0;
        char weiter;
    
        printf("Bitte geben Sie die beiden Zahlen ein:\n");
    
        printf("Zahl_1 = ");
        scanf("%i",&zahl1);
        getchar();
    
        printf("\nZahl_2 = ");
        scanf("%i",&zahl2);
        getchar();
    
        printf("\nIhr Ergebnis: %i\n",zahl1+zahl2);
    
        printf("Wollen Sie weiterrechnen [j] \\ [n]: ");
        scanf("%c",&weiter);
        getchar();
    
        if (weiter == 'j' || weiter == 'J')
        {
                   return;
                   }
                   else if (weiter == 'n' || weiter == 'N')
                   {
                        printf("\nSchade, auf Wiedersehen!\n");
                        return 0;
                        }
                        else
                        {
                            printf("Falsche Eingabe!");
                            return 0;
                            }
    }
    
    int Subtraktion()
    {
        int zahl1=0, zahl2=0;
        char weiter;
    
        printf("Bitte geben Sie die beiden Zahlen ein:\n");
    
        printf("Zahl_1 = ");
        scanf("%i",&zahl1);
        getchar();
    
        printf("\nZahl_2 = ");
        scanf("%i",&zahl2);
        getchar();
    
        printf("\nIhr Ergebnis: %i\n",zahl1-zahl2);
    
        printf("Wollen Sie weiterrechnen [j] \\ [n]: ");
        scanf("%c",&weiter);
        getchar();
    
        if (weiter == 'j' || weiter == 'J')
        {
                   return;
                   }
                   else if (weiter == 'n' || weiter == 'N')
                   {
                        printf("\nSchade, auf Wiedersehen!\n");
                        return 0;
                        }
                        else
                        {
                            printf("Falsche Eingabe!");
                            return 0;
                            }
    }
    


  • Anmerkung: "Subtraktion" ist absolut identisch vom Aufbau etc. wie "Addition"

    Solche Redundanzen sind schrecklich. Nichts zweimal schreiben!

    while (status != 0)
      {
            status = Hauptmenue();
            }
    

    Das ist besser als die Rekursionen.

    Deine Einrückung ist übrigens sehr seltsam.



  • Inwiefern hab ich Redundanzen?! Oder meintest du einfach nur die Aussage von mir? Wenn du es auf den Code bezogen meinst, bitte näher erläutern 😉

    if (weiter == 'j' || weiter == 'J')
        {
                   return;
                   }
                   else if (weiter == 'n' || weiter == 'N')
                   {
                        printf("\nSchade, auf Wiedersehen!\n");
                        return 0;
                        }
                        else
                        {
                            printf("Falsche Eingabe!");
                            return 0;
                            }
    

    kann ich das so mit der If-Else if Abfrage lassen? Oder gibts da eine "schönere" Lösung...(gibts mit Sicherheit 😃 )
    wie sollte ich es besser Einrücken? Welche "Richtlinien" gibts da? Wie gesagt, ich biege mir das ganze selbst bei und hab sonst keinen zum Fragen...



  • Inwiefern hab ich Redundanzen?!

    Du hast zwei Funktionen, die sich nur durch ein '+' und ein '-' unterscheiden. Den grössten Teil des gemeinsamen Codes könnten sich die beiden teilen, das wäre kürzer und im Nachhinein leichter zu verändern.

    wie sollte ich es besser Einrücken?

    Meine IDE hat es gerade so gemacht:

    if (weiter == 'j' || weiter == 'J')
        {
            return;
        }
        else if (weiter == 'n' || weiter == 'N')
        {
            printf("\nSchade, auf Wiedersehen!\n");
            return 0;
        }
        else
        {
            printf("Falsche Eingabe!");
            return 0;
        }
    

    Das ist einer der üblichen Stile.

    Wie gesagt, ich biege mir das ganze selbst bei und hab sonst keinen zum Fragen...

    Macht nichts, hier sind genug Menschen.
    🙂



  • herzlichen Dank! 🙂
    aber das mit IF kann ich so veranstalten?



  • Die oben gezeigte Einrückung wäre in der Tat sehr zu empfehlen. Das mit den Redundanzen stimmt natürlich auch, aber hier noch ein Tipp, wie du sie am besten Auflösen kannst: Eine recht gute Faustregel ist, dass eine Funktion immer nur genau eine Sache machen soll. Wenn eine Funktion zwei Dinge macht, müssten es eigentlich zwei Funktionen sein.

    Beispiel:
    Deine Funktion Addition() macht im Grunde drei Dinge:
    1.) Werte einlesen
    2.) Die eigentliche Rechnung durchführen
    3.) Benutzer fragen, ob er weiterrechnen will

    Wenn du es schaffst, diese drei Schritte sinnvoll in einzelne Funktionen zu packen, löst sich das Redundanz-Problem zeitgleich von selbst.



  • chmbw schrieb:

    aber das mit IF kann ich so veranstalten?

    Whitespace (unsichtbare Zeichen) haben in C keinerlei Bedeutung (ausser um Token zu trennen, wie bei i = a + ++b; ). Du kannst einrücken und formatieren wie du willst.

    Mikrooptimirer schrieb:

    Wenn du es schaffst, diese drei Schritte sinnvoll in einzelne Funktionen zu packen, löst sich das Redundanz-Problem zeitgleich von selbst.

    Das klingt sinnvoll.
    🙂



  • Hallo

    noch ein kleiner Tip

    schau dir mal switch an (statt der vielen IFs)

    Mfg
    Klaus



  • herzlichen Dank für die vielen Infos!
    ich werde mich gleich mal frisch ans Werk machen und das Ergebnis dann posten 🙂



  • Hallo,

    hat zwar ein bisschen gedauert, aber jetzt hab ich meinen Code für den "Taschenrechner" nochmal überarbeitet bekommen, hoffe die Einrückungen sind jetzt besser als beim letzten Code 😉 :

    #include <stdio.h>
    #include <stdlib.h>
    
    int Hauptmenue();
    int Subtrahieren();
    int Addieren();
    int Wahl1();
    int Weiter();
    
    int main(int argc, char *argv[])
    {
      int status=1;
    
      printf("\tTaschenRechner Version 3.0\n\n");
    
      while (status != 0)
      {
            status = Hauptmenue();
      }  
    
     system("PAUSE");	
      return 0;
    }
    
    int Hauptmenue()
    {
        char wahl;
    
        printf("Hallo, welche Rechenoperation wollen Sie ausfuehren?\n\n");
        printf("****************************************************\n\n");
        printf("\t[a] - Addition\n");
        printf("\t[b] - Subtrakion\n");
        printf("**************************\n");
        printf("\t[c] - Beenden\n\n");
        printf("Ihre Wahl: ");
    
        scanf("%c",&wahl);
        getchar();
    
        switch (wahl)
        {
               case 'A' :
               case 'a' : Addieren(); 
                          break;
               case 'B' :
               case 'b' : Subtrahieren();
                          break;
               case 'C' :
               case 'c' : printf("Auf wiedersehen!\n");
                          return 0;
                          break;
               default  : printf("Falsche Eingabe!\n");
                          return;                        
        }          
    
        if ( Weiter() == 0)
        {
             return 0;
        }
    
    }                  
    
    int Weiter()
    {
        char weiter;
    
        printf("Weiterrechnen?\n\n");
        scanf("%c",&weiter);
        getchar();
    
        if (weiter == 'J' || weiter == 'j')
        {
           return 1;
        }
        else
        {
            return 0;
        }
    }
    
    int Wahl1(int *a, int *b)
    {     
        int z1=0,z2=0;
    
        printf("Bitte Zahl eingeben: \n\n");
    
        scanf("%i %i",&z1,&z2);
        getchar();
    
        *a = z1;
        *b = z2;
    }
    
    int Addieren()
    {
        int a=0, b=0;
    
        Wahl1(&a,&b);
        printf("a=%d und b=%d\n\n",a,b);
        printf("Ihr Ergebnis: %i \n\n",a + b);
    
        return 0;
    }                      
    
    int Subtrahieren()
    {
        int a=0, b=0;
    
        Wahl1(&a,&b);
        printf("a=%d und b=%d\n\n",a,b);
        printf("Ihr Ergebnis: %i \n\n",a - b);
    
        return 0;
    }
    

    Das Problem beim letzten Code waren die ganzen Rekursionen, die vielen IFs etc. und ich wollte versuchen möglichst eine Funktion pro "Funktion" bzw. Aufgabe. zu erstellen. Freu mich über jegliche Art konstruktiver Kritik!!! 🙂
    Danke im Voraus!

    Grüße



  • // statt
    scanf("%c",&wahl);
    // schreib doch einfach:
    wahl = getchar();
    
    // statt
        if (weiter == 'J' || weiter == 'j')
        {
           return 1;
        }
        else
        {
            return 0;
        }
        // schreib einfach:
        return weiter == 'J' || weiter == 'j';
        // (denk mal in Ruhe drüber nach)
    

    Wahl1() geht auch noch einfacher:

    int Wahl1(int *a, int *b)
    {    
        int z1=0,z2=0;
    
        printf("Bitte Zahl eingeben: \n\n");
    
        scanf("%i %i", a, b);
        getchar();
        // hier entweder ein 'return', oder Wahl1() muss 'void' statt 'int' sein
    }
    
    case 'c':
                   printf("Auf wiedersehen!\n");
                   return 0;
                   break;    // <-- das ist nutzlos, weil's nach dem 'return'
                             //     nicht erreicht werden kann
    

    Das Problem beim letzten Code waren die ganzen Rekursionen, die vielen IFs etc. und ich wollte versuchen möglichst eine Funktion pro "Funktion" bzw. Aufgabe. zu erstellen.

    Ich hab sofort alles verstanden. Das ist oft das wichtigste. 🙂
    Rekursion ist übrigens ein sehr nützliches Werkzeug. In C muss man zwar ein wenig vorsichtig damit sein, aber lass dir auf keinen Fall das rekursive Denken austreiben.



  • Ich ja, jetzt kannst du langsam damit anfangen, nachzusehen, was mit dem Ding passiert, wenn man völlig unsinnige Eingaben macht.
    🙂



  • Den Aufruf von Weiter() solltest du bei deiner while-Schleife machen, das ist ja auch der Ort, an dem du die Entscheidung brauchst: Dann kannst du einfach "while(Weiter())" schreiben. Addieren() und Subtrahieren() haben immer noch gleichen Code - unterscheiden sich nur im Rechenoperator. Addiere() sollte also wirklich nur so aussehen:

    int Addiere(int a, int b)
    {
        return a + b;
    }
    

    Den Code zur Ein- / Ausgabe verfrachtest du dann am besten in eine eigene Funktion Rechne() in der du auch die switch-Abfrage machst. Statt im switch Funktionen aufzurufen, kannst du natürlich die Rechnung direkt durchführen, ganz wie du willst. Rechne() könnte leicht eine relativ große Funktion werden, also überlege dir was du da vllt. wieder in eigene Funktionen packen könntest - betrachte dabei die einzelnen Schritte der Funktion und was für sich eine abgetrennte Aufgabe darstellt.



  • Mikrooptimierer schrieb:

    Addiere() sollte also wirklich nur so aussehen:

    int Addiere(int a, int b)
    {
        return a + b;
    }
    

    Das ist unter Umständen didaktischer Unsinn. Stattdessen kann man ja gleich a + b schreiben. Ausser du willst jetzt anfangen, mit Funktionszeigern herumzuwerfen. Dann wäre das aber keine schlechte Idee. Nur quält man sich üblicherweise erst durch das Kapitel "Arrays & Zeiger", Funktionszeiger kommen darin immer erst am Ende vor.
    🙂

    int Wahl1(int *a, int *b)
    {    
        // z1 und z2 sind natürlich nicht mehr nötig, wenn ich sie nicht verwende
        ...
    }
    


  • µngbd schrieb:

    Stattdessen kann man ja gleich a + b schreiben. Ausser du willst jetzt anfangen, mit Funktionszeigern herumzuwerfen.

    Dass man die Rechnung auch direkt ausführen kann, habe ich ja gesagt. Und ja, erst hatte ich tatsächlich eine Antwort verfasst, die Funktionszeiger empfohlen hat, fand es dann aber doch unnötig kompliziert, gerade für eine eigentlich einfache Sache wie den ersten Taschenrechner.



  • Hallo,

    herzlichen Dank für eure vielen Antworten, leider bin ich momentan noch in der Uni, deshalb werde ich meinen Code erst heut Abend (hoffentlich) erst überarbeitet posten können und die vielen Tipps genau durchgehen, aber ich hab mir ein paar Gedanken zum return gemacht:

    µngbd schrieb:

    // statt
        if (weiter == 'J' || weiter == 'j')
        {
           return 1;
        }
        else
        {
            return 0;
        }
        // schreib einfach:
        return weiter == 'J' || weiter == 'j';
        // (denk mal in Ruhe drüber nach)
    

    ich kann also den return-wert ohne Probleme in eine "Wahrheitsabfrage" (kann man das so nennen?!) stecken, sprich wenn die Bedingung unwahr/falsch ist wird 0 returned, sonst !=0, richtig?! somit ist der ganze Spaß doch eigentlich nur eine Kurzform der if-Schleife. Ich hoffe ich habs richtig verstanden?! Wenn ja, find ichs genial 😃 Danke!

    Grüße



  • Ich hoffe ich habs richtig verstanden?!

    Ja.
    🙂



  • sooo, nach vielem Tüfteln und überlegen hab ich hier meine aktuelle Version zustande gebracht:

    #include <stdio.h>
    #include <stdlib.h>
    
    int Hauptmenue();
    int Eingabe();
    int Addition();
    int Subtraktion();
    int Weiter();
    
    int main(int argc, char *argv[])
    {
    
      int status = 1;
    
      printf("\tTaschenRechner Version 3.0\n\n");
    
      while (status !=0)
      {
            status = Hauptmenue();
      }
    
      printf("Auf Wiedersehen\n\n");
    
      system("PAUSE");	
      return 0;
    }
    
    int Hauptmenue()
    {
        char wahl;
        int ergebnis=0;
    
        printf("Hallo, welche Rechenoperation wollen Sie ausfuehren?\n\n");
        printf("****************************************************\n\n");
        printf("\t[a] - Addition\n");
        printf("\t[b] - Subtrakion\n");
        printf("**************************\n");
        printf("\t[c] - Beenden\n\n");
        printf("Ihre Wahl: ");
    
        wahl = getchar();
        getchar();
    
        switch (wahl)
        {
               case 'a' :
               case 'A' : ergebnis = Addition();
                          printf("Ergebnis: %d\n",ergebnis);
                          break;
               case 'b' :
               case 'B' : ergebnis = Subtraktion();
                          printf("Ergebnis: %d\n",ergebnis);
                          break;
               case 'c' :
               case 'C' : return 0;
    
               default  : printf("Falsche Eingabe!\n\n");
                          return;
        } 
        return (Weiter());  
    }                  
    
    int Eingabe()
    {
        int eingabe=0;
    
        printf("Bitte Zahl eingeben: \n\n");        
        scanf("%i",&eingabe);
        getchar();
    
        return eingabe;      
    }                  
    
    int Addition()
    {
        int a=0,b=0;
    
        a=Eingabe();
        b=Eingabe();
    
        return (a+b);
    }
    
    int Subtraktion ()
    {
        int a=0,b=0;
    
        a=Eingabe();
        b=Eingabe();
    
        return (a-b);
    }
    
    int Weiter()
    {
        char weiter='j';
    
        printf("Weiterrechnen [j] // [n] ?\n\n");
        weiter = getchar();
        getchar();
    
       return (weiter == 'J' || weiter == 'j');
    }
    

    die

    getchar();
    

    musste ich bei den Eingaben drunterschreiben, weil ich sonst immer noch ein \n oder so im Puffer hatte, mir viel keine elegantere Lösung ein...Zumindest nehme ich an, dass es der Puffer ist, denn er hat öfters einfach eine Eingabe "angenommen" was halt eigentlich nur noch aus dem Puffer stammen konnte...Außerdem habe ich bewusst versucht, auf Zeiger zu verzichten und bin froh es so hinbekommen zu haben (war für mich echt eine kleine Herausforderung 😃 )

    Bin auf eure Meinungen sehr gespannt!

    Grüße



  • chmbw schrieb:

    Außerdem habe ich bewusst versucht, auf Zeiger zu verzichten

    Warum?



  • wenn ich ehrlich bin, just for fun...bzw. um mich ein bisschen intensiver mit den abfolgen der funktionen und den möglichkeiten mit diesen zu beschäftigen 😉


Anmelden zum Antworten