2017-10-06 20 views
1

我正在学习二叉搜索树。下面给出了一个程序执行基本BST操作的主要功能。所述option变量选其操作来执行用于switch带'char'类型输入的无限循环

int main() 
{ 
struct node* tree=NULL; 
struct node* ptr=NULL; 
struct node* ptrm=NULL; 
int val; 
int option; 
do 
{ 
    printf("\n1.Insert Node\n2.Preorder Traversal\n3.Postorder Traversal\n4.Inorder Traversal\n5.find_smallest_element\n6.find_largest_element\n7.Delete Element\n8.Total_nodes\n9.total_external_nodes\n10.total_internal_nodes\n11.Mirror image\n12.Exit\n"); 
    printf("\nEnter option"); 
    scanf("%d",&option); 
    switch(option) 
    { 
     case 1: 
      printf("\nEnter value to be inserted"); 
      scanf("%d",&val); 
      tree=insert_element(&tree,val); 
      printf("\n%d Inserted\n",val); 
      break; 
     case 2: 
      preorder(&tree); 
      break; 
     case 3: 
      postorder(&tree); 
      break; 
     case 4: 
      inorder(&tree); 
      break; 
     case 5: 
      ptr=find_smallest_element(&tree); 
      printf("\nSmallest element:%d",ptr->data); 
      break; 
     case 6: 
      ptr=find_largest_element(&tree); 
      printf("\nLargest element:%d",ptr->data); 
      break; 
     case 7: 
      printf("\nEnter value of element to be deleted"); 
      scanf("%d",&val); 
      tree=delete_node(&tree,val); 
      break; 
     case 8: 
      printf("\nTotal nodes%d",total_nodes(&tree)); 
      break; 
     case 9: 
      printf("\nTotal External nodes%d",total_external_nodes(&tree)); 
      break; 
     case 10: 
      printf("\nTotal Internal nodes%d",total_internal_nodes(&tree)); 
      break; 
     case 11: 
      ptrm=mirror_image(&tree); 

    } 
}while(option!=12); 
return 0; 

一切正常,当我给int数据作为用于“option'.However输入,当我给一个字符输入程序进入无限循环和显示选项列表反复。

为什么会发生这种情况?

+1

更多细节在这里:https://stackoverflow.com/a/1716066/7034621 – orhtej2

+0

@ orhtej2我加了if条件与scanf如jergason所述。我输入'a',它给出了Err ..输出,但是scanf仍然等待输入。如果我再次输入'2',会发生这种情况 - 输入选项a 错误。 。 。 输入要插入的值 2插入的 1.Insert节点 2.Preorder遍历 3.Postorder遍历 4.Inorder遍历 5.find_smallest_element 6.find_largest_element 7.Delete元 8.Total_nodes 9.total_external_nodes 10.total_internal_nodes 11.镜像 12.退出 输入选项' – zahlen

回答

1

既然你在scanf()格式字符串使用%d格式说明,

scanf("%d",&val); 

将成功地分配给val只有当一个整数被赋予作为输入。如果给出char而不是scanf()(它返回成功分配的数量)将在这里返回0并且将使char未被使用在输入缓冲区中。

在循环的下一次迭代,这char仍然会在输入缓冲区和scanf()最终会试图读取同样的事情,会不会分配给val一次。

这将继续并导致无限循环。

要解决此问题,请检查scanf()返回的值。如果不是1,清除输入缓冲区,直到下一个\n(新行),喜欢

int t; 
while((t=getchar()) != `\n`); 

这将从输入缓冲器消耗的旧数据,直到一个\n

然后,您可以使用continue语句跳过该循环的其余部分。

阅读关于getchar()here

1

这是为什么发生?

这个问题的根源干回如何scanf显示错误代码到您的代码(不是全部,因为你的代码丢弃它们),并预计该怎么办scanf("%d", &val)一路时非小数遇到输入;它会停止读取输入,可能会返回一个错误代码,但是您的代码将丢弃该代码并继续愉快地尝试删除由值指示的节点,该节点可能未被读取,导致稍后可能使用未初始化的变量...

有人拿猜测发挥到了极致,并认为这是适当的使用 fflush(stdin) 解决这个(它不是;不要做...)。你还没有去那么远,但我认为这可能是一个好主意,开始阅读你正在使用的功能的手册。 scanf手册是here。记下该URL,并意识到可以通过替换函数的名称来查找其他标准函数(C99和POSIX标准)。

您的代码必须做的第一件事是检查返回值,你的手册将在返回Document价值观部分;与大多数标准库函数一样,scanf具有返回值,您的代码应该很可能包含关于关键逻辑的关键逻辑!从那里,你如何处理错误是你的事。也许它可能是适当的使用一些简单但用户不友好的,如:

perror(scanf); 
exit(EXIT_FAILURE); 

你应该寻求简单的解决方案在可能情况下,为了避免过于复杂的事情。如果你的输入不是直接来自用户,或者你只是想要原型,你应该使用上面的解决方案。如果需要,您可以随时将exit(EXIT_FAILURE)更改为return EXIT_FAILURE;return 0;

如果您选择让程序继续运行,由于错字取决于您,有多少用户输入会被丢弃。到目前为止,最简单的办法是刚读(使用getchar();)单个字符...

你可以选择放弃一个字输入,像这样:scanf("%*s");*通知scanf读取和放弃输入,而不是读取和分配。

这些选项都不会让我觉得特别用户友好。如果您要努力创建一个用户友好的界面,您可能需要选择以下选项之一。

使用*分配抑制调节剂,也可以丢弃输入线,就像这样:

scanf("%*[^\n]"); 
getchar(); 

getchar();要丢弃换行符,我们预计是当一条线被丢弃时丢弃。

使用命令行参数为您的输入,而不是使用stdin(或其他文件/流)。一些令人惊讶的简单但多功能的菜单就是这样生成的,比如你的编译器向你展示的菜单。然后,您的输入模式将更改为使用更友好的功能,如sscanf,并且不将程序开发为保持打开的循环程序,而是作为即时程序在必要时随时执行,以便更新记录或不执行任何操作。

使用图形用户界面而不是控制台。那么,那个人真的会成为ol'noggin'的受害者,呃?您可以使用... 上下文菜单,例如Windows中的File/Edit/etc菜单,或者列表框(可能更易触摸屏)来提示您的用户进行选择。

我只想说,这看起来像功课,所以你可能没有设计一个更适当的用户界面......在这种情况下的选择,我使用*分配抑制修改作为建议根据以上(第一粗体部分)。