Es soll unter Linux ein double Wert per Tastatur eingegeben werden und das führt zu Problemen



  • Ich habe jetzt gerade mal getestet, was sscanf zurückliefert, wenn man nur Enter drückt.

    printf("Testcode: %i\n", sscanf(line,"%lf",&input));
    

    Das Ergebnis ist -1, wenn nur Enter eingegeben wurde.
    Das Ergebnis ist 0, wenn ein Buchstabe oder irgendwetwas anderes außer Zahlen eingegeben wurde.
    Und 1, wenn eine Zahl eingegeben wurde.

    Daher würde ich darauf schließen, dass -1 für C99 nicht FALSE ist.
    Es wird also als TRUE interpretiert.
    Ist das so im C Standard definiert?



  • Swordfish schrieb:

    sscanf Problem schrieb:

    Auch dachte ich bisher, dass
    while ( true != irgendwas());

    gleichwertig ist mit

    while(!irgendwas());

    Wenn die Funktion irgendwas() einen Boolwert zurückliefert.
    Zumindest ist das in anderen Sprachen meistens so.

    Warum funktioniert das in C99 hier nicht?
    Also warum muss man das explizit ausschreiben?

    Du schnappst/suchst dir jetzt eine Referenz der C-Standardbibliothek und schaust dir die Bedeutung des Rückgabewerts von scanf() an!

    Ja, so wie es aussieht ein signed int.
    Aber war es nicht so, dass alles <= 1 als FALSE zu interpretieren ist?



  • sscanf Problem schrieb:

    Ja, so wie es aussieht ein signed int.
    Aber war es nicht so, dass alles <= 1 als FALSE zu interpretieren ist?

    sry, ich meinte < 1.
    1 ist ja wieder logsicherweise TRUE.



  • sscanf Problem schrieb:

    Aber war es nicht so, dass alles <= 1 als FALSE zu interpretieren ist?

    Nein. Alles ungleich 0 ist true .

    Du hast nicht verstanden.

    Swordfish schrieb:

    Du schnappst/suchst dir jetzt eine Referenz der C-Standardbibliothek und schaust dir die Bedeutung des Rückgabewerts von scanf() an!

    Wer sagt, daß das irgendwas mit einem Boolean zu tun hat!?



  • (s)scanf gibt keinen Boolwert zurück, sondern die Anzahl der erfolgreich gelesenen Elemente. Oder auch EOF bei einem Lesefehler.
    Für sscanf ist eine Leerzeile ein Lesefehler. EOF ist etwas anderes als 0.

    Bei while (1 != scanf("%lf%*[^\n]",&input)); ist das auch nur eine while-Schleife. Keine do-while.
    ~Ich weiß allerdings nicht, ob die 1 richtig ist.~



  • swordfish schrieb:

    Nein. Alles ungleich 0 ist true.

    Okay, dann lag ich hier im Irrtum und das erklärt dann auch das Verhalten des Codes.

    Bei while (1 != scanf("%lf%*[^\n]",&input)); ist das auch nur eine while-Schleife. Keine do-while.
    ~Ich weiß allerdings nicht, ob die 1 richtig ist.~

    Ich habe mir jetzt den verlinkten Thread durchgelesen und Variante 2 entsprechend modifiziert.

    So funktioniert es:

    // Variante 2:
    double eingabe_variante_2(){
      double input;
      int c;
      do {
        c; // int c, nicht char c.
        while ((c = getchar()) != EOF && c != '\n'); // das ist jetzt mein flush()
      } while (!scanf("%lf",&input));
      return input;
    }
    


  • Komisch. Bei deiner "Lösung" muss ich bevor ich eine double eingeben kann einmal Enter drücken?? und wenn ich dann EOF eingebe, komm ich trotzdem aus der Schleife, ohne eine double eingegeben zu haben?



  • sscanf Problem schrieb:

    So funktioniert es:

    // Variante 2:
    double eingabe_variante_2(){
      double input;
      int c;
      do {
        c; // int c, nicht char c.
        while ((c = getchar()) != EOF && c != '\n'); // das ist jetzt mein flush()
      } while (!scanf("%lf",&input));
      return input;
    }
    

    Ich muss mich korrigieren, es funktioniert nicht, wenn gleich am Anfang eine Zahl richtig eingegeben wurde.

    Habe es in:

    // Variante 2:
    double eingabe_variante_2(){
      double input;
      int c;
      do {
        c; // int c, nicht char c.
        while ((c = getchar()) != EOF && c != '\n'); // Dies funktioniert im Gegensatz zu fflush(stdin)
    //  } while (!scanf("%lf",&input));
      } while (1 != scanf("%lf",&input));
    // }  while (1 != scanf("%lf%*[^\n]",&input));
      return input;
    }
    

    und

    // Variante 2:
    double eingabe_variante_2(){
      double input;
      int c;
      do {
        c; // int c, nicht char c.
        while ((c = getchar()) != EOF && c != '\n'); // Dies funktioniert im Gegensatz zu fflush(stdin)
    //  } while (!scanf("%lf",&input));
    //  } while (1 != scanf("%lf",&input));
     }  while (1 != scanf("%lf%*[^\n]",&input));
      return input;
    }
    

    geändert, aber bei beiden Varianten existiert der Fehler, dass man die Zahl, wenn sie am Anfang richtig eingegeben wurde, noch einmal eingeben muss.

    Variante 2 ist somit immer noch ungelöst.
    Wenn auch der erste Bug, dass das Programm nicht mehr weitergeht, sobald irgendetwas anderes als eine Zahl eingegeben wurde, bei beiden modifizierten Varianten nicht mehr vorkommt.



  • Swordfish schrieb:

    Komisch. Bei deiner "Lösung" muss ich bevor ich eine double eingeben kann einmal Enter drücken??

    Ja, das ist leider der neue Bug, der betrifft aber alle Modifikationen von Variante 2.

    Also egal welches man davon nimmt:

    } while (!scanf("%lf",&input));
     } while (1 != scanf("%lf",&input));
     } while (1 != scanf("%lf%*[^\n]",&input));
    

    Der Fehler trifft bei allen auf.
    Sowohl wenn man zuerst ENTER eingibt oder eine ZAHL, also richtig, eingibt, muss man die eigentliche Zahl noch einmal geben.

    Lediglich der andere Bug, dass es gar nicht mehr weitergeht, wenn man einen Buchstaben oder ENTER zuerst eingegeben hat ist jetzt weg.



  • Dann mach eine while-Schleife (das do muss weg).



  • Wie wäre es, wenn du dich von der Vorstellung zwei Varianten zu brauchen verabschiedest und stattdessen die logische Vorgehensweise
    - Leseversuch
    - wenn Fehler:
    -- Fehlerbehandlung
    anwendest?



  • Swordfish schrieb:

    Wie wäre es, wenn du dich von der Vorstellung zwei Varianten zu brauchen verabschiedest und stattdessen die logische Vorgehensweise
    - Leseversuch
    - wenn Fehler:
    -- Fehlerbehandlung
    anwendest?

    Das ist doch gar nicht das Thema.

    Variante 1 funktioniert, ich könnte diese also nehmen.

    Aber Variante 2 funktioniert noch nicht.
    Was bitteschön ist jetzt falsch daran zu untersuchen warum sie nicht geht und sie entsprechend zu modifizieren bis sie geht?

    Variante 1 verwendet sscanf, Variante 2 scanf, das ist schon ein großer Unterschied und vielleicht braucht man mal das eine oder das andere.
    Bisher existiert aber nur eine funktionierende Lösung für sscanf.
    Die für scanf muss erst noch gefunden werden.

    @DirkB
    Werde ich noch testen.



  • Okay, die while(){} Variante ohne do geht:

    // Variante 3:
    double eingabe_variante_3(){
      double input;
      int c;
      while (1 != scanf("%lf",&input)){
     // while (1 != scanf("%lf%*[^\n]",&input)) { // <- das war nicht nötig
        c; // int c, nicht char c.
        while ((c = getchar()) != EOF && c != '\n'); // Dies funktioniert im Gegensatz zu fflush(stdin)
     } 
      return input;
    }
    


  • sscanf Problem schrieb:

    Okay, die while(){} Variante ohne do geht:

    Und das ist genau:

    Swordfish schrieb:

    - Leseversuch
    - wenn Fehler:
    -- Fehlerbehandlung

    Was meinst du, was Zeile 7 macht?
    Die schleppst du jetzt schon ein paar Versionen mit dir rum.



  • DirkB schrieb:

    Was meinst du, was Zeile 7 macht?

    Steht doch im Kommentar daneben!? 🤡



  • Was noch geht, ohne extra Variable oder Puffer:

    while (1 != scanf("%lf", &input)) 
           scanf("%*[^\n]");  // im Fehlerfall alles bis zum '\n' überlesen
        scanf("%*[^\n]");     // evtl Rest bis zum '\n' überlesen
    

    Der Versuch, das mit einem scanf zu machen geht nicht, da scanf mit dem einlesen aufhört, wenn es auf einen Fehler trifft.



  • Swordfish schrieb:

    DirkB schrieb:

    Was meinst du, was Zeile 7 macht?

    Steht doch im Kommentar daneben!? 🤡

    Oh! Äh, ja.

    Aber was bewirkt sie wirklich. 😕 😉


Anmelden zum Antworten