资源预览内容
第1页 / 共27页
第2页 / 共27页
第3页 / 共27页
第4页 / 共27页
第5页 / 共27页
第6页 / 共27页
第7页 / 共27页
第8页 / 共27页
第9页 / 共27页
第10页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
常见错误和程序调试1 常见错误分析 2 程序调试要真正学好C、用好C并不容易,“灵活”固然 是好事,但也使人难以掌握,尤其是初学者 往往出了错还不知怎么回事。 C编译程序对语法的检查不如其他高级语言那 样严格(这是为了给程序人员留下“灵活”的余 地)。因此,往往要由程序设计者自己设法保 证程序的正确性。需要不断积累经验,提高 程序设计和调试程序的水平。13.1 常见错误分析 下面将初学者在学习和使用C语言(不包括 C+)时容易犯的错误列举出来,以起提醒的 作用。这些内容在以前各章中大多已谈到, 为便于查阅,在本章中集中列举,供初学者 参考,以此为鉴。 (1) 忘记定义变量。如: main( )x=3;y=6;printf(“%dn “,x+y);(2) 输入输出的数据的类型与所用格式说明符 不一致。 例如,若a已定义为整型,b已定义为实型。a=3;b=4.5;printf(“%f %dn“,a,b);编译时不给出出错信息,但运行结果将与原 意不符,输出为 0.000000 16402(3) 未注意int型数据的数值范围。 一般微型计算机上使用的C编译系统,对一个 整型数据分配两个字节。因此一个整数的范围 为 -215215-1,即-3276832767。常见这样的程 序段:int num;num=89101;printf(“%d“,num); 得到的却是23565,原因是89101已超过32767 。两个字节容纳不下89101,则将高位截去。printf(“%ld“,num); 请注意,如果只定义num为long型,而在输出时仍 用“%d”说明符,仍会出现以上错误。对于超过整个范围的数,要用long型,即改为 long int num; num=89101;(4) 输入变量时忘记使用地址符。如: scanf(“%d%d“,a,b); C语言要求指明“向哪个地址标识的单元送值” 。应写成scanf(“%d%d“,(5) 输入时数据的组织与要求不符。 用scanf函数输入数据,应注意如何组织输入 数据。 在scanf输入时,除了格式控制符以外的 其他字符必须按原样输入。假如有以下scanf函数: scanf(“%d%d“,有人按下面的方法输入数据: 3,4应该用以下方法输入: 3 4 如果scanf函数为scanf(“%d,%d“,应按以下方法输入: 3,4 此时如果用“34”反而错了。(6) 误把“=”作为“等于”比较符。 在C语言中,“=”是赋值运算符,“=”才是关 系运算符“等于”。如果写成 if(a=b) printf(“a equal to b“); C编译系统将(a=b)作为赋值表达式处理,将b 的值赋给a,然后判断a的值是否零,若为非 零,则作为“真”;若为零作为假。 如果a的值为3,b的值为4,ab,按原意不应 输出“ae q u a lt ob”。而现在输出“ae q u a lt o b”。这种错误在编译时是检查不出来的,但运行 结果往往是错的。而且由于习惯的影响,程 序设计者自己往往也不易发觉。(7) 语句后面漏分号。 C语言规定语句末尾必须有分号。分号是C语 句不可缺少的一部分。这也是和其他语言不 同的。有的初学者往往忘记写这一分号。如 : a=3 b=4 编译时,编译程序在“a=3”后面未发现分号, 就把下一行“b=4”也作为上一行的语句的一部 分,这就出现语法错误。如果用复合语句, 漏写最后一个语句的分号,如: t=a;a=b;b=t(8) 在不该加分号的地方加了分号。例如: if(ab);printf(“a is larger than bn“); 本意为当ab时输出“a is larger than b”的 信息。 但由于在if(ab)后加了分号,因此if语句到此 结束。即当(ab)为真时,执行一个空语句。本 来想ab时不输出上述信息,但现在printf函数 语句并不从属于if语句,而是与if语句平行的语 句。不论ab还是ab,都输出“a is larger than b” 。又如:for(i=0;i10;i+);scanf(“%d“,printf(“%dn“,x*x); 本意为先后输入10个数,每输入一个数后输 出它的平方值。由于在for( )后加了一个分 号,使循环体变成了空语句。只能输入一个 整数并输出它的平方值。 总之,在if、for、while语句中,不要画蛇添 足多加分号。(9) 对应该有花括弧的复合语句,忘记加花括 弧。 如: sum=0;i=1;while(i=100)sum=sum+i;i+; 本意是实现1+2+100,即i。但上面的语 句只是重复了sum+1的操作,而且循环永不终 止。因为i的值始终没有改变。错误在于没有 写成复合语句形式。因此while语句的范围到 其后第一个分号为止。语句“i+;”不属于循环 体范围之内。应改100i=0为 while(i=100)sum=sum+i;i+; (10) 括弧不配对。当一个语句中使用多层括弧时常出现这 类错误,纯属粗心所致。如: while(c=getchar( )!=#) putchar(c);少了一个右括弧。(11) 在用标识符时,忘记了大写字母和小写 字母的区别。例如: main( )int a,b,c;a=2;b=3;C=A+B;printf(“%d+%d=%“,A,B,C); 编译时出错。编译程序把a和A认作是两个不 同的变量名处理,同样b和B,c和C都分别代 表两个不同的变量。(12) switch语句的各分支中漏写break语句。 switch(score)case 5:printf(“ery good!“);case 4:printf(“Good!“);case 3:printf(“Pass!“);case 2:printf(“Fail!“);defult:printf(“data error!“); 上述switch语句的作用是希望根据score(成绩) 打印出评语。但当score的值为5时,输出为 ery Good!Good!Pass!Fail!data error !原因是漏写了break语句。case只起标号的作 用,而不起判断作用,因此在执行完第一个 printf函数语句后接着执行第2、3、4、5个 printf函数语句。应改为 switch(score) case 5:printf(“erygood!“);break;case 4:printf(“Good!”); break;case 3:printf(“Pass!”); break;case 2:print(“Fail!”); break;defult:print(“data error!“);(13) 混淆字符和字符串的表示形式。 char sex;sex=“M“; sex是字符变量,只能存放一个字符。而字符 常量的形式是用单引号括起来的,应改为 sex=M; “M”是用双引号括起来的字符串,它包括两 个字符:M和0,无法存放到字符变量sex 中。(14)没有注意函数参数的求值顺序。例如有以下 语句: i=3; printf(“%d,%d,%dn“,i,+i,+i); 许多人认为输出必然是 3,4,5 实际不尽然。在Turbo C和其他一些C系统中输 出是 5,5,4因为这些系统是采取自右至左的顺序求函数参 数的值。先求出最右面一个参数(+i)的值为4, 再求出第2个参数(+i)的值为5,最后求出最左 面的参数(i)的值5。建议最好不用会引起二义性的用法。如果 在上例中,希望输出“3,4,5”时,可以改用 i=3; j=i+1; k=j+1; printf(“%d,%d,%dn“,i,j,k);程序出错有三种情况: 语法错误。指违背了C语法的规定,对这 类错误,编译程序一般能给出“出错信息”, 并且告诉你在哪一行出错。只要细心,是可 以很快发现并排除的。 逻辑错误。程序并无违背语法规则,但程 序执行结果与原意不符。这是由于程序设计 人员设计的算法有错或编写程序有错,通知 给系统的指令与解题的原意不相同,即出现 了逻辑上的混乱。例如:前面第9条错误:sum=0;i=1;while(i=100)sum=sum+i;i+; 语法并无错误。但while语句通知给系统的信 息是当i100时,执行“sum=sum+i;”。C系统 无法辨别程序中这个语句是否符合作者的原 意,而只能忠实地执行这一指令。这种错误 比语法错误更难检查。要求程序员有较丰富 的经验。 运行错误。程序既无语法错误,也无逻辑 错误,但在运行时出现错误甚至停止运行。 例如: int a ,b ,c; scanf(“%d %d“, c=b/a; printf(“c=%dn“,c); 输入a和b的值, 输出b/a的值, 程序没有错 。 但是如果输入a的值为0, 就会出现错误。 因此程序应能适应不同的数据, 或者说能经 受各种数据的“考验” , 具有“健壮性”。 写完一个程序只能说完成任务的一半(甚至不 到一半)。调试程序往往比写程序更难,更需 要精力、时间和经验。常常有这样的情况: 程序花一天就写完了,而调试程序二三天也 未能完。有时一个小小的程序会出错五六处 ,而发现和排除一个错误,有时竟需要半天 ,甚至更多。希望读者通过实践掌握调试程 序的方法和技术。13.2 程 序 调 试所谓程序调试是指对程序的查错和排错。 调试程序一般应经过以下几个步骤: (1) 先进行人工检查,即静态检查。在写好一个 程序以后,不要匆匆忙忙上机,而应对纸面上 的程序进行人工检查。这一步是十分重要的, 它能发现程序设计人员由于疏忽而造成的多数 错误。而这一步骤往往容易被人忽视。有人总 希望把一切推给计算机系统去做,但这样就会 多占用机器时间。而且,作为一个程序人员应 当养成严谨的科学作风,每一步都要严格把关 ,不把问题留给后面的工序。 为了更有效 地进行人工检查,所编的程序应注意力求做到以下几点:应当采用结构化程序方 法编程,以增加可读性;尽可能多加注释, 以帮助理解每段程序的作用;在编写复杂的 程序时,不要将全部语句都写在main函数中, 而要多利用函数,用一个函数来实现一个单独 的功能。这样既易于阅读也便于调试,各函数 之间除用参数传递数据这一渠道以外,数据间 尽量少出现耦合关系,便于分别检查和处理。 (2) 在人工(静态)检查无误后,才可以上机调试 。通过上机发现错误称动态检查。在编译时给 出语法错误的信息(包括哪一行有错以及错误 类型),可以根据提示的信息具体找出程序中 出错之处并改正之。应当注意的是:有时提示 的出错行并不是真正出错的行,如果在提示出错的行上找不到错误 的话应当到上一行再找。 如果系统提示的出错信息多,应当从上 到下逐一改正。有时显示出一大片出错信息 往往使人感到问题严重,无从下手。其实可 能只有一二个错误。例如,对所用的变量未 定义,编译时就会对所有含该变量的语句发 出出错信息。只要加上一个变量定义,所有 错误都消除了。 (3) 在改正语法错误(包括“错误”(error)和“警 告”(warning)后,程序经过连接(link)就得到 可执行的目标程序。运行程序,输入程序所需 数据,就可得到运行结果。应当对运行结果作 分析,看它是否符合要求。应当把程序可能遇 到的多种方案都一一试到。 (4) 运行结果不对,大多属于逻辑错误。对这 类错误往往需要仔细检查和分析才能发现。可 以采用以下办法: printf语句输出 设置断点Ctrl+F8 单步运行 F8 观测变量的值Ctrl +F7
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号