记一次曲折的查错过程-关于二叉树的创建

学数据结构时书上有个先序创建二叉树的程序,下面是整体的代码(包含了创建代码和测试代码)。

#include<stdio.h>                                                                                                                                                             
#include<stdlib.h>
#include<string.h>
typedef struct BiNode{
    char data;
    struct BiNode *lchild,*rchild;
}BiNode;
//先序创建二叉树
void CreateBiTree(BiNode **T){
    char ch;
    scanf("%c",&ch);
    if(ch=='#'){
        *T=NULL;
    }else{
        (*T) = (BiNode *)malloc(sizeof(BiNode));
        (*T) -> data = ch;
        CreateBiTree(&((*T) -> lchild));
        CreateBiTree(&((*T) -> rchild));
    }
}
//先序遍历二叉树
void PreOrderTreverse(BiNode *T){
    if(T){
        printf("%c",T->data);
        PreOrderTreverse(T -> lchild);
        PreOrderTreverse(T -> rchild);
    }
}
//测试代码
int main(){
    BiNode *T;
    CreateBiTree(&T);
    PreOrderTreverse(T);
    printf("\n");
    return 0;
}

编译运行,测试时准备输入的数据为AB#D##C##,我是按如下方式输入的:
1. A回车
2. B回车
3. #回车
4. D回车
5. #回车
6. #回车
7. C回车
8. #回车
9. #回车
然后就发现程序没有结束,而是继续等待我输入字符,百思不得其解,于是打开gdb调试,首先又用-g选项编译了一下源程序来加入调试信息,然后gdb 文件名开始调试,下面是调试步骤。

(gdb) b 9
Breakpoint 1 at 0x80484a3: file testbitree.c, line 9.
(gdb) r
Starting program: /home/wpp/program/c/算法/tree/testbitree

Breakpoint 1, CreateBiTree (T=0xbffff1ec) at testbitree.c:11
11 scanf(“%c”,&ch);
(gdb) n
A
12 if(ch==’#’){
(gdb) n
15 (T) = (BiNode )malloc(sizeof(BiNode));
(gdb) n
16 (*T) -> data = ch;
(gdb) n
17 CreateBiTree(&((*T) -> lchild));
(gdb) n

Breakpoint 1, CreateBiTree (T=0x804b00c) at testbitree.c:11
11 scanf(“%c”,&ch);
(gdb) n
12 if(ch==’#’){

在执行到第二次scanf(上面最下面的 11 scanf)时,它并没有让我输入内容而是直接执行if(ch==’#’)这行代码。这就有点奇怪了,于是我用p ch打印了ch的值,发现结果是$1 = 10 ‘\n’,说明scanf读入了一个换行符。然后上网搜索scanf的用法,发现scanf每次会从输入缓冲区读取自己需要的部分,然后下次再从上次的位置开始读取需要的部分。拿上例来说吧,当我输入A回车时,输入缓冲区的内容是A\n,第一次调用scanf时它读取了自己需要的部分即A,然后指针指向\n,第二次又调用scanf时,它发现输入缓冲区还有内容,于是它就直接读了\n不给你再次输入的机会了。所以按我上面的方式来创建二叉树,这个程序会一直让你输入不会停止,因为永远达不到递归程序退出的条件。
正确的输入方式应该是: AB#D##C##回车
结果为:

AB#D##C##
ABDC

实际上这个问题困扰了我整整两天,上面对我的查错过程进行了很多简化,我只把我认为比较重要的点写出来了。看来我对c的掌握程度还远远不够,一个scanf就把我难住了,只能说革命尚未成功,同志仍需努力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值