用于输入的fgets()/ sscanf在函数中运行良好。当fnct离开并返回时,stdin中有额外的输入/行?

时间:2014-02-05 16:38:13

标签: c fgets scanf c89

我意识到已经提出了类似的问题并得到了解答。但在搜索完它们之后,我仍然没有真正找到解决方案。

显然我是C.的新手。

我已经读过fflush()不适合用于刷新缓冲区,因为它具有未确定的结果,具体取决于环境。

我所拥有的是一个菜单,它将执行流程指向另一个功能,该功能可以从用户那里获得选择。这成功地工作,直到选择正确的菜单后,执行流程被定向到另一个功能,然后返回主菜单。

这就是我所拥有的......

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

如果我没有在EnterData()中调用Menu(),它可以正常工作;继续提示选择(在getChoice()中)。

我可以做些什么来允许从GetChoice流出到另一个函数,然后回到Menu()而不会在缓冲区中留下一堆字符?

如果有人可以解释我做错了什么,我需要在其中添加额外的循环来捕获多余的数据,只需要一两个例子,我将非常感激。

(或者指点解决方案的方向!)

非常感谢。

2 个答案:

答案 0 :(得分:1)

似乎发生的事情是,您每次做出选择时都会不断调用新方法,而不是返回第一个Menu()来电,我认为这应该是理想的。 我们可以按照执行流程清楚地看到这一点。

假设main来电Menu,我们有:

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

这解释了为什么在最终退出程序之前必须多次按3,或基本上返回主程序。

解决此问题的一种方法是让ValidateChoice返回10(有效选择或退出),并在Menu中保持循环验证这一点的方法。

例如:

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

   } while (ValidateChoice());

   return;
}

ValidateChoice如下:

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

答案 1 :(得分:0)

尝试使用您的代码 并进行以下修改:(请参阅注释)此mod允许选择 3 退出程序。

注意: 其他功能可能需要进行其他调试

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)
{

}