Doppelte Eingabe in C



  • Guten Tag,
    wir haben gerade ein Problem. Es wird eine Doppelte eingabe gefordert die im Code nicht ersichtlich ist, und die wir nicht wollen. Es handelt sich um einen Teilausschnitt eines Sudokus. In dem Werte an gewissen stellen eingelesen werden sollen, zum beispiel feld[0][0] soll eine 6 stehen.
    Das eigentliche Problem ist daran, dass er am anfang, wo man die Anzahl der Zahlen des gesamten Sudokus angibt. Noch eine Abfrage startet, welche Reihe, der Benutzer die Zahlen eingeben möchte, dies soll nicht sein.
    Da wir im nächsten Schritt die genaue Position festlegen.
    Schonmal Danke für eure Hilfe
    LG Ingmar

    #include <stdio.h>
    #include <stdlib.h>
    #define SIZE 9
    int main()
    {
        int feld[9][9] = { 0 };
    
        int anzahl_Zahlen = 0;
        int wert=0;
        int eingabe ;
        int wert_ausgabe;
        int i,j;
        for(i=0;i<SIZE;i++)
        {
            for(j=0;j<SIZE;j++)
            {
                printf("%d ",feld[i][j]);
            }
            printf("\n");
        }
        printf("Wie viele Zahlen möchten sie in das Sudoku eintragen? ");
        scanf("%d ", &eingabe);
        //hier erfolgt eine Doppelte eingabe die nicht sein soll
        while (anzahl_Zahlen<eingabe)
        {
    
            printf("Geben sie die Reihe in der sie eine Zahl ableben möchten an! ");
            scanf("%d \n", &i);
            printf("[Geben sie die Spalte in der sie eine Zahl ableben möchten an!  ");
            scanf("%d \n", &j);
            printf("%d %d %d ", i, j, wert);
    
            printf("Setzen Sie nun eine Ihre Zahl von 1 bis 9 hinein! \n ");
            scanf("%d \n", &wert);
            wert = wert_ausgabe;
            printf("%d \n", wert_ausgabe);
            feld[i][j]= wert_ausgabe;
    
    
    
        anzahl_Zahlen++;
        }
    
    
        for(i=0;i<SIZE;i++)
        {
            for(j=0;j<SIZE;j++)
            {
                printf("%d ",feld[i][j]);
            }
            printf("\n");
        }
    
        return 0;
    }
    

  • Mod

    Was sollen die Leerzeichen und Zeilenumbrüche am Ende deiner scanf-Formatstrings? Die haben eine handfeste Bedeutung für das Verhalten von scanf.

    Oft zitiert und stets wahr:

    Code ist kein zusammengewürfelter Haufen von Zeichen. Code ist Logik pur! Du musst von jedem Zeichen in deinem Code genau wissen, wo und warum du es setzt.



  • @Luckyingmar Welche Eingabe ist doppelt? die von eingabe?
    Oder die von i und j?

    Die Leerzeichen und Newline haben bei scanf eine ganz andere Bedeuitung als bei printf. Lass sie weg.

    Wenn du schon SIZE benutzt, dann auch bei der Definition vom Feld in Zeile 6



  • Wir haben die Leerzeichen und \n im scanf entfernt, es kommt aber dennoch zu dieser doppelten Eingabe.
    Die doppelte Eingabe entsteht bei Zeile 22 eingabe.
    EDIT: Danke Euch beiden. Hat doch geklappt.



  • @Luckyingmar Leerzeichen und Newline haben im Formatstring von scanf dieselbe Bedeutung: Überlesen/ignorieren von Whitespace (Leerzeichen, Tabulatoren, Vorschübe).
    Daher sind sie vor einem Formatspecifier sinnvoll.
    Aber nicht vor jedem, da die Specifier für Zahleneingabe und auch %s führende Whitespace von sich aus überlesen.



  • Das Problem ist, dass du dir zuwenig Gedanken um die Eingabe aus stdin im Rahmen deines C-Programms gemacht hast, und um die Validierung gar keine.
    scanf hinterlässt in der Regel '\n' in stdin, was dann beim nächsten scanf zu Problemen führt, deshalb musst du das selbst behandeln und ebenso die Validierung. Das machen 99,999% aller C-Programmierer nicht, was dann zu deinen Problemen führt.
    C ist nicht für Frontends gedacht, deshalb gibt es dafür nur spartanischen Service aus der Standardbibliothek.
    Wenn man es doch macht, muss man halt Profi sein - und für solche ist C gemacht worden.

    #include <stdio.h>
    #include <stdlib.h>
    enum {MYSIZE=9};
    int main()
    {
        int feld[MYSIZE][MYSIZE] = { 0 };
    
        int anzahl_Zahlen = 0;
        int wert=0;
        int eingabe ;
        int wert_ausgabe;
        int i,j;
        for(i=0;i<MYSIZE;i++)
        {
            for(j=0;j<MYSIZE;j++)
            {
                printf("%d ",feld[i][j]);
            }
            printf("\n");
        }
        printf("Wie viele Zahlen möchten sie in das Sudoku eintragen? ");
        if(1!=scanf("%d", &eingabe)) perror("fehlerhafte Eingabe"),exit(1); for(int c;(c=getchar())!='\n'&&c!=EOF;);
        //hier erfolgt eine Doppelte eingabe die nicht sein soll
        while (anzahl_Zahlen<eingabe)
        {
    
            printf("Geben sie die Reihe in der sie eine Zahl ableben möchten an! ");
            if(1!=scanf("%d", &i)) perror("fehlerhafte Eingabe"),exit(1); for(int c;(c=getchar())!='\n'&&c!=EOF;);
            printf("[Geben sie die Spalte in der sie eine Zahl ableben möchten an!  ");
            if(1!=scanf("%d", &j)) perror("fehlerhafte Eingabe"),exit(1); for(int c;(c=getchar())!='\n'&&c!=EOF;);
            printf("%d %d %d ", i, j, wert);
    
            printf("Setzen Sie nun eine Ihre Zahl von 1 bis 9 hinein! \n ");
            if(1!=scanf("%d", &wert)) perror("fehlerhafte Eingabe"),exit(1); for(int c;(c=getchar())!='\n'&&c!=EOF;);
            wert_ausgabe = wert;
            printf("%d\n", wert_ausgabe);
            feld[i][j]= wert_ausgabe;
    
        anzahl_Zahlen++;
        }
    
        for(i=0;i<MYSIZE;i++)
        {
            for(j=0;j<MYSIZE;j++)
            {
                printf("%d ",feld[i][j]);
            }
            printf("\n");
        }
        
        return 0;
    }
    

    https://ideone.com/54poLV


  • Mod

    Häh? Das kannste dir komplett sparen, wenn's von einem scanf zum nächsten geht. Besonders mit nur %d. Wenn hier formatierte und unformatierte Eingaben gemischt wären, dann wäre das anders. Aber so wie hier ist das unnötiger und verwirrender Blähcode.

    Außerdem machst du so die Eingaben von Powerusern kaputt, die die Werte ggf. nicht unnötig mit \n trennen.



  • Das ist kein Blähcode sondern professioneller Code, der immer und überall und unter allen Umständen funktionieren wird.
    Und wenn man den Code in eine Funktion packt, das exit durch return ersetzt ist er somit ideal als Bibliothek zu verwenden, und für Bibliotheken gilt nun mal, dass sie unabhängig vom Kontext und DAU Bedienern immer (gleich) funktionieren müssen, wenn sie professionellen Anspruch haben wollen.


  • Mod

    Hmm. Eine Bibliothek sagst du? Klingt nützlich, so eine Funktion, die bei formatierten Eingaben automatisch Whitespace überspringt. Man könnte sie scanf nennen und in eine Bibliothek packen, deren Name ausdrückt, dass sie die Standardfunktionen für Ein- und Ausgaben enthält. Wie wäre es mit stdio?

    Oder weniger sarkastisch: Wenn dein Programm exakt das gleiche macht, egal ob es die vielen Wiederholungen der Zeile for(int c;(c=getchar())!='\n'&&c!=EOF;); enthält oder nicht, dann ist diese Zeile unnötiger Blähcode. Und das ist hier der Fall. Gerade der Profi-C-Entwickler weiß nämlich, was seine Eingabefunktionen machen und schreibt nicht blind irgendwelche getchar-Schleifen überall hin, weil er nicht darüber nachdenken möchte, wo und warum die eigentlich hin gehören oder wann nicht.

    Ähnlich dein Code zu den Eingabefehlern. Hier gibt es ein recht klares Gesamtdatum, bestehend aus jeweils drei Zahlen. Da prüft der mitdenkende Entwickler einmal pro Datum den Gesamterfolg, denn nur dieser zählt, anstatt blind 3x den gleichen Code zu kopieren.



  • Unsinn.
    Jeder Zugriff auf globalstatischen Speicher (hier stdin) ist immer fragil, Annahmen darüber, was wohl vorher geschehen sein könnte und wohl anschließend passieren wird sind einfach nur ignorant und somit laienhafter Unsinn, zumal sie einfach zu behandeln sind.
    Weiterhin ist es laienhafter Unsinn - gerade bei Nutzereingaben - davon auszugehen, dass diese DAUs schon das Richtige eingeben werden, das zum Code des jeweiligen "verantwortlichen" Entwicklers passen wird und keine Abhängigkeiten im übrigen Programmkontext schafft.



  • Dieser Beitrag wurde gelöscht!

Anmelden zum Antworten