您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 企业财务 > C语言课件 第十四章 常见错误和程序调试
第14章常见错误和程序调试第14章常见错误和程序调试14.1常见错误分析14.2程序调试要真正学好C、用好C并不容易,“灵活”固然是好事,但也使人难以掌握,尤其是初学者往往出了错还不知怎么回事。C编译程序对语法的检查不如其他高级语言那样严格(这是为了给程序人员留下“灵活”的余地)。因此,往往要由程序设计者自己设法保证程序的正确性。调试一个C程序要比调试一个PASCAL或FORTRAN程序更困难一些。需要不断积累经验,提高程序设计和调试程序的水平。C语言有些语法规定和其他高级语言不同,学习过其他高级语言的读者往往按照使用其他高级语言的习惯来写C程序,这也是出错的一个原因。14.1常见错误分析下面将初学者在学习和使用C语言时容易犯的错误列举出来,以起提醒的作用。(1)忘记定义变量。如:main(){x=3;y=6;printf(%d\n,x+y);}(2)输入输出的数据的类型与所用格式说明符不一致。例如,若a已定义为整型,b已定义为实型。a=3;b=4.5;printf(%f%d\n,a,b);编译时不给出出错信息,但运行结果将与原意不符。(3)未注意int型数据的数值范围。一般微型计算机上使用的C编译系统,对一个整型数据分配两个字节。因此一个整数的范围为215~215-1,即-32768~32767。常见这样的程序段:intnum;num=89101;printf(%d,num);得到的却是23565,原因是89101已超过32767。两个字节容纳不下89101,则将高位截去。(4)输入变量时忘记使用地址符。如:scanf(%d%d,a,b);应写成scanf(%d%d,&a,&b);(5)输入时数据的组织与要求不符。用scanf函数输入数据,应注意如何组织输入数据。(6)误把“=”作为“等于”比较符。(7)语句后面漏分号。(8)在不该加分号的地方加了分号。例如:if(a>b);printf(aislargerthanb\n);(9)对应该有花括弧的复合语句,忘记加花括弧。(10)括弧不配对。(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)引用数组元素时误用了圆括弧。如:main(){inti,a(10);for(i=0;i<10;i++)scanf(%d,&a(i));}C语言中对数组的定义或引用数组元素时必须用方括弧。(13)在定义数组时,将定义的“元素个数”误认为是“可使用的最大下标值”。main(){inta[10]={1,2,3,4,5,6,7,8,9,10};inti;for(i=1;i<=10;i++)printf(%d,a[i]);}用a[10]就超出a数组的范围了。(14)对二维或多维数组的定义和引用的方法不对。main(){inta[5,4];…printf(%d,a[1+2,2+2]);…}(15)误以为数组名代表数组中全部元素。例如:main(){inta[4]={1,3,5,7};printf(%d%d%d%d\n,a);}(16)混淆字符数组与字符指针的区别。main(){charstr[4];str=Computerandc;printf(%s\n,str);}编译出错。str是数组名,代表数组首地址。在编译时对str数组分配了一段内存单元,因此在程序运行期间str是一个常量,不能再被赋值。(17)在引用指针变量之前没有对它赋予确定的值。main(){char*p;scanf(%s,p);(18)switch语句的各分支中漏写break语句。例如:switch(score){case5:printf(Verygood!);case4:printf(Good!);case3:printf(Pass!);case2:printf(Fail!);defult:printf(dataerror!);}上述switch语句的作用是希望根据score(成绩)打印出评语。但当score的值为5时,输出为VeryGood!Good!Pass!Fail!dataerror!(19)混淆字符和字符串的表示形式。charsex;sex=M;…sex是字符变量,只能存放一个字符。而字符常量的形式是用单引号括起来的,应改为sex='M';“M”是用双引号括起来的字符串,它包括两个字符:‘M’和‘\0’,无法存放到字符变量sex中。(20)使用自加(++)和自减(--)运算符时出的错误。例如:main(){intp,a[5]={1,3,5,7,9};p=a;printf(%d,*p++);}先执行p++,而p++的作用是先用p的原值,用完后使p加1。p的原值指向数组a的第0个元素a[0],因此*p就是第0个元素a[0]的值1。结论是先输出a[0]的值,然后再使p加1。如果是*(++p),则先使p指向a[1],然后输出a[1]的值。(21)有人习惯用传统的方式对函数形参进行声明,但却把对函数的形参和函数中的局部变量混在一起定义。如:max(x,y)intx,y,z;{z=x>y?x,y;return(z);}(22)所调用的函数在调用语句之后才定义,而又在调用前未加说明。①在main函数中增加一个对max函数的声明。②将max函数的定义位置调到main函数之前。(23)误认为形参值的改变会影响实参的值。(24)函数的实参和形参类型不一致。(25)不同类型的指针混用。main(){inti=3,*p1;floata=1.5,*p2;p1=&i;p2=&a;p2=p1;printf(%d,%d\n,*p1,*p2);}企图使p2也指向i,但p2是指向实型变量的指针,不能指向整型变量。指向不同类型的指针间的赋值必须进行强制类型转换。(26)没有注意函数参数的求值顺序。例如有以下语句:i=3;printf(%d,%d,%d\n,i,++i,++i);许多人认为输出必然是3,4,5实际不尽然。在TurboC和其他一些C系统中输出是5,5,4(27)混淆数组名与指针变量的区别。main(){inti,a[5];for(i=0;i<5;i++)scanf(%d,a++);…}企图通过a的改变使指针下移,每次指向欲输入数据的数组元素。它的错误在于不了解数组名代表数组首地址,它的值是不能改变的,用a++是错误的,应当用指针变量来指向各数组元素。(28)混淆结构体类型与结构体变量的区别,对一个结构体类型赋值。structworker{longintnum;charname[20];charsex;intage;};worker.num=187045;strcpy(worker.name,ZhangFun);worker.sex='M';worker.age=18;这是错误的,只能对变量赋值而不能对类型赋值。上面只定义了structworker类型而未定义变量。(29)使用文件时忘记打开,或打开方式与使用情况不匹配。例如,对文件的读写,用只读方式打开,却企图向该文件输出数据。例如:if((fp=fopen(test,r))==NULL){printf(cannotopenthisfile\n);exit(0);}ch=fgetc(fp);while(ch!='#'){ch=ch+4;fputc(ch,fp);ch=fget(fp);}对以“r”方式(只读方式)打开的文件,进行既读又写的操作,显然是不行的。此外,有的程序常忘记关闭文件,虽然系统会自动关闭所用文件,但可能会丢失数据。因此必须在用完文件后关闭它。以上只是列举了一些初学者常出现的错误,这些错误大多是对于C语法不熟悉之故。对C语言使用多了,比较熟练了,犯这些错误自然就会减少了。在深入使用C语言后,还会出现其他一些更深入、更隐蔽的错误。程序出错有三种情况:①语法错误。②逻辑错误。③运行错误。程序既无语法错误,也无逻辑错误,但在运行时出现错误甚至停止运行。例如:inta,b,c;scanf(%d%d,&a,&b);c=b/a;printf(c=%d\n,c);输入a和b的值,输出b/a的值,程序没有错。但是如果输入a的值为0,就会出现错误。因此程序应能适应不同的数据,或者说能经受各种数据的“考验”,具有“健壮性”。所谓程序调试是指对程序的查错和排错。调试程序一般应经过以下几个步骤:(1)先进行人工检查,即静态检查。(2)在人工(静态)检查无误后,才可以上机调试。(3)在改正语法错误(包括“错误”(error)和“警告”(warning))后,程序经过连接(link)就得到可执行的目标程序。14.2程序调试(4)运行结果不对,大多属于逻辑错误。对这类错误往往需要仔细检查和分析才能发现。可以采用以下办法:①将程序与流程图(或伪代码)仔细对照,如果流程图是正确的话,程序写错了,是很容易发现的。②如果实在找不到错误,可以采取“分段检查”的方法。③也可以用第9章介绍过的“条件编译”命令进行程序调试(在程序调试阶段,若干printf函数语句要进行编译并执行。④如果在程序中没有发现问题,就要检查流程图有无错误,即算法有无问题,如有则改正之,接着修改程序。⑤有的系统还提供debug(调试)工具,跟踪流程并给出相应信息,使用更为方便,请查阅有关手册。总之,程序调试是一项细致深入的工作,需要下功夫、动脑子、善于累积经验。上机调试程序的目的决不是为了“验证程序的正确性”,而是“掌握调试的方法和技术”。
本文标题:C语言课件 第十四章 常见错误和程序调试
链接地址:https://www.777doc.com/doc-3213195 .html