【问题标题】:Infinite loop with 'char' type input带有“char”类型输入的无限循环
【发布时间】:2017-10-06 22:39:01
【问题描述】:

我正在学习二叉搜索树。下面给出的是执行基本 BST 操作的程序的主要功能。 option 变量选择为switch 执行哪个操作

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' 的输入时,一切正常。但是,当我输入 char 时,程序进入无限循环并重复显示选项列表。

为什么会这样?

【问题讨论】:

标签: c data-structures binary-search-tree


【解决方案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

【讨论】:

    【解决方案2】:

    为什么会这样?

    这个问题的根源可以追溯到 scanf 如何向您的代码指示错误代码(根本不是,因为您的代码会丢弃它们),以及当 non 时 scanf("%d", &val) 应该做什么-遇到十进制输入;它停止读取输入,可能返回一个错误代码,但您的代码会丢弃它并继续愉快地尝试删除由值指示的节点可能尚未读取,导致可能使用未初始化的以后变...

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

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

    perror(scanf);
    exit(EXIT_FAILURE);
    

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

    如果您选择让您的程序继续运行,有多少用户输入因拼写错误而被丢弃,这取决于您。到目前为止,最简单的选择是只读取一个字符(使用getchar();)...

    您可以选择丢弃单词的输入,例如:scanf("%*s");* 通知 scanf 读取并丢弃输入,而不是读取和分配。

    这些选项都没有让我觉得特别用户友好。如果您要努力制作用户友好的界面,您可能需要选择以下选项之一。

    使用* assignment-suppression 修饰符,您还可以丢弃输入的,如下所示:

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

    getchar(); 是丢弃换行符所必需的,我们希望在丢弃一行时丢弃它。

    使用命令行参数输入,而不是使用stdin(或其他文件/流)。以这种方式产生了一些令人惊讶的简单但多功能的菜单,例如您的编译器呈现给您的菜单。然后您的输入模式更改为使用更友好的函数,例如sscanf,并且将您的程序开发为保持打开状态的循环程序,而是作为一个即时程序,在必要时不时执行以更新记录或什么-不是。

    使用图形用户界面而不是控制台。嗯,那个真的很让人头疼,是吗?您可以使用... 上下文菜单,例如 Windows 中的文件/编辑/等菜单,或列表框(对触摸屏更友好)来提示您的用户进行选择。

    可以这么说,这看起来像是功课,所以你可能没有选择设计更合适的用户界面......在这种情况下,我建议使用@ 987654340@ assignment-suppression modifier 同上(第一个粗体部分)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-06
      • 2019-04-03
      • 2015-01-27
      • 2012-10-18
      • 2021-03-12
      • 1970-01-01
      • 2021-10-15
      • 2021-08-03
      相关资源
      最近更新 更多