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

StackOverflow https://stackoverflow.com/questions/21583082

  •  07-10-2022
  •  | 
  •  

سؤال

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.

هل كانت مفيدة؟

المحلول

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;
}

نصائح أخرى

Try your code with the following modifications: (see comments) This mod allows selection of 3 to exit program.

Note: Other debugging may be required for additional functionality

int     main()
{
    EnterData();
}

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

   ValidateChoice();

   return;
}

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

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

char GetChoice(void)
{
   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(void)
{
   printf( "\nEnterData() called\n" );
   Menu();

   return;
}

void DisplayData(void)
{

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top