Search code examples
cfgetsscanfc89

fgets()/sscanf for input works well in function. When fnct left and returned to, there is extra input/line in stdin?


I realize similar questions have been asked, and answered. But after searching through them, I still haven't really found a solution to what I'm encountering.

Obviously I'm new to C.

I've read that fflush() is not good to use to flush the buffer, as it has undetermined results, depending on environment.

What I've got is a menu, that directs execution flow to a different function, which gets a choice from the user. This works successfully until, upon correct menu selection, execution flow is directed to another function, and then back to the main menu.

Here's what I've got...

int main ( void )
{
   Menu();

   return 0;
}

void Menu()
{
   printf( "\n" );
   printf( "1. Enter data\n" );
   printf( "2. Display data\n" );
   printf( "3. Quit\n" );

   ValidateChoice();

   return;
}

void ValidateChoice()
{
   char choice = '\0';

   do 
   {
      printf( "\nChoice: " );
      choice = GetChoice();
      switch (choice) 
      {
         case '1':
            EnterData();
            break;
         case '2':
            DisplayData();
            break;
         case '3':
            printf( "\nQuit\n" );
            break;
         default:
            break;
      }
      while (getchar() != '\n');
   } 
   while (choice != '3');
}

char GetChoice()
{
   char choice[CHOICE_LENGTH];
   char firstChar;

   fgets(choice, CHOICE_LENGTH, stdin); /*readline into string */
   sscanf(choice, "%c", &firstChar); /* get the first char of the string */

   return (firstChar);
}

void EnterData()
{
   printf( "\nEnterData() called\n" );
   Menu();

   return;
}

void DisplayData()
{
   printf( "\nDisplayData() called\n" );
   Menu();

   return;
}

If I don't call Menu() in EnterData() it works fine; continuing to prompt for a Selection (in getChoice()).

What can I do to allow flow out of GetChoice, into another function, and back to Menu() without having a bunch of characters left over in the buffer?

If someone could offer an explanation as to what I'm doing wrong, where I need to put additional loops to catch excess data, with an example or two, I would greatly appreciate it.

(Or point me in the direction of a post with the solution!)

Thanks a bunch.


Solution

  • What seems to happen is that you're constantly calling new methods each time you make a choice, instead of returning to the first Menu() call, which in my opinion should be ideal. We can follow the flow of execution to see this clearly.

    Assuming that main calls Menu, we have:

    main
      Menu
        ValidateChoice
          GetChoice (assume you return 1)
          EnterData
            Menu
              ValidateChoice
                GetChoice
                EnterData
                  Menu
                      ....
    

    This explains why you have to press 3 multiple times before finally exiting the program, or basically returning to main.

    One approach to solve this issue would be to make your ValidateChoice return 1 or 0 (for valid choice or exit), and keep a loop in your Menu method to verify this.

    For instance:

    void Menu(void)
    {
       do 
       {
           printf( "\n" );
           printf( "1. Enter data\n" );
           printf( "2. Display data\n" );
           printf( "3. Quit\n" );
    
       } while (ValidateChoice());
    
       return;
    }
    

    And have ValidateChoice as follows:

    int ValidateChoice()
    {
       char choice = '\0';
    
       printf( "\nChoice: " );
       choice = GetChoice();
       switch (choice) 
       {
          case '1':
             EnterData();
             break;
          case '2':
             DisplayData();
             break;
          case '3':
             printf( "\nQuit\n" );
             return 0;
          default:
             break;
       }
    
       return 1;
    }