调试程序的利器—printf
2016-04-08 11:05
183 查看
声明:这些内容主要是面向C语言的初学者,尤其是正在学习C语言的学生。
当排除了所有的语法错误,但运行结果却不正确时,很多初学者往往束手无策,只好求助老师了,“老师,我这个程序没错,但结果不正确”,这是在上机课上经常听到的声音。初学者缺乏经验,也缺乏耐心。殊不知每个程序员都是在不断的和错误斗争的过程中成长起来的,调试程序的过程有时候是很痛苦的,但发现错误原因的那一刻,幸福却是满满的。
调试程序的方法很多,但对于初学者来说,用好printf基本就能解决大多数问题,可以说简单实用。当程序编译报错时,我们一般能很快解决问题,那是因为编译器明确地告诉你哪一行有问题。但当编译没错,程序运行结果出错时,没有人告诉我们错在哪里,这时候就需要自己想办法去确定错误的位置。printf函数就是用来确定错误位置的一把利器。运行结果不对时,错误可能发生在程序的任意一行,我们可以从打印结果的代码开始倒着往回寻找,适当的打印出一些中间结果(变量或者表达式的值),如果发现某个中间结果和你期望的值不同时,就进一步去检查和分析与这个中间结果相关的语句,有必要的话可以继续输出一些变量进行观察。通过这种不断打印中间结果进行观察和分析的方法,往往很快就能定位错误的位置。下面通过一个例子来说明这种方法。
例: 计算1-1/2+1/3-1/4+...+1/99-1/100+...,直到最后一项的绝对值小于1E-4为止。
某位学生的程序:
程序的运行结果如图1所示,sum = 0.000000,显然这个结果是错误的。
图1. 错误的运行结果
分析:
按照我们上面所说的方法,输出一些中间结果来观察和分析。离打印sum的语句最近的是while循环,循环体的最后一句是n++; 我们就先输出n的值来看看,即在循环体的最后加一句printf(“n=%d”,n); 程序如下:
你期望的结果一定是一列很长的n= 1 n=2 n=3…,因为我们知道随着循环的不断进行,n的值一直会增1。然而,重新运行程序后得到的结果居然和图1一模一样,一个n都没有被输出,sum依然为0。这和我们的期望相去甚远,但高兴的是,离发现问题很近了。为什么一个n都没有被输出来呢,n至少还有一个初值1呀。仔细思考,只有一种可能:while循环一次都没执行。while循环一次都不执行的原因也很容易想到,while语句中的循环条件第一次就是假。这时候我们就能定位错误的位置了:循环条件有问题!通过增加一个printf函数我们就成功定位了错误的位置。接下来,就是仔细研究循环条件了,题目中说“直到最后一项的绝对值小于1E-4为止”,那意思就是说当某一项的绝对值小于1E-4时,循环结束,反过来就是,要让循环得以继续,每一项的绝对值必须大于等于1E-4。说到这里,相信大家明白了,源程序中循环条件写反了,正确的应该是:while((1.0/n)>=1E-4)。请自己修改程序并运行。
上面的例子程序比较短,加了一个printf就能确定错误的位置,如果程序较长的话,就需要增加多个printf来打印中间结果,并且逐段去排查。这种方法很灵活,上面的例子中也不一定要打印n的值,也可以打印sum或者term的值来观察,可以得到同样的结论,大家需要多做练习来体会这种简单但强大的调试程序的方法。
当排除了所有的语法错误,但运行结果却不正确时,很多初学者往往束手无策,只好求助老师了,“老师,我这个程序没错,但结果不正确”,这是在上机课上经常听到的声音。初学者缺乏经验,也缺乏耐心。殊不知每个程序员都是在不断的和错误斗争的过程中成长起来的,调试程序的过程有时候是很痛苦的,但发现错误原因的那一刻,幸福却是满满的。
调试程序的方法很多,但对于初学者来说,用好printf基本就能解决大多数问题,可以说简单实用。当程序编译报错时,我们一般能很快解决问题,那是因为编译器明确地告诉你哪一行有问题。但当编译没错,程序运行结果出错时,没有人告诉我们错在哪里,这时候就需要自己想办法去确定错误的位置。printf函数就是用来确定错误位置的一把利器。运行结果不对时,错误可能发生在程序的任意一行,我们可以从打印结果的代码开始倒着往回寻找,适当的打印出一些中间结果(变量或者表达式的值),如果发现某个中间结果和你期望的值不同时,就进一步去检查和分析与这个中间结果相关的语句,有必要的话可以继续输出一些变量进行观察。通过这种不断打印中间结果进行观察和分析的方法,往往很快就能定位错误的位置。下面通过一个例子来说明这种方法。
例: 计算1-1/2+1/3-1/4+...+1/99-1/100+...,直到最后一项的绝对值小于1E-4为止。
某位学生的程序:
程序的运行结果如图1所示,sum = 0.000000,显然这个结果是错误的。
图1. 错误的运行结果
分析:
按照我们上面所说的方法,输出一些中间结果来观察和分析。离打印sum的语句最近的是while循环,循环体的最后一句是n++; 我们就先输出n的值来看看,即在循环体的最后加一句printf(“n=%d”,n); 程序如下:
你期望的结果一定是一列很长的n= 1 n=2 n=3…,因为我们知道随着循环的不断进行,n的值一直会增1。然而,重新运行程序后得到的结果居然和图1一模一样,一个n都没有被输出,sum依然为0。这和我们的期望相去甚远,但高兴的是,离发现问题很近了。为什么一个n都没有被输出来呢,n至少还有一个初值1呀。仔细思考,只有一种可能:while循环一次都没执行。while循环一次都不执行的原因也很容易想到,while语句中的循环条件第一次就是假。这时候我们就能定位错误的位置了:循环条件有问题!通过增加一个printf函数我们就成功定位了错误的位置。接下来,就是仔细研究循环条件了,题目中说“直到最后一项的绝对值小于1E-4为止”,那意思就是说当某一项的绝对值小于1E-4时,循环结束,反过来就是,要让循环得以继续,每一项的绝对值必须大于等于1E-4。说到这里,相信大家明白了,源程序中循环条件写反了,正确的应该是:while((1.0/n)>=1E-4)。请自己修改程序并运行。
上面的例子程序比较短,加了一个printf就能确定错误的位置,如果程序较长的话,就需要增加多个printf来打印中间结果,并且逐段去排查。这种方法很灵活,上面的例子中也不一定要打印n的值,也可以打印sum或者term的值来观察,可以得到同样的结论,大家需要多做练习来体会这种简单但强大的调试程序的方法。
相关文章推荐
- Eclipse中设置在创建新类时自动生成注释
- 深入理解RunLoop
- 操作系统的发展与分类
- mysql5的日常记录
- 安卓开发设置Tabhost位于底部的方法
- 点击table中的一行获取这一行中的其他数据
- Linux test --检查文件和比较值
- Linux telnet --基于TELNET协议的远程登录工具
- 信号量Semaphore的使用Demo
- Java ConcurrentModificationException异常原因和解决方法
- 自己总结
- 红茶一杯话Binder(ServiceManager篇)
- C++实现MySQL分页查询
- android 之listview(一)
- canvas API ,通俗的canvas基础知识(二)
- 汉堡包
- Linux文件处理命令
- 根据页面edittext的内容控制按钮可点击状态
- xoyojank 的 UE4中的DynamicTexture数据更新
- 构造方法,super,this