trouble bulltproofing scanf
Author |
Message |
Ivan #1 / 14
|
 trouble bulltproofing scanf
Hello everyone, I tried to read one string from the user using: scanf("%s", UserResponse); However, if the user types two words before hitting the enter key, the second word seems to remain in the stream even though my format control string contains only one %s. The problem arises in subsequent uses of scanf. The string that is converted and assigned to the character array in the latter scanf is not the string that the user just typed, but rather the second srting that the user typed in the previous scanf. After the first scanf the extra garbage tht the user types, that is not expected in the format control string seems to stay in the stream. How do I clear out any garbage that is in the stream? By the way, the purpose of the program is to teach a foreign language. Thanks. Ivana #include <stdio.h> #include <string.h> main () { char EnglishWord[20], Word1[20], Word2[20], Word3[20], UserResponse[20]; char UserMenuChoice[3]; int counter=0; FILE *DictionaryPointer; printf("Type C to continue or Q to quit\n"); scanf("%s", UserMenuChoice); if(strcmp(UserMenuChoice, "C") == 0 ) printf("\nOK, let's get started............\n\n\n"); else exit(0); if((DictionaryPointer=fopen("/code/Dictionary", "rw")) == NULL) { printf("Error: Can't open /code/Directory in read/write mode!\n"); exit(1); } for(counter=0;counter<3;counter++) { fscanf(DictionaryPointer,"%s",EnglishWord); fscanf(DictionaryPointer,"%s",Word1); fscanf(DictionaryPointer,"%s",Word2); fscanf(DictionaryPointer,"%s",Word3); printf("What does \"%s\" mean? ",EnglishWord); scanf("%s", UserResponse); printf("\n"); if (strcmp(UserResponse, Word1) == 0 || strcmp(UserResponse, Word2) == 0 || strcmp(UserResponse, Word3) == 0 ) printf("You are a badass.\n\n"); else { printf("You are a loser.\n\n"); printf("Would you like me to tell you what it means? "); scanf("%s", UserMenuChoice); printf("\n"); if(UserMenuChoice[0] == 'y') printf("\t\t%s means %s", EnglishWord, Word1); if(strcmp(Word1, Word2) != 0) printf(" or %s", Word2); if(strcmp(Word3, Word1) != 0 && strcmp(Word3, Word2) != 0) printf(" or %s", Word3); printf(".\n\n\n"); } } } fclose(DictionaryPointer); return(0); Quote: }
|
Sun, 27 Aug 2000 03:00:00 GMT |
|
 |
Joshua Waxma #2 / 14
|
 trouble bulltproofing scanf
Quote:
> Hello everyone, > I tried to read one string from the user using: > scanf("%s", UserResponse); > However, if the user types two words before hitting the enter key, the > second word seems to remain in the stream even though my format control > string contains only one %s. The problem arises in subsequent uses of scanf. > The string that is converted and assigned to the character array in the > latter scanf is not the string that the user just typed, but rather the > second srting that the user typed in the previous scanf. After the first > scanf the extra garbage tht the user types, that is not expected in the > format control string seems to stay in the stream. How do I clear out any > garbage that is in the stream? > By the way, the purpose of the program is to teach a foreign language. > Thanks. Ivana
Well, you could make a loop to eat up characters until \n. while (getchar() != '\n'); Or, instead of using scanf, use fgets from stdout to read the entire line and then sscanf to take only the first element of the string. HTH, Josh Waxman Quote: > #include <stdio.h> > #include <string.h> > main () > { > char EnglishWord[20], Word1[20], > Word2[20], Word3[20], UserResponse[20]; > char UserMenuChoice[3]; > int counter=0; > FILE *DictionaryPointer; > printf("Type C to continue or Q to quit\n"); > scanf("%s", UserMenuChoice); > if(strcmp(UserMenuChoice, "C") == 0 ) > printf("\nOK, let's get started............\n\n\n"); > else > exit(0); > if((DictionaryPointer=fopen("/code/Dictionary", "rw")) == NULL) > { > printf("Error: Can't open /code/Directory in read/write mode!\n"); > exit(1); > } > for(counter=0;counter<3;counter++) > { > fscanf(DictionaryPointer,"%s",EnglishWord); > fscanf(DictionaryPointer,"%s",Word1); > fscanf(DictionaryPointer,"%s",Word2); > fscanf(DictionaryPointer,"%s",Word3); > printf("What does \"%s\" mean? ",EnglishWord); > scanf("%s", UserResponse); > printf("\n"); > if > (strcmp(UserResponse, Word1) == 0 || > strcmp(UserResponse, Word2) == 0 || > strcmp(UserResponse, Word3) == 0 ) > printf("You are a badass.\n\n"); > else > { > printf("You are a loser.\n\n"); > printf("Would you like me to tell you what it means? "); > scanf("%s", UserMenuChoice); > printf("\n"); > if(UserMenuChoice[0] == 'y') > printf("\t\t%s means %s", EnglishWord, Word1); > if(strcmp(Word1, Word2) != 0) > printf(" or %s", Word2); > if(strcmp(Word3, Word1) != 0 && > strcmp(Word3, Word2) != 0) > printf(" or %s", Word3); > printf(".\n\n\n"); > } > } > } > fclose(DictionaryPointer); > return(0); > }
|
Sun, 27 Aug 2000 03:00:00 GMT |
|
 |
Joshua Waxma #3 / 14
|
 trouble bulltproofing scanf
Quote: > Hey, scanf() stops scanning at he first white space it encounters. Use a line > get and use strtok() ... > -SC
Actually, while this is true for ansi C, it is interesting to note that, according to Advanced C by Example, many compilers provide a hidden extension. scanf("%[a-zA-Z0-9 \t]s", my_string); will keep reading until it hits a character not in the set of characters in the brackets. Thus, this will read til the end of the line. Josh Waxman
|
Sun, 27 Aug 2000 03:00:00 GMT |
|
 |
SolidCod #4 / 14
|
 trouble bulltproofing scanf
Hey, scanf() stops scanning at he first white space it encounters. Use a line get and use strtok() ... -SC
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
SolidCod #5 / 14
|
 trouble bulltproofing scanf
You can use fflush() to clear the stream (if you do want to do it) -SC
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
James #6 / 14
|
 trouble bulltproofing scanf
On Wed, 11 Mar 1998 23:25:18 -0500, Joshua Waxman Quote:
>Actually, while this is true for ansi C, it is interesting to note that, >according to Advanced C by Example, many compilers provide a hidden >extension. >scanf("%[a-zA-Z0-9 \t]s", my_string); >will keep reading until it hits a character not in the set of characters >in the brackets. Thus, this will read til the end of the line.
This is actually not a hidden extension. It has always been defined for scanf in the C Standard. It is called a "scanset". The trailing "s" in the string above is probably an errata, or you copied it from the book wrong. --
http://www.cs.wustl.edu/~jxh/ Washington University in Saint Louis Quote: >>>>>>>>>>>>> I use *SpamBeGone* <URL:http://www.internz.com/SpamBeGone/>
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Bernd Luevelsmeye #7 / 14
|
 trouble bulltproofing scanf
Quote:
> You can use fflush() to clear the stream (if you do want to do it) > -SC
You do not want to do it. fflush() is only defined for output-streams, and for update-streams after output operations. If you want to clear the stream from an unread line-rest, read the stream's contents up to and including the trailing '\n' of the line, for example with fgets(): char buffer[30]; /* or any other size */ do { fgets(buffer,sizeof buffer,stdin); } while(!strchr(buffer,'\n'));
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Will Ro #8 / 14
|
 trouble bulltproofing scanf
: Hello everyone, : I tried to read one string from the user using: : scanf("%s", UserResponse); : However, if the user types two words before hitting the enter key, the : second word seems to remain in the stream even though my format control : string contains only one %s. The problem arises in subsequent uses of scanf. : The string that is converted and assigned to the character array in the : latter scanf is not the string that the user just typed, but rather the : second srting that the user typed in the previous scanf. After the first : scanf the extra garbage tht the user types, that is not expected in the : format control string seems to stay in the stream. How do I clear out any : garbage that is in the stream? Don't start from there; bomb-proofing scanf() is a waste of time. Use fgets(), and either your own parser, or possibly sscanf(), to get the data you need. Will
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Michael Rubenste #9 / 14
|
 trouble bulltproofing scanf
Quote: >On Wed, 11 Mar 1998 23:25:18 -0500, Joshua Waxman
>>Actually, while this is true for ansi C, it is interesting to note that, >>according to Advanced C by Example, many compilers provide a hidden >>extension. >>scanf("%[a-zA-Z0-9 \t]s", my_string); >>will keep reading until it hits a character not in the set of characters >>in the brackets. Thus, this will read til the end of the line. >This is actually not a hidden extension. It has always been defined >for scanf in the C Standard. It is called a "scanset". The trailing >"s" in the string above is probably an errata, or you copied it from >the book wrong.
Actually, as written it has not been defined in the standard. From ISO 7.9.6.2: If a - character is in the scanlist and is not the first, nor the second where the first character is a ^, nor the last character, the behavior is implementation-defined. -- Michael M Rubenstein
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Lawrence Kir #10 / 14
|
 trouble bulltproofing scanf
Quote:
>> Hey, scanf() stops scanning at he first white space it encounters. Use a line>> get and use strtok() ... >> -SC >Actually, while this is true for ansi C, it is interesting to note that, >according to Advanced C by Example, many compilers provide a hidden >extension. >scanf("%[a-zA-Z0-9 \t]s", my_string); >will keep reading until it hits a character not in the set of characters >in the brackets. Thus, this will read til the end of the line.
Or it hits a %, (, ) & etc. etc. Scansets are standard although your use of - to indicate ranges is not. Also you'll need to remove the s at the end of your string. The way to read until the end of a line with a scanset is: scanf("%[^\n]%*c", my_string); However this still acts oddly in some circumstances and it is far better to read a whole line in with fgets(). -- -----------------------------------------
-----------------------------------------
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Will Ro #11 / 14
|
 trouble bulltproofing scanf
[...] : Or it hits a %, (, ) & etc. etc. Scansets are standard although your use of - : to indicate ranges is not. Also you'll need to remove the s at the end of : your string. The way to read until the end of a line with a scanset is: : scanf("%[^\n]%*c", my_string); : However this still acts oddly in some circumstances and it is far better to : read a whole line in with fgets(). I spent quite a while trying to get MSDOS to read lines reliably with scanf(), and gave up - Unix implementations seemed to work, so my guess is some sort of newline conversion problem. It happened with a couple of compilers. fgets() seems the way to go. BTW, if you must use scanf(), it's probably worth adding a width to the scanf() string; it needs all the help it can get. Will
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Stephan Wilm #12 / 14
|
 trouble bulltproofing scanf
Quote:
> On Wed, 11 Mar 1998 23:25:18 -0500, Joshua Waxman
> >scanf("%[a-zA-Z0-9 \t]s", my_string); > >will keep reading until it hits a character not in the set of characters > >in the brackets. Thus, this will read til the end of the line. > This is actually not a hidden extension. It has always been defined > for scanf in the C Standard.
I don't really know about the standard, but my compiler manual lists the range specification "[a-z]" as an ANSI-C *extension*. It says that for real ANSI-C compliance you'll have to list all the single characters explicitely. Stephan (initiator of the campaign against grumpiness in c.l.c)
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Lawrence Kir #13 / 14
|
 trouble bulltproofing scanf
Quote:
>[...] >: Or it hits a %, (, ) & etc. etc. Scansets are standard although your use of - >: to indicate ranges is not. Also you'll need to remove the s at the end of >: your string. The way to read until the end of a line with a scanset is: >: scanf("%[^\n]%*c", my_string); >: However this still acts oddly in some circumstances and it is far better to >: read a whole line in with fgets(). >I spent quite a while trying to get MSDOS to read lines reliably with >scanf(), and gave up - Unix implementations seemed to work, so my guess >is some sort of newline conversion problem. It happened with a couple >of compilers. fgets() seems the way to go.
It would be more interesting to know of Win95 and NT compilers have this sort of problem. Quote: >BTW, if you must use scanf(), it's probably worth adding a width to >the scanf() string; it needs all the help it can get.
Very true. -- -----------------------------------------
-----------------------------------------
|
Mon, 28 Aug 2000 03:00:00 GMT |
|
 |
Mark Brow #14 / 14
|
 trouble bulltproofing scanf
Quote:
> You can use fflush() to clear the stream (if you do want to do it)
I don't have a copy of the original question availible here (one of the reasons for quoting context), but the subject suggests that your advice may not work. As far as the standard is concerned, fflush() can't be used on input streams (or read/write streams where the last operation was a read). Sometimes implementations will define fflush(stdin) to throw away any characters waiting to be read, but you can't rely on this. A better solution is to work out what you're trying to get rid of with the fflush(), and explicitly get rid of this. --
http://www.tardis.ed.ac.uk/~broonie/ EUFS http://www.ed.ac.uk/~filmsoc/
|
Tue, 05 Sep 2000 03:00:00 GMT |
|
|
|