while schleife problem - anfänger



  • Hallo,
    ich hab seit kurzer Zeit mit C angefangen und würde gerne mir helfen lassen.
    Hab ein progrämmchen geschrieben zur kreisberechnung, jedoch hab ich ein problem mit meiner while schleife. Alles wir wiederholt jedoch in doppelter ausgabe, naja guckt es euch selber an...
    hoff ihr könnt mir erklären was ich falsch mache.
    Hat jemand villeicht sogar Anfänger tipps&tricks?

    #include <stdio.h>
    #include <math.h>
    
    int main(){
    
        double r, D, U, A, pi, ende;
        char auswahl;
        pi = 3.14159;
        ende = 0;
    
        while (!ende)
            {
    
        printf(" Moechten sie etwas berechnen oder das Programm beenden?\n");
        printf("Radius - r\n");
        printf("Durchmesser - d\n");
        printf("Umfang - u\n");
        printf("Flaecheninhalt - a\n");
        printf("Programm beenden - e\n\n");
        printf("Ihre Wahl:");
        scanf("%c", &auswahl);
        printf("\n");
    
        switch (auswahl)
                {
                    case 'r':
                        printf("Radius: ");
                        scanf("%lf", &r);
                        printf("Durchmesser: %.2lf\n", r*2 );
                        printf("Umfang: %.2lf\n", pi*2*r);
                        printf("Flaecheninhalt: %.2lf\n", pi*r*r);
                        break;
    
                    case 'd':
                        printf("Durchmesser: ");
                        scanf("%lf", &D);
                        printf("Radius: %.2lf\n", D / 2);
                        printf("Umfang: %.2lf\n", pi * D);
                        printf("Flaechenumfang: %.2lf\n",pi * (D/2 * D/2));
                        break;
    
                    case 'u' :
                        printf("Umfang:");
                        scanf("%lf", &U);
                        printf("Radius: %.2lf\n",(U/pi)/2);
                        printf("Durchmesser: %.2lf\n", U/pi);
                        printf("Flaechenumfang: %.2lf\n", ((U/pi)/2)*((U/pi)/2)*pi);
                        break;
    
                    case 'a' :
                        printf("Flaecheninhalt:");
                        scanf("%lf", &A);
                        printf("Radius: %.2lf\n", sqrt (A/pi));
                        printf("Durchmesser: %.2lf\n", sqrt (A/pi)*2);
                        printf("Umfang: &.2lf\n", sqrt (A/pi)*2*pi);
                        break;
    
                    case 'e' :
                        printf("Das Programm wird beendet.\n\n");
                        ende = 1;
                        break;
                }
    
            }
    return 0;
    }
    


  • Eingabepuffer vor erneutem Einleseversuch leeren.


  • Mod

    Swordfish schrieb:

    Eingabepuffer vor erneutem Einleseversuch leeren.

    Was ist ein Eingabepuffer und wie leert man ihn?



  • scanf liest nur die Zeichen ein, die auch zum Formatspecifier passen.
    Bei den meisten Specifiern werden führenden Whitespace (Leerzeichen, Zeilenvorschub, Tabulatoren) überlesen.

    Wie sieht das jetzte bei dir aus:

    Du gibst ein Zeichen (r, d, u, a, e) ein und schließt die Eingabe mit der Entertaste (\n) ab.
    scanf("%c", &auswahl) ; liest den Buchstaben ein, das '\n' bleibt im Eingabestrom stehen.
    Dann gibst du z.B. den Radius ein, und schließt auch diese Eingabe mit der Entertaste ab.
    scanf überliest das '\n' von der Zeicheneingabe und liest den Radius ein.
    Bei einem Zeichen, das nicht mehr zu einem double-Wert passt, wird die Eingabe abgebrochen. Das Zeichen bleibt im Eingabestrom stehen.

    Dann kommst du wieder (durch das while) zu dem scanf("%c", &auswahl);
    Jetzt wird das Zeichen eingelesen das direkt hinter dem double-Wert steht.
    Dies ist meist das '\n' von der Entertaste.

    Dazu gibt es bei switch kein case, also wird wieder die Aufforderung zur Eingabe ausgegeben.



  • Hallo Leute,
    auch ich bin noch Anfänger in C und habe vielleicht ein ähnliches Problem.
    Bei mir wird, nachdem eine Eingabe erfolgt, (außer bei 'e'), der Textteil unter "while" immer doppelt ausgegeben.
    Ich habe keinen Plan woran das liegt.
    Vielleicht wisst ihr ja bescheid? 😉

    /* Kreisrechner v0.1 */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main() {
    
        // r = radius, c = cercumference, a = area
        float r, c, a;
        char auswahl;
    
        printf("Mein kleiner Kreisrechner\n");
    
        while (auswahl != 'e' || auswahl == 'r' || auswahl == 'u' || auswahl == 'f')
        {
            printf("\nWas ist gegeben? Radius 'r', Umfang 'u' oder Flaeche 'f'?");
            printf("\nZum Beenden bitte (e) waehlen.");
            printf("\nIhre Auswahl: ");
                scanf("%c", &auswahl);
    
            if (auswahl == 'r') {
                printf("\nBitte geben Sie den Radius des Kreises ein.");
                printf("\nRadius: ");
                    scanf("%f", &r);
    
                    c = 2 * M_PI * r;
                    a = M_PI * r * r;
    
                printf("\nDer Umfang betraegt: %f", c);
                printf("\nDer Flaecheninhalt betraegt: %f", a);
            }
            else if (auswahl == 'u') {
    
                printf("\nBitte geben Sie den Umfang des Kreises ein.");
                printf("\nUmfang: ");
                    scanf("%f", &c);
    
                   r = c / (2 * M_PI);
                   a = M_PI * r * r;
    
                printf("\nDer Radius betraegt: %f", r);
                printf("\nDer Flaecheninhalt betraegt: %f", a);
            }
            else if (auswahl == 'f') {
    
                printf("\nBitte geben Sie den Flaecheninhalt des Kreises ein.");
                printf("\nFlaeche: ");
                    scanf("%f", &a);
    
                    r = sqrt (a / M_PI);
                    c = 2 * M_PI * r;
    
                printf("\nDer Radius betraegt: %f", r);
                printf("\nDer Umfang betraegt: %f", c);
            }
        }
        if (auswahl == 'e') {
    
                printf("Das Programm wird nun beendet.");
                printf("\nBitte mit 'ENTER' bestaetigen.\n");
        }
        else {
                printf("Ihre Eingabe ist ungueltig.\n");
                printf("Bitte versuchen Sie es erneut.\n");
             }
    
        return 0;
    }
    

    PS: bin über jede helfende Kritik erfreut.

    EDIT: ich nutze Windows XP und CodeBlocks

    LG Patric


  • Mod

    Mach ein Leerzeichen vor das %c in Zeile 20. Sonst wird auch der Whitespace der die Buchstaben trennt mit eingelesen und du bekommst einen Durchlauf für den Whitespace und einen für den folgenden Buchstaben.

    Tipps:
    - Der Text passt teilweise nicht zu dem, was passiert. Zum Beispiel der in Zeile 65.
    Und das übliche:
    - Einheitlichere Einrückung.
    - Aussagekräftigere Variablennamen. Warum nennst du dir Variablen nicht auch radius, circumference und area?

    Ansonsten recht ok. Hier kommt auf dem Niveau gewöhnlicherweise wesentlich schlimmeres. Dein Programm sieht aus wie C, die Fehler sind nur stilistisch.



  • Hi,

    deine Variable auswahl ist nicht initialisiert,
    darum ist in ihr irgendein (zufälliger) Wert gespeichert, der könnte auch 'e' sein, die möglichen Folgen kannst du dir selbst ausmalen.

    Die while Schleife wird durchlaufen, wenn auswahl != 'e' ist, d.h.
    auch wenn auswahl != 'r' && auswahl != 'u' && auswahl != 'f' ist (wenn z.B. 'x' eingegeben wird),
    das ist nicht das, was du möchtest(das nehme ich jetzt einfach mal aufgrund deiner if-Anweisung unterhalb der while-Schleife an).

    Die Funktion scanf hat einen Rückgabewert der dabei helfen kann fehlerhafte Eingaben zu erkennen, dieser Rückgabewert sollte also abgefragt werden.



  • Danke für die Tipps,
    ich habe es nun nochmal überarbeitet und es funktioniert soweit.
    Nun kommt aber ein weiteres Problem dazu.
    Bei der Abfrage nach "Radius", "Umfang", "Flaeche" funktioniert die Fehlerangabe.
    Also die Reaktion auf eine Falscheingabe.
    Eine solche Falschangabe ist aber auch bei Eingabe des gegebenen Wertes möglich.
    Hier soll dann auch darauf hingewiesen werden, dass eine Falscheingabe vorliegt, dann soll der User erneut eine Eingabe tätigen dürfen, ohne 'auswahl' neu belegen zu müssen.

    #include <stdio.h>
    #include <math.h>
    
    int main() {
    
      float radius, umfang, flaeche;
      char auswahl = 0;
    
      printf("Kreisberechnungen");
    
      while (auswahl != 'x')
        {
            printf("\n\n-----------------------------------------");
            printf("\n\nBitte waehlen Sie, was gegeben ist.\n");
            printf("'r' fuer Radius\n");
            printf("'u' fuer Umfang\n");
            printf("'f' fuer Flaeche\n\n");
            printf("'x' zum Beenden des Programms\n\n");
            printf("Ihre Auswahl: ");
            scanf(" %c", &auswahl);
    
            if (auswahl == 'r') {
                printf("\nBitte geben Sie den Radius des Kreises ein.");
                printf("\nRadius: ");
                scanf(" %f", &radius);
    
                  umfang = 2 * M_PI * radius;
                  flaeche = M_PI * radius * radius;
    
                printf("\nDer Umfang betraegt: %f", umfang);
                printf("\nDer Flaecheninhalt betraegt: %f", flaeche);
            }
            else if (auswahl == 'u') {
    
                printf("\nBitte geben Sie den Umfang des Kreises ein.");
                printf("\nUmfang: ");
                scanf(" %f", &umfang);
    
                  radius = umfang / (2 * M_PI);
                  flaeche = M_PI * radius * radius;
    
                printf("\nDer Radius betraegt: %f", radius);
                printf("\nDer Flaecheninhalt betraegt: %f", flaeche);
            }
            else if (auswahl == 'f') {
    
                printf("\nBitte geben Sie den Flaecheninhalt des Kreises ein.");
                printf("\nFlaeche: ");
                scanf(" %f", &flaeche);
    
                  radius = sqrt (flaeche / M_PI);
                  umfang = 2 * M_PI * radius;
    
                printf("\nDer Radius betraegt: %f", radius);
                printf("\nDer Umfang betraegt: %f", umfang);
            }
            else {
    
                printf("**********************************\n");
                printf("* Ihre Eingabe ist ungueltig.    *\n");
                printf("* Bitte versuchen Sie es erneut. *\n");
                printf("**********************************\n");
            } 
        if (auswahl == 'x') {
    
                printf("Das Programm wird nun beendet.");
                printf("\nBitte mit 'ENTER' bestaetigen.\n");
        }
        } /* while Ende */
        return 0;
    }
    


  • Du musst halt um das einlesen vom Wert eine Schleife machen.
    Dazu kannst du den Rückgabewert (Return Value) von scanf auswerten: http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

    Da gibt es allerdings das Problem, das scanf falsche Zeichen (z.B Buchstaben bei Zahleneingabe) nicht einliest.
    Du musst also erst diese Zeichen überlesen: http://www.c-plusplus.net/forum/p1146014#1146014

    Da du das aber mehrmals brauchst, solltest du dafür eine eigene Funktion schreiben.



  • - M_PI ist kein Standard
    - dein Programm macht Unsinn bei z.B. Eingabe von 3,5 , weil du den Puffer von stdin nicht löscht (nach jeder Operation auf stdin immer sinnvoll)
    - bei scanf(" %f", ist das führende Leerzeichen redundant/sinnfrei
    - wie schon erwähnt kapsele deine mehrfach verwendeten Funktionalitäten in Funktionen


Log in to reply