程序改错学习如钻探石油,钻得愈深,愈能找到知识的精髓2程序改错是个大悲大喜的过程,一天之内可以让人在悲伤的低谷和喜悦的巅峰之间跌宕起伏。如果改过了成千上万个错误,……改错很像侦破案件,有坏事发生了,而仅有的信息是它的确发生了。必须从结果出发,逆向思考学习如钻探石油,钻得愈深,愈能找到知识的精髓3程序改错改错的第一步是找出错误的根源,然后对症下药。寻找错误根源的过程称为调试。学习如钻探石油,钻得愈深,愈能找到知识的精髓4程序改错难点在于:症状和根源可能相隔很远症状可能在另一个错误被纠正后暂时消失症状并不是某个程序错误引发的,如误差累积症状可能时隐时现,如“内存泄露”很难产生完全一样的输入条件,难以恢复“错误的现场”学习如钻探石油,钻得愈深,愈能找到知识的精髓5程序中常见的出错原因(1)编译错误指在编译过程中发现的错误,通常属于语法错误,即编写的语句不符合C语言的语法规则。Undefinedsymbol'xxx'标识符xxx未定义Expressionsyntaxerror表达式语法错误Toofewparameterincall函数调用时的实参少于函数的形参学习如钻探石油,钻得愈深,愈能找到知识的精髓6程序中常见的出错原因(2)连接错误指在连接程序时发生的错误往往是由于写错了函数名等造成的。例如,将printf()写成了print()。学习如钻探石油,钻得愈深,愈能找到知识的精髓7程序中常见的出错原因(3)运行错误指在程序运行时发生的错误往往是由于语义上的错误造成的,即语句虽然合乎语法,但要求计算机去做不该做或做不到的事情。例如,当用0做除数时,运行后将显示“Divisionbyzero”错误提示信息。学习如钻探石油,钻得愈深,愈能找到知识的精髓8逻辑错误程序中有逻辑错时,不影响程序运行并得到运行结果,只是运行结果不正确。比较隐蔽,出错后不易查找。累加求和运算时,累加和变量忘记了赋初值;累乘运算时,累乘变量初值赋值为0;函数声明时的返回值数据类型与实际返回的数据类型不一致,导致自动类型转换数组下标越界(即超出了定义的范围);程序中存在死循环。程序中常见的出错原因(4)学习如钻探石油,钻得愈深,愈能找到知识的精髓9程序改错在程序设计语言的发展中,一个重要的努力方向就是想通过语言特征的设计帮助避免错误如下标范围检查,受限制的指针甚至完全取消指针,内存回收,强类型检查但没有任何语言能防止我们犯错误,每个为预防某些问题而设置的语言特征都会带给它自身额外的代价作为程序员应知道所用语言中有潜在危险和引起错误倾向的那些语言特征如goto语句,全局变量,无限制的指针,自动类型转换世界上最好的调试工具是那些有经验的人学习如钻探石油,钻得愈深,愈能找到知识的精髓10调试的基本方法“粗分细找”定位大致的范围:归纳、推理、二分、排除缩减输入数据设法找到能导致失败的最小输入采用注释的办法切掉一些代码减少有关的代码区域,调试无误后再将它们打开注释,即采用分而治之的策略将问题局部化利用调试工具逐条语句跟踪插入打印语句观看屏幕输出结果学习如钻探石油,钻得愈深,愈能找到知识的精髓11错误案例关系运算符==错写成赋值运算符=if(a=b)printf(yes);/*运行结果错误*/Warning:Possiblyincorrectassignmentinfunctionmainif(a==b)printf(yes);/*正确*/=表示赋值操作==表示比较是否相等的操作学习如钻探石油,钻得愈深,愈能找到知识的精髓12错误案例while后面有分号while(n100);{……n++;}循环体为空语句,导致死循环for后的表达式2省略for(n=1;;n++)/*死循环*/学习如钻探石油,钻得愈深,愈能找到知识的精髓13错误案例判断字符是大写字符或者小写字符('a'=ch='z')||('A'=ch='Z')/*不提示任何错误,但导致运行结果错误*/(ch='a'&&ch='z')||(ch='A'&&ch='Z')/*正确*/判断字符是数字字符'0'=ch='9'/*不提示任何错误,但导致运行结果错误*/ch='0'&&ch='9'/*正确*/学习如钻探石油,钻得愈深,愈能找到知识的精髓14错误案例数据类型由高向低赋值时,进行类型转换后导致信息丢失doublea,b;intsum;sum=a+b;VC下编译warningC4244:'=':conversionfrom'double'to'int',possiblelossofdata学习如钻探石油,钻得愈深,愈能找到知识的精髓15错误案例函数声明时的返回值类型与实际返回的数据类型不一致,导致自动类型转换doubleAdd(doublea,doubleb){intsum;……returnsum;}不提示任何错误intAdd(doublea,doubleb){doublesum;……returnsum;}warningC4244:'return':conversionfrom'double'to'int',possiblelossofdata学习如钻探石油,钻得愈深,愈能找到知识的精髓16错误案例数组下标越界inta[10],i,sum;for(i=1;i=10;i++)sum=sum+a[i];不提示任何错误,或者提示Written、read之类信息学习如钻探石油,钻得愈深,愈能找到知识的精髓17关于代码风格问题缩进(indent)—保证代码整洁、层次清晰的主要手段intisprime(intn){intk,i;k=sqrt((double)n);for(i=2;i=k;i++){if(n%i==0)return0;}return1;}#includemath.hintmain(){inti;for(i=2;i100;i++){if(isprime(i))printf(%d\t,i);}return0;}学习如钻探石油,钻得愈深,愈能找到知识的精髓18关于代码风格问题良好风格的程序应严格采用梯形层次对应好各层次intisprime(intn){intk,i;k=sqrt((double)n);for(i=2;i=k;i++){if(n%i==0)return0;}return1;}#includemath.hintmain(){inti;for(i=2;i100;i++){if(isprime(i))printf(%d\t,i);}return0;}学习如钻探石油,钻得愈深,愈能找到知识的精髓19程序版式现在的许多开发环境、编辑软件都支持“自动缩进”根据用户代码的输入,智能判断应该缩进还是反缩进,替用户完成调整缩进的工作VC中有自动整理格式功能只要选取需要的代码,按ALT+F8就能自动整理成微软的文件格式