最新常见错误类型和程序调试_第1页
最新常见错误类型和程序调试_第2页
最新常见错误类型和程序调试_第3页
最新常见错误类型和程序调试_第4页
最新常见错误类型和程序调试_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、常见错误和程序调试常见错误和程序调试1常见错误分析常见错误分析2程序调试程序调试 要真正学好要真正学好c、用好、用好c并不容易,并不容易,“灵活灵活”固然是固然是好事,但也使人难以掌握,尤其是初学者往往出好事,但也使人难以掌握,尤其是初学者往往出了错还不知怎么回事。了错还不知怎么回事。 c编译程序对语法的检查不如其他高级语言那样编译程序对语法的检查不如其他高级语言那样严格严格(这是为了给程序人员留下这是为了给程序人员留下“灵活灵活”的余地的余地)。因此,往往要由程序设计者自己设法保证程序的因此,往往要由程序设计者自己设法保证程序的正确性。需要不断积累经验,提高程序设计和调正确性。需要不断积累经

2、验,提高程序设计和调试程序的水平。试程序的水平。13.1常见错误分析常见错误分析 下面将初学者在学习和使用下面将初学者在学习和使用c语言语言(不包括不包括c+)时时容易犯的错误列举出来,以起提醒的作用。这些容易犯的错误列举出来,以起提醒的作用。这些内容在以前各章中大多已谈到,为便于查阅,在内容在以前各章中大多已谈到,为便于查阅,在本章中集中列举,供初学者参考,以此为鉴。本章中集中列举,供初学者参考,以此为鉴。 (1) 忘记定义变量忘记定义变量。如:。如:main()x=3; y=6; printf(%dn,x+y); (2) 输入输出的数据的类型与所用格式说明符不一输入输出的数据的类型与所用格

3、式说明符不一致致。 例如,若例如,若a已定义为整型,已定义为整型,b已定义为实型。已定义为实型。 a=3;b=4.5; printf(%f%dn,a,b); 编译时不给出出错信息,但运行结果将与原意不编译时不给出出错信息,但运行结果将与原意不符,输出为符,输出为 0.00000016402(3) 未注意未注意int型数据的数值范围型数据的数值范围。 一般微型计算机上使用的一般微型计算机上使用的c编译系统,对一个整型编译系统,对一个整型数据分配两个字节。因此一个整数的范围为数据分配两个字节。因此一个整数的范围为-215215-1,即,即-3276832767。常见这样的程序段:。常见这样的程序段

4、: int num; num=89101;printf(%d,num); 得到的却是得到的却是23565,原因是,原因是89101已超过已超过32767。两。两个字节容纳不下个字节容纳不下89101,则将高位截去。,则将高位截去。printf(%ld,num);请注意,如果只定义请注意,如果只定义num为为long型,而在输出时仍型,而在输出时仍用用“%d”说明符,仍会出现以上错误。说明符,仍会出现以上错误。对于超过整个范围的数,要用对于超过整个范围的数,要用long型,即改为型,即改为long intnum;num=89101; (4) 输入变量时忘记使用地址符输入变量时忘记使用地址符。如:

5、。如: scanf(%d%d,a,b); c语言要求指明语言要求指明“向哪个地址标识的单元送值向哪个地址标识的单元送值”。应写成应写成scanf(%d%d,&a,&b); (5) 输入时数据的组织与要求不符输入时数据的组织与要求不符。 用用scanf函数输入数据,应注意如何组织输入数据。函数输入数据,应注意如何组织输入数据。在在scanf输入时,除了格式控制符以外的其他字符输入时,除了格式控制符以外的其他字符必须按原样输入。必须按原样输入。假如有以下假如有以下scanf函数:函数: scanf(%d%d,&a,&b); 有人按下面的方法输入数据:有人按下面的方法

6、输入数据: 3,4 应该用以下方法输入:应该用以下方法输入: 3 4 如果如果scanf函数为函数为scanf(%d,%d,&a,&b); 应按以下方法输入:应按以下方法输入: 3,4 此时如果用此时如果用“34”反而错了。反而错了。 (6) 误把误把“=”作为作为“等于等于”比较符比较符。 在在c语言中,语言中,“=”是赋值运算符,是赋值运算符,“=”才是关系才是关系运算符运算符“等于等于”。如果写成。如果写成 if(a=b)printf(a equal to b); c编译系统将编译系统将(a=b)作为赋值表达式处理,将作为赋值表达式处理,将b的值的值赋给赋给a,然后判断,

7、然后判断a的值是否零,若为非零,则作的值是否零,若为非零,则作为为“真真”;若为零作为假。若为零作为假。 如果如果a的值为的值为3,b的值为的值为4,ab,按原意不应输出,按原意不应输出“ae q u a lt ob”。而现在输出。而现在输出“ae q u a lt o b”。 这种错误在编译时是检查不出来的,但运行结果这种错误在编译时是检查不出来的,但运行结果往往是错的。而且由于习惯的影响,程序设计者往往是错的。而且由于习惯的影响,程序设计者自己往往也不易发觉。自己往往也不易发觉。 (7) 语句后面漏分号语句后面漏分号。 c语言规定语句末尾必须有分号。分号是语言规定语句末尾必须有分号。分号是

