Re: problems writing a printf/scanf function that handles both int and char input from the console

From: CBFalconer (cbfalconer_at_yahoo.com)
Date: 02/07/05


Date: Mon, 07 Feb 2005 00:54:34 GMT

Dawn Minnis wrote:
>
... snip ...
>
> Now, here comes the problem. When I enter in characters or symbols
> OTHER than integers it spirals into a never ending loop, that I can
> only exit by closing the command prompt window.
>
> So, can anyone take a quick look at this program and spot for me
> what I assume would be a glaringly obvious reason for this to
> happen? Such as the use of int for the function declaration, or
> %d when reading in the value. But I don't know how to correct the
> program so that it "accepts" all possibilities and then handles
> them.
>
... snip unindented code with over long lines ...
      (because it is too ugly to read)

In general, if you input values with scanf the char that terminates
the input or signals that the input cannot be done at all, remains
in the input stream. You have to get rid of it. Now lets change
your mechanism to something general (untested code, I am just
writing things down on the fly). Lets say you want to get one of
the chars in a specified string and reject everything else.
Meanwhile you want to prompt with something:

/* flush stdin until a '\n' or EOF occurs */
int flushln(void)
{
   int ch;

   while (('\n' != (ch = getchar())) && (EOF != ch)) continue;
   return ch;
} /* flushln */
   
int getone(const char *prompt, const char* allowed)
{
   int entered;

   while (1) {
      printf("%s", prompt); fflush(stdout);
      entered = getchar();
      flushln(); /* we only want the first line char */
      if (strchr(allowed, entered)) { /* acceptable */
         return entered; /* so return it */
      }
      else {
         printf("Invalid entry '%c', retry:\n", entered);
      }
   }
} /* untested */

Which encapsulates prompting, getting a char, testing validity, and
retrying until the entry is valid. All assuming I have made no
silly goofs above.

So, to get your 1 or 2, you would call:

   doMMorMV = getone("Enter 1 or 2 for M or V", "12");

which means you have the friendlier method of:

   doMMorMV = getone("Enter M for MM, or V for MV:", "MV");
or
   doMMorMV = getone("Enter M for MM, or V for MV:", "MmVv");

with confidence that you are getting something you expect and that
you have gobbled a complete input line. This simplifies life
greatly.
         

-- 
"If you want to post a followup via groups.google.com, don't use
 the broken "Reply" link at the bottom of the article.  Click on 
 "show options" at the top of the article, then click on the 
 "Reply" at the bottom of the article headers." - Keith Thompson


Relevant Pages