trouble bulltproofing scanf 
Author Message
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 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  
 
 [ 14 post ] 

 Relevant Pages 

1. Newbie: Trouble with scanf - HELP!!!

2. scanf troubles

3. Trouble with scanf() (newbie here)

4. printf/scanf trouble on SPARCstation

5. Troubles using C's scanf Function

6. trouble with scanf?

7. Scanf troubles

8. Trouble with scanf( "...%[^...]", ...)

9. scanf or n/scanf

10. newbie trouble: CoCreateInstance Error + IWebBrowser trouble...

11. (novice) I'm Having trouble scanf'ing a double ?

12. scanf("%s", string) or scanf("%s", &string)? Both work, yet...

 

 
Powered by phpBB® Forum Software