8、c语句不语句不可缺少的一部分。这也是和其他语言不同的。有可缺少的一部分。这也是和其他语言不同的。有的初学者往往忘记写这一分号。如:的初学者往往忘记写这一分号。如: a=3 b=4 编译时,编译程序在编译时,编译程序在“a=3”后面未发现分号,就后面未发现分号,就把下一行把下一行“b=4”也作为上一行的语句的一部分,也作为上一行的语句的一部分,这就出现语法错误。如果用复合语句,漏写最后这就出现语法错误。如果用复合语句,漏写最后一个语句的分号,如:一个语句的分号,如:t=a; a=b; b=t (8) 在不该加分号的地方加了分号在不该加分号的地方加了分号。 例如:例如: if(ab); print

9、f(aislarger than bn); 本意为当本意为当ab时输出时输出“aislarger than b”的信息。的信息。 但由于在但由于在if(ab)后加了分号,因此后加了分号,因此if语句到此结束。语句到此结束。即当即当(ab)为真时,执行一个空语句。本来想为真时,执行一个空语句。本来想ab时时不输出上述信息,但现在不输出上述信息,但现在printf函数语句并不从属于函数语句并不从属于if语句,而是与语句,而是与if语句平行的语句。不论语句平行的语句。不论ab还是还是ab,都输出,都输出“a is larger than b”。 又如:又如:for(i=0;i10;i+); scan

10、f(%d,&x); printf(%dn,x*x); 本意为先后输入本意为先后输入10个数,每输入一个数后输出它个数,每输入一个数后输出它的平方值。由于在的平方值。由于在for()后加了一个分号,使循后加了一个分号,使循环体变成了空语句。只能输入一个整数并输出它环体变成了空语句。只能输入一个整数并输出它的平方值。的平方值。 总之,在总之,在if、for、while语句中,不要画蛇添足多语句中,不要画蛇添足多加分号。加分号。 (9) 对应该有花括弧的复合语句,忘记加花括弧对应该有花括弧的复合语句,忘记加花括弧。 如:如:sum=0;i=1;while(i=100) sum=sum+i;

11、i+; 本意是实现本意是实现1+2+100,即,即i。但上面的语句只。但上面的语句只是重复了是重复了sum+1的操作,而且循环永不终止。因为的操作,而且循环永不终止。因为i的值始终没有改变。错误在于没有写成复合语句的值始终没有改变。错误在于没有写成复合语句形式。因此形式。因此while语句的范围到其后第一个分号为语句的范围到其后第一个分号为止。语句止。语句“i+;”不属于循环体范围之内。应改不属于循环体范围之内。应改100i=0为为while(i=100) sum=sum+i; i+; (10) 括弧不配对括弧不配对。 当一个语句中使用多层括弧时常出现这类错当一个语句中使用多层括弧时常出现这类

12、错误,纯属粗心所致。如:误,纯属粗心所致。如: while(c=getchar()!=#) putchar(c); 少了一个右括弧。少了一个右括弧。 (11) 在用标识符时,忘记了大写字母和小写字母在用标识符时,忘记了大写字母和小写字母的区别的区别。 例如:例如:main()inta,b,c; a=2;b=3; c=a+b; printf(%d+%d=%,a,b,c); 编译时出错。编译程序把编译时出错。编译程序把a和和a认作是两个不同的认作是两个不同的变量名处理,同样变量名处理,同样b和和b,c和和c都分别代表两个不都分别代表两个不同的变量。同的变量。 (12) switch语句的各分支中漏

13、写语句的各分支中漏写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只起标

14、号的作用,只起标号的作用,而不起判断作用,因此在执行完第一个而不起判断作用,因此在执行完第一个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) 混淆字符和字符串的表示形式混淆字符和字符串的表示形式。c

15、har sex;sex=m; sex是字符变量,只能存放一个字符。而字符常量是字符变量,只能存放一个字符。而字符常量的形式是用单引号括起来的,应改为的形式是用单引号括起来的,应改为 sex=m; “m”是用双引号括起来的字符串,它包括两个字是用双引号括起来的字符串,它包括两个字符:符:m和和0,无法存放到字符变量,无法存放到字符变量sex中。中。 (14)没有注意函数参数的求值顺序没有注意函数参数的求值顺序。例如有以下语句:。例如有以下语句: i=3; printf(%d,%d,%dn,i,+i,+i);许多许多人认为输出必然是人认为输出必然是 3,4,5 实际不尽然。在实际不尽然。在turb

16、o 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); 程序出错有三种情况:程序出错有

17、三种情况: 语法错误语法错误。指违背了。指违背了c语法的规定,对这类错语法的规定,对这类错误,编译程序一般能给出误,编译程序一般能给出“出错信息出错信息”,并且告,并且告诉你在哪一行出错。只要细心,是可以很快发现诉你在哪一行出错。只要细心,是可以很快发现并排除的。并排除的。 逻辑错误逻辑错误。程序并无违背语法规则,但程序执。程序并无违背语法规则,但程序执行结果与原意不符。这是由于程序设计人员设计行结果与原意不符。这是由于程序设计人员设计的算法有错或编写程序有错,通知给系统的指令的算法有错或编写程序有错,通知给系统的指令与解题的原意不相同,即出现了逻辑上的混乱。与解题的原意不相同,即出现了逻辑上

18、的混乱。例如:前面第例如:前面第9条错误:条错误: sum=0;i=1;while(i=100) sum=sum+i; i+; 语法并无错误。但语法并无错误。但while语句通知给系统的信息是语句通知给系统的信息是当当i100时,执行时,执行“sum=sum+i;”。c系统无法辨系统无法辨别程序中这个语句是否符合作者的原意,而只能别程序中这个语句是否符合作者的原意,而只能忠实地执行这一指令。这种错误比语法错误更难忠实地执行这一指令。这种错误比语法错误更难检查。要求程序员有较丰富的经验。检查。要求程序员有较丰富的经验。 运行错误运行错误。程序既无语法错误,也无逻辑错误,。程序既无语法错误,也无逻

19、辑错误,但在运行时出现错误甚至停止运行。例如:但在运行时出现错误甚至停止运行。例如:int a ,b ,c;scanf(%d %d,&a,&b);c=b/a;printf(c=%dn,c); 输入输入a和和b的值,的值, 输出输出b/a的值,的值, 程序没有错。程序没有错。 但但是如果输入是如果输入a的值为的值为0, 就会出现错误。就会出现错误。 因此程序因此程序应能适应不同的数据,应能适应不同的数据, 或者说能经受各种数据的或者说能经受各种数据的“考验考验” , 具有具有“健壮性健壮性”。 写完一个程序只能说完成任务的一半写完一个程序只能说完成任务的一半(甚至不到一甚至不到一

20、半半)。调试程序往往比写程序更难,更需要精力、。调试程序往往比写程序更难,更需要精力、时间和经验。常常有这样的情况:程序花一天就时间和经验。常常有这样的情况:程序花一天就写完了,而调试程序二三天也未能完。有时一个写完了,而调试程序二三天也未能完。有时一个小小的程序会出错五六处,而发现和排除一个错小小的程序会出错五六处,而发现和排除一个错误,有时竟需要半天,甚至更多。希望读者通过误,有时竟需要半天,甚至更多。希望读者通过实践掌握调试程序的方法和技术。实践掌握调试程序的方法和技术。13.2程程 序序 调调 试试 所谓程序调试是指对程序的查错和排错。所谓程序调试是指对程序的查错和排错。 调试程序一般

21、应经过以下几个步骤:调试程序一般应经过以下几个步骤: (1) 先进行人工检查,即静态检查先进行人工检查,即静态检查。在写好一个程序。在写好一个程序以后,不要匆匆忙忙上机,而应对纸面上的程序进以后,不要匆匆忙忙上机,而应对纸面上的程序进行人工检查。这一步是十分重要的,它能发现程序行人工检查。这一步是十分重要的,它能发现程序设计人员由于疏忽而造成的多数错误。而这一步骤设计人员由于疏忽而造成的多数错误。而这一步骤往往容易被人忽视。有人总希望把一切推给计算机往往容易被人忽视。有人总希望把一切推给计算机系统去做,但这样就会多占用机器时间。而且,作系统去做,但这样就会多占用机器时间。而且,作为一个程序人员

22、应当养成严谨的科学作风,每一步为一个程序人员应当养成严谨的科学作风,每一步都要严格把关,不把问题留给后面的工序。为都要严格把关,不把问题留给后面的工序。为了更有效地进行人工检查,所编的程序应注意力了更有效地进行人工检查,所编的程序应注意力求做到以下几点:求做到以下几点:应当采用结构化程序方法编应当采用结构化程序方法编程,以增加可读性程,以增加可读性;尽可能多加注释,以帮助理尽可能多加注释,以帮助理解每段程序的作用解每段程序的作用;在编写复杂的程序时,不要在编写复杂的程序时,不要将全部语句都写在将全部语句都写在main函数中,而要多利用函数,函数中,而要多利用函数,用一个函数来实现一个单独的功能。这样既易于阅用一个函数来实现一个单独的功能。这样既易于阅读也便于调试,各函数之间除用参数传递数据这一读也便于调试,各函数之间除用参数传递数据这一渠道以外,数据间尽量少出现耦合关系,便于分别渠道以外,数据间尽量少出现耦合关系,便于分别检查和处理。检查和处理。 (2) 在人工在人工(静态静态)检查无误后,才可以上机调试。通检查无误后,才可以上机调试。通过上机发现错误称过上机发现错误称动态检查动态检查。在编译时给出语法错。在编译时给出语法错误的信息误的信息(包括哪一行有错以及错误类型包括哪一行有错以及错误类型),可以根,可以根据提示

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论