Scanf und Buchstaben ;)
-
Hi,
ich habe ein Problem bezüglich dem einlesen von Zeichen mit char.#include <stdio.h> int main() { int figure_a = 0; // determining needed variables int figure_b = 0; int result_a = 0; int result_b = 0; int choice = 'a'; int x = 0; do // do while for repeatability of the program { x = 1; printf ("Enter an even number: \n"); // einlesen von figure_a scanf ("%d", &figure_a); printf("Enter an odd number: \n"); // einlesen vonfigure_b scanf ("%d", &figure_b); result_a = (figure_a % 2); result_b = (figure_b % 2); if ((result_a==0)&&(result_b==1)) { printf ("You are able to differ between odd and even number. Congratulations!\n"); x = 0; } else { printf ("Your entered atleast one wrong number! \nDo you want to try again? 1=j/0=n \n"); // repeat request? scanf ("%d", &choice); [b]das problem ist hier![/b] if ( choice == 1) // reading out choice, restart or program end { x=1; } else { x--; } } } while (x==1); return 0; }
Mit Zahlen zum auswählen ob wiederholen oder nicht ging es bis vor kurzen, aber vom einen auf das andre mal funktionierte es nicht mehr.
Zuvor hab ich es mit Zeichen probiert J/N und dass ging auch nicht.
Wisst ihr was ich falsch mache.Danke im Voraus
lg
-
Wie kommst du darauf, dass scanf Probleme macht?
Hast du dir mal angesehen, was du eingeben hast?
Im Debugger oder mit einem printf?Wenn du einmal etwas anderes als Ziffern eingegeben hast, hängt dein Programm, da scanf bei %d nur Ziffern (und evtl. Vorzeichen) und Whitespace einliest.
Das dein Code hier nicht richtig formatiert ist, liegt am: das problem ist hier! .
Das cpp-Tag mag keine zusätzlichen Formatierungen.
-
Wenn
scanf()
eine im Bezug auf den angegebenen Formatstring fehlerhafte Eingabe bekommt, verbleibt der Rest der eingabe im Puffer. -> Im Fehlerfall solange ausstdin
lesen, bis entwederEOF
oder'\n'
daherkommt.#include <stdio.h> void clear_stdin( void ) { int ch = 0; while( ( ( ch = getchar() ) != '\n' ) && ( ch != EOF ) ); } int main() { int a = 0; // declaration and definition of needed variables int b = 0; char choice = '\0'; do { while( printf( "Enter an even number: "), scanf ( "%d", &a ) != 1 ) { clear_stdin(); printf( "Input error! Please try again.\n\n" ); } while( printf( "Enter an odd number: "), scanf( "%d", &b ) != 1 ) { clear_stdin(); printf( "Input error! Please try again.\n\n" ); } if( !( a % 2 ) && ( b % 2 ) ) { printf( "\nYou are able to tell the difference between odd and even numbers. Congratulations!\n"); choice = 'n'; } else { clear_stdin(); printf( "\nAt least one input didn't meet requirements!\n\n" ); while( printf( "Do you want to try again? (y/n) "), scanf( "%c", &choice ) != 1 && ( choice != 'y' && choice != 'n' ) ) { clear_stdin(); printf( "Input error! Please try again.\n\n" ); } printf( "\n\n" ); } } while( choice == 'y' ); }
Spelling, grammar and style fixed for you.
-
Schön ist der Aufruf der Funktion printf in der while-Schleife ja nicht gerade zumal für Anfänger recht verwirrend.
-
Ansichtssache. Wie machst du's?
-
vielen Dank schonmal;)
wenn ich deinen source code copy paste, dann wiederholt er bei mir bei richtiger Eingabe das Programm automatisch und bei falscher ist es automatisch zu Ende.
Liegt das Problem bei meinem Compiler?
Ich verwende Codeblocks 10.5.
-
richard1092 schrieb:
wenn ich deinen source code copy paste, dann wiederholt er bei mir bei richtiger Eingabe das Programm automatisch und bei falscher ist es automatisch zu Ende.
? Kann ich mir nicht vorstellen.
richard1092 schrieb:
Liegt das Problem bei meinem Compiler?
Als der da wäre? (Nein, CodeBlocks 10.5 ist nicht dein Compiler)
-
Swordfish schrieb:
scanf( "%c", &choice ) != 1 && ( choice != 'y' && choice != 'n' ) ) {
Nach einem scanf-Fehler noch irgendwelche Argumente auszuwerten, ist sinnfrei.
-
Wenn links
false
ist wird rechts nicht ausgewertet... deswegen auch die Klammerei.edit: Short-circuiting §§6.3.13 u. 6.3.14
-
Swordfish schrieb:
Ansichtssache.
printf soll hier keine schleife steuern, also würd ich es da rausnehmen
und die eingabefunktion auslagern.
btw. hast du noch nen logikfehler hierwhile( printf( "Do you want to try again? (y/n) "), scanf( "%c", &choice ) != 1 && ( choice != 'y' && choice != 'n' ) )
Swordfish schrieb:
Wie machst du's?
aber nicht lachen!
int integer_input ( char* even_or_odd ) { int ret = 0, number; do { if ( even_or_odd ) printf ( even_or_odd ); if ( 1 != (ret = scanf ( "%d", &number ))) printf( "Input error! Please try again.\n\n" ); clear_stdin(); } while ( 0 == ret ); return number; } int main(void) { int a = 0, b = 0, choice = 0; do { choice = 0; // !!! :D a = integer_input("Enter an even number: "), b = integer_input("Enter an odd number: "); if ( !( a % 2 ) && ( b % 2 )) choice = 'n', printf( "\nYou are able to tell the difference between odd and even numbers. Congratulations!\n"); else printf( "\nAt least one input didn't meet requirements!\n\n" ); while ( choice != 'y' && choice != 'n' ) printf( "Do you want to try again? (y/n)" ), choice = getchar(), clear_stdin(); } while ( choice == 'y' ); puts("Hit enter to quit."); getchar(); return 0; }
-
C Ästhetiker schrieb:
btw. hast du noch nen logikfehler hier
while( printf( "Do you want to try again? (y/n) "), scanf( "%c", &choice ) != 1 && ( choice != 'y' && choice != 'n' ) )
Als der da wäre?
C Ästhetiker schrieb:
Swordfish schrieb:
Wie machst du's?
[...]
Hm, eine Schleife, zwei if und eine Variable vs. eine Schleife?
Ich nehm' die Schleife
-
ich meinte den bei codeblocks vorinstallierten compiler.
gnu gcc Ccompiler steht unter settings compiler.Keine Ahnung ob da auf meinem PC etwas falsch läuft.
Vermutlich schon! Habe den source code einem Kollegen geschickt bei ihm läuft alles wunderbar (bei meiner älteren version). Bei mir hats nie funktioniert.Evtl nen neuen Editor + Compiler/Debugger runterladen? Wenn ja, hab ich halt das Problem, dass ich net weiß was und wie^^
-
so ich habe jetzt folgenden Code am Server meiner Uni compiliert.
Läuft alles wunderbar nur auf meinem Rechner nicht.
Nachdem beide Zahlen eingegeben wurden kommt das "Sie haben einen Fehler gemacht. Erneut versuchen J/N".
Und das Programm beednet sich genau in diesem Moment.
Bei richtiger Eingabe passt alles.Ich weiß sehr wohl das alles sehr umständlich von mir programmiert wurde, nur das ist erst mein 3tes Programm und ich würd halt gern einen "funktionierenden" Compiler haben(falls man das so ausdrücken kann, er wird wohl funktionieren nur halt nicht sehr anfängerfreundlich sein was den Speicherplatz etc angeht^^).
Hier der Code
/* * File: main.c * Author: Richard * * Created on 10. Oktober 2012, 20:19 */ #include <stdio.h> int main() { int figure_a = 0; // determining needed variables int figure_b = 0; int result_a = 0; int result_b = 0; char choice = 'a'; int x = 0; do // do while for repeatability of the program { x = 1; figure_a = 0; figure_b = 0; choice = 'a'; printf ("Enter an even number: \n"); // einlesen von figure_a scanf ("%d", &figure_a); printf("Enter an odd number: \n"); // einlesen vonfigure_b scanf ("%d", &figure_b); result_a = (figure_a % 2); result_b = (figure_b % 2); if ((result_a==0)&&(result_b==1)) { printf ("You are able to differ between odd and even number. Congratulations!\n"); x = 0; } else { printf ("Your entered atleast one wrong number! \nDo you want to try again? j/n \n"); // repeat request? scanf ("%c", &choice); if (choice == 'j' || choice =='J') // reading out choice, restart or program end { x=1; } else { x--; } } } while (x==1); return 0; }
-
richard1092 schrieb:
Nachdem beide Zahlen eingegeben wurden kommt das "Sie haben einen Fehler gemacht. Erneut versuchen J/N".
Und das Programm beednet sich genau in diesem Moment.
Bei richtiger Eingabe passt alles.Auch bei korrekter Eingabe der beiden
int
s bleibt ein'\n'
im Puffer, welches von deinemscanf ("%c", &choice);
konsumiert wird (
choice == 10
).Danach kommt immer
if (choice == 'j' || choice =='J') // reading out choice, restart or program end { x=1; } else { x--; // <- das. btw: warum nicht einfach x = 0 ? }
Die Lösung ist wie hier schon erklärt, den Eingabepuffer zu leeren.
ps&btw: "jes/no" ?
-
Du kannst auch mal ein Leerzeichen in dem Formatsring von scanf vor dem % probieren:
scanf (" %c", &choice); ^ da
C99 7.19.6.2 The fscanf function schrieb:
5. A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read.
...
8. Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier.
-
Swordfish schrieb:
Hm, eine Schleife, zwei if und eine Variable vs. eine Schleife?
Ich nehm' die SchleifeDu spottest über eine vermeintliche Verschlechterung. Siehst du nicht?
Ich habe eine Zeile im Hauptprogramm, die dasselbe bewirkt wie 12 von dir.
Des Weiteren ist es guter Stil die Ein- und Ausgabefunktionen auszulagern, u.a. um Spaghetticode zu vermeiden.
Dafür spendiere ich doch gern ein if und lege noch eine Variable oben druff!
Hugh!Zugegeben die Funktion integer_input ist noch ein wenig verbesserungswürdig, weil sie dem Hauptprogramm eine Eingabe aufzwingt
- das Hauptprogramm hat keine Chance bei einer falschen Eingabe abzubrechen/zu verzweigen.
Darum habe ich meinen Senf ein wenig überarbeitet, guck:int integer_input ( int* number ) { int ret = scanf ( "%d", number ); clear_stdin(); if ( 1 != ret ) puts ( "Input error!" ); return 1 != ret; } int main(void) { int a = 0, b = 0, choice = 0; do { choice = 0; /// !!!! do printf("Enter an even number: "); while ( integer_input ( &a )); do printf("Enter an odd number: "); while ( integer_input ( &b )); if ( !( a % 2 ) && ( b % 2 )) choice = 'n', puts( "Well done!"); else puts( "At least one input didn't meet requirements!" ); while ( choice != 'y' && choice != 'n' ) puts( "Do you want to try again? (y/n)" ), choice = getchar(), clear_stdin(); } while ( choice == 'y' ); puts("Hit enter to quit."); getchar(); return 0; }
Was sagst du jetzt?
Btw. hast du deinen Logikfehler gefunden?
-
DirkB schrieb:
Du kannst auch mal ein Leerzeichen in dem Formatsring von scanf vor dem % probieren
Danke!
C Ästhetiker schrieb:
Swordfish schrieb:
Hm, eine Schleife, zwei if und eine Variable vs. eine Schleife?
Ich nehm' die SchleifeDu spottest über eine vermeintliche Verschlechterung. Siehst du nicht?
Schonschon. Aber bis zu diesem Punkt hast du nur gegen die Verwendung des Kommaoperators argumentiert. Er ist so angewandt wie er gedacht ist, so what's the point?
C Ästhetiker schrieb:
Ich habe eine Zeile im Hauptprogramm, die dasselbe bewirkt wie 12 von dir.
Des Weiteren ist es guter Stil die Ein- und Ausgabefunktionen auszulagern, u.a. um Spaghetticode zu vermeiden.Ich habe nie gesagt, daß ich gegen das auslagern redundanten Codes in Funktionen gesagt.
C Ästhetiker schrieb:
int integer_input ( int* number ) { int ret = scanf ( "%d", number ); clear_stdin(); if ( 1 != ret ) /* Dann überlass auch die */ puts ( "Input error!" ); /* Fehlerbehandlung dem caller ... */ return 1 != ret; /* im Erfolgsfall false zurückgeben? */ }
#include <ctype.h> #include <string.h> #include <stdio.h> void clear_stdin( void ) { int ch = 0; while( ( ( ch = getchar() ) != '\n' ) && ( ch != EOF ) ); } int request_int( int *dst, char const *prompt = 0, int may_fail = 0 ) { int success = 0; while( prompt && printf( "%s: ", prompt ), ( success = scanf ( "%d", dst ) ) != 1 && !may_fail ) { clear_stdin(); printf( "Input error! Please try again.\n\n" ); } return success; } int request_char( char *dst, char const* valid_chars, char const *prompt = 0, int may_fail = 0 ) { int success = 0; while( prompt && printf( "%s ", prompt ), !( ( success = scanf ( " %c", dst ) ) == 1 && ( !valid_chars || strchr( valid_chars, *dst ) ) ) || may_fail ) { clear_stdin(); printf( "Input error! Please try again.\n\n" ); } return success; } int main() { int a = 0; // declaration and definition of needed variables int b = 0; char choice = '\0'; do { request_int( &a, "Enter an even number" ); request_int( &b, "Enter an odd number" ); if( !( a % 2 ) && ( b % 2 ) ) { printf( "\nYou are able to tell the difference between odd and even numbers. Congratulations!\n"); choice = 'n'; } else { printf( "\nAt least one input didn't meet requirements!\n\n" ); request_char( &choice, "yYnN", "Do you want to try again? (y/n)" ); printf( "\n\n" ); } } while( tolower( choice ) == 'y' ); }
C Ästhetiker schrieb:
Btw. hast du deinen Logikfehler gefunden?
Ja. Deine Zuweisung an
choice
am Beginn des Schleifenkörpers ist aber trotzdem unnötig.
-
Swordfish schrieb:
Schonschon. Aber bis zu diesem Punkt hast du nur gegen die Verwendung des Kommaoperators argumentiert.
Er ist so angewandt wie er gedacht ist, so what's the point?Eher gegen das printf in der while Schleife, weil es keine Funktion hat außer den Code schwerer lesbar zu machen,
aber recht hast du, die Kommaoperatoren fand ich dort zusammen mit dem printf auch verwirrend
(du ja vielleicht auch, wegen des misslungenen Schleifenkopfs? (der musste ja jetzt kommen, ne ;))).Swordfish schrieb:
Ich habe nie gesagt, daß ich gegen das auslagern redundanten Codes in Funktionen gesagt.
Full ACK. (Du hattest es lediglich praktiziert. *breitgrins und wechduck*)
Swordfish schrieb:
return 1 != ret; /* im Erfolgsfall false zurückgeben? */
Neineineineinein, return 1 == Funktion liefert einen Fehler,
return 0 == Funktion liefert Null Fehler.Swordfish schrieb:
/* Dann überlass auch die /
puts ( "Input error!" ); / Fehlerbehandlung dem caller ... */Das sehe und mache ich prinzipiell auch so. War wohl noch nicht richtig wach. (Warum machst du das nicht?)
Swordfish schrieb:
int request_char( char *dst, char const* valid_chars, char const *prompt = 0, int may_fail = 0 ) { ... clear_stdin(); printf( "Input error! Please try again.\n\n" ); // Wasser predigen Wein trinken :D (not caller-driven) ...
->
int int_input ( int* number, int report ) { int ret = scanf ( "%d", number ); clear_stdin(); if ( ret ) return 0; else if ( report ) return emsg ( "Input error!" ); // caller driven message output else return 1; // dito(kein output) } // Da die Funktion int_input nicht zur Eingabe einer gültigen Zahl zwingt, // kann im Programm unterschiedlich auf die Antwort reagiert werden: do printf ( "Enter an odd number:" ); while ( int_input ( &b, 1 )); // Eine gültige Eingabe erzwingen. if ( int_input ( &b, 1 ) ) return msg ( "Danger of CPU overheating! Go somewhere else and learn how to type numbers, then come back and try again."); // Funktion oder Programm verlassen.
Swordfish schrieb:
Deine Zuweisung an
choice
am Beginn des Schleifenkörpers ist aber trotzdem unnötig.Is woll nötig, eildieweil man bei fehlerhafter Eingabe ansonsten gar nicht mehr "Do you want to try again? (y/n)" gefragt würde.
Swordfish schrieb:
int request_char( char *dst, char const* valid_chars, char const *prompt = 0, int may_fail = 0 )
Defaultparameter? Das muffelt verdächtig nach C++, oder ist das mittlerweile C99 Standard? Dem C99 hinke ich meilenweit hinterher ächts.
Swordfish schrieb:
... while( prompt && printf( "%s ", prompt ), !( ( success = scanf ( " %c", dst ) ) == 1 && ( !valid_chars || strchr( valid_chars, *dst ) ) ) || may_fail ) ...
Ein wenig kryptisch das geworden ist und noch schwerer zu verstehen, da bräuchte ich ja schon Zettel und Stift bei
den vielen Möglichkeiten, um das zu kapieren! Das geht ja gaaar nicht ... ich bin eher fürs schlichte, leicht verständliche, ästhetische.
Oder glaubst du ich hatte mir nur so diesen edlen Namen zugelegt? Ich bin doch nicht zum Spaß hier!
Dafür ist deine main jetzt schön aufgeräumt.Was wird das eigentlich, online team homework development?
Ich habe deine validate Idee geklaut und den Inhalt der main ein wenig nach meiner Nase abgeändert, natürlich mit redundancy-free while conditions :p .// Ausgelagerte Ausgabe(n) -> wartungs && multi language development friendly. int msg ( const char* s ) { printf ( "%s", s ); return 1; } int validate_char ( const char* valid_set, int c ) { if ( EOF == c ) return 1; // ERROR return NULL == strchr ( valid_set, c ); // 1: ERROR, 0: OK } void clear_stdin ( void ) { int c; while (( c = getchar()) != '\n' && c != EOF ) {} } int int_input ( int* number, int verbose ) { int ret = scanf ( "%d", number ); clear_stdin(); if ( ret ) return 0; else if ( verbose ) return msg ( "Input error!\n" ); // caller driven message output else return 1; // dito } int char_input ( int* c, const char* valid_set, int verbose ) { if (( *c = getchar()) != '\n' ) clear_stdin(); if ( validate_char ( valid_set, *c )) { if ( verbose ) return msg ( "Input error! " ); // caller driven message output else return 1; // dito } // auto else implicit return 0; } int main ( void ) { int a = 0, b = 0, choice = 0; do { do msg ( "Enter an even number: "); while ( int_input ( &a, 1 )); do msg ( "Enter an odd number: "); while ( int_input ( &b, 1 )); if ( !( a % 2 ) && ( b % 2 )) msg ( "Well done!\n" ); else msg ( "At least one input doesn't meet requirements!\n" ); do msg ( "Do you want to try again(y/n)? " ); while ( char_input ( &choice, "YyNn", 1 )); } while ( choice == 'y' || choice == 'Y' ); return 0; }
-
Swordfish schrieb:
Wenn links
false
ist wird rechts nicht ausgewertet... deswegen auch die Klammerei.edit: Short-circuiting §§6.3.13 u. 6.3.14
Du meine Güte.
Du hast bei deinem ganzen Klammerungskram den Überblick zw. true und false verloren. Rechts wird choice ausgewertet, wenn links true ergibt. Links ergibt true, wenn scanf !=1 liefert also fehlerhaft interpretiert wurde, was zu einem fraglichen Inhalt von choice führt, den du rechts dann auswertest.
-
Big Brother the genuine schrieb:
Neineineineinein, return 1 == Funktion liefert einen Fehler,
return 0 == Funktion liefert Null Fehler.Ziemlich gewöhnungsbedürftig für C, um nicht ein schlimmeres Wort zu gebrauchen.
Big Brother the genuine schrieb:
int int_input ( int* number, int report ) { int ret = scanf ( "%d", number ); clear_stdin(); if ( ret ) return 0;
Falsch.
Liefert scanf EOF, liefert deine Funktion true in deinem Sinne, was natürlich unsinnig ist.