scanf,fgets,fgetc跳过内部循环

时间:2015-03-25 05:18:15

标签: char stdin scanf fgets fgetc

我试图制作一个递归菜单。

此程序稍后将使用树(hojanodo),这就是我跟踪根的原因。

问题:出于某种原因,fgets / fgetc在第二次运行时被递归到内部,为什么会发生这种情况? 我希望用户输入1,2或3.(int) 对此有什么解决方法?这是实现菜单的最佳方式吗?

这就是我现在所拥有的:(它编译并运行,因此您可以测试它,但实际上并不像我想的那样......)

    #include<stdio.h>
#include<stdlib.h>

typedef struct node{
  char ch;
  int i;
  struct node *left;
  struct node *right;
}hojaNodo;


int  handle_menu(int eventHandler, hojaNodo **root);
int opcion_menu();
char get_symbol();
int get_userMenuInput();
int intro();

int main(){

  hojaNodo *treeRoot = NULL;
  intro();
  // system("clear");
  handle_menu(opcion_menu(), &treeRoot);

  return 0;
}

int opcion_menu(){
  int userOption;   

  printf("1.Agrega un Simbolo.\n");
  printf("2.Listar Codigo\n");
  printf("3.Exit");

    userOption = get_userMenuInput();
    printf("User: %d",userOption);

  if(userOption < 4 && userOption > 0){
    return userOption;
  }
  else
    return -1;

}//eof opcion_menu

int handle_menu(int userOption,hojaNodo **root){
  hojaNodo *tempRoot = NULL;
  tempRoot = *root;
   int valor;
   char simbol;

  switch(userOption){
  case 1:

    simbol = get_symbol();
    printf("Simbol: %c", simbol);

    break;
  case 2:
     printf("List Nodes\n");
    break;
  case 3:
    printf("Exit");
    userOption = -1;
    // destroy_tree(root);
    break;
    default:
    printf("userOption Error, Bye!");
    break;
  }//eof switch
  if(userOption != -1)
  handle_menu(opcion_menu(),&tempRoot);
  // return userOption;
  return -1;
}//eof menu()



char get_symbol(){

    /*char userKey[3]
    fgets(userKey,len,stdin);*/
    char simbolo;
    printf("Give me a symbol.");
    simbolo = fgetc(stdin);
    return simbolo;
}

int get_userMenuInput(){

     char userKey[3];
     int userOption;
    size_t len;
     len = sizeof(userKey);
     fgets(userKey,len,stdin);
     userOption = atoi(userKey);
  //printf("User Option: %d\n", userOption);
  return userOption;
}

2 个答案:

答案 0 :(得分:0)

除了与递归和其他建议有关的所有评论之外,请检查一下。 fgets()函数需要刷新输入流。可以使用fflush()或fgetc()来完成。

一个简单的解决方案是:

在功能中:

  

int opcion_menu(){

...
fgets(userKey,2,stdin);
fgetc(stdin); // Add this statement

同样在功能:

  

int handle_menu(int userOption,hojaNodo ** root)

            case 1:
                    printf("Give me a choice : ");
                    fgets(userKey,2,stdin);
                    fgetc(stdin); // add this statement

fgets从流中读取最多一个小于大小的字符,并将它们存储到string指向的缓冲区中。这将导致仍需要刷新输入流中的换行符。如果没有从输入流中读取这个换行符,那么这将成为下一个fgets函数的输入,最终它将跳过fgets(因为它已经输入了换行符)

fgetc(stdin)将清除这些额外的换行符。

答案 1 :(得分:0)

我不知道这是否可以帮助任何人。 在我的情况下,我必须“免费”#39;来自char的缓冲区具有此功能:

void clean(){
char cTemp;
while((cTemp = getchar()) !=  '\n')
;
}

我不确定为什么会有效,但确实如此(如果有的话,请将其添加到我的答案中)。 我在调用get_userOption();

之前调用它