扫雷英雄榜 - C常见错误及解决方案


扫雷英雄榜——C常见错误及解决方案 王牌9 1 扫雷英雄榜——C常见错误及解决方案 以下“解决方案”中的内容对应的是“错误举例”中内容的解决方法。 1. 把“=”误当作“==”使用  错误举例 ect.top = rect.bottom) { MessageBox(hwnd, "Invalid rectangle!", NULL, MB_OK | MB_ICONERROR); }  解决方案 因为条件判断误写成了赋值,上面的判断将永远为真,除非 rect.bottom 为零。 比较低级却又难以发现的错误。说它低级是因为它属于再基本不过的语法问题;而它之 所以难以发现是因为它不会产生编译错误,唯有在调试过程中跟踪执行才会发现。通常它导 致的后果是某一个条件判断失效或者进一步导致死循环。 2. 使用已释放了的指针  错误举例 最常出现在释放链表时。初学者容易这样写: while (p) { delete p; p = p->next; }  解决方案 这样是很危险的。正确的方法是: while (p) { q = p->next; delete p; p = q; C从入门到精通 2 } 3. 在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。  错误举例 main() {staticinta[10]={1,2,3,4,5,6,7,8,9,10}; printf( "%d ",a[10]); }  解决方案 C 语言规定:定义时用 a[10],表示 a 数组有 10 个元素。其下标值由 0 开始,所以数组 元素 a[10]是不存在的。 4. 输入数据时,企图规定精度。  错误举例 scanf( "%7.2f ",&a);  解决方案 这样做是不合法的,输入数据时不能规定精度。 5. 输入数据的方式与要求不符。  错误举例 scanf( "%d%d ",① &a,&b); 输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法: 3,4  输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键 tab。 scanf( "%d,%d ",&a,&b);② C 规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时 应输入与这些字符相同的字符。下面输入是合法的: 3,4  此时不用逗号而用空格或其它字符是不对的。 34 3  :4  又如: 扫雷英雄榜——C常见错误及解决方案 王牌9 3 scanf( "a=%d,b=%d ",&a,&b); 输入应如以下形式: a=3,b=4 6. 混淆字符和字符串的表现形式  错误举例 char sex; sex=”M”; …  解决方案 sex 为字符变量,只能存放一个字符。而字符常量的形式是用单撇号括起来的,应改为 sex=‘M’; “M”使用双撇号括起来的字符串,它包括两个字符:‘M’和‘\0’,无法存放到字符变 量 sex 中。 7. 赋值写法错误:  错误举例 /*this program is wrong*/ int main(void) { int x, *p; x = 10; p = x; printf("%d", *p); return 0; }  解决方案 这里原本是想输出 x 的内容,结果却没有达到效果,应该是 p = &x。 C从入门到精通 4 8. 错记“<<”与“+”的优先级  错误举例 比如计算 n*5: result = n << 2 + n;  解决方案 因为“<<”和“>>”相当于乘除 2^N,所以容易误认为它们的优先级高于加减运算,其 实不然。当把它们跟加减法一起用的时候一定要注意。 这样就错了,应该用括号: result = (n << 2) + n; 9. 书写标识符时,忽略了大小写字母的区别。  错误举例 main() { inta=5; printf( "%d ",A); }  解决方案 编译程序把 a 和 A 认为是两个不同的变量名,而显示出错信息。C 认为大写字母和小写 字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。 10. 操作越界:  错误举例 int first[10], second[10]; int *p, t; p = first; for(t = 0; t < 20; ++t)*p++ = t;  解决方案 这段代码在某些编译器下面可能可以正常工作, 但是其实是错误的. first 只有 10 个元素, 但是循环却取到第 20 个去了, 虽然可能用户是试图给 second 赋值, 但是 c 语言并不保证 两个数组在内存里面是连续的。 扫雷英雄榜——C常见错误及解决方案 王牌9 5 11. 定义数组时误用变量。  错误举例 intn; scanf( "%d ",&n); inta[n];  解决方案 数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即 C 不允许对数 组的 大小作动态定义。 12. 头文件重复包含  错误举例 当你的工程越来越庞大时,头文件的管理也麻烦起来。经常遇到这样的情况:在编译一 个源文件时,发现因为没有包含某个头文件而导致“符号未定义”之类的错误,于是你加入了 这个头文件,可是这个头文件中又包含另外一个头文件,而那个头文件原先已经加在源文件 中了,结果产生了“符号重定义”错误,这样你又不得不把这个重复包含的文件去掉。  解决方案 为了避免出现“符号重定义”错误,可以采取条件编译技术。在创建头文件时,首先为 这个头文件定义一个唯一的标识(假设是_SOME_SYMBOL_),然后在头文件的开头及结尾 加上几行代码,像下面这样: #ifndef _SOME_SYMBOL_ #define _SOME_SYMBOL_ ....(头文件代码) #endif 第一行语句判断是否定义了符号 _SOME_SYMBOL_,如果没有,说明本次编译尚未扫 描过这个头文件,于是编译正常进行,并且定义符号_SOME_SYMBOL_,以标明文件已被扫 描过一次;反之,如果文件已被包含过一次,_SOME_SYMBOL_就有了定义,于是条件编译 语句使编译器跳过整个文件。 如果所有的头文件都这样处理,就可以大量减少出现“符号重定义”错误的机率。 13. 将字符常量与字符串常量混淆。  错误举例 charc; C从入门到精通 6 c= "a ";  解决方案 在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符, 字符串常量是一对双引号括起来的字符序列。C 规定以“\”作字符串结束标志,它是由系统自 动加上的,所以字符串“a”实际上包含两个字符:‘a '和‘\ ',而把它赋给一个字符变量是不行 的。 14. 多次循环使用一个指针的时候忘记赋初值:  错误举例 /*this program is wrong*/ int main(void) { char *p1; char s[80]; p1 = s; do{ gets(s); while(*p1) printf(" %d", *p1++); }while(strcmp(s, "done")); return 0; }  解决方案 程序想重复利用缓冲区s来保存每次输入的字符串, 但是没次循环结束后,忘记把p1置回 到缓冲开始的位置, 造成很危险的故障. 正确做法: /*this program is now correct.*/ int main(void) { char *p1; char s[80]; do{ p1 = s; gets(s); while(*p1) printf(" %d", *p1++); 扫雷英雄榜——C常见错误及解决方案 王牌9 7 }while(strcmp(s, "done")); return 0; } 15. 对应该有花括号的复合语句,忘记加花括号。  错误举例 sum=0; i=1; while(i<=100) sum=sum+I; i++;  解决方案 错误在于没有写成复合语句的形式。因此,while 语句的范围到最后一个分号为止。语 句“i++;”不属于循环体范围之内。应该为 while(i<=100) { sum=sum+I; i++; } 16. 忽略了变量的类型,进行了不合法的运算。  错误举例 main() { floata,b; printf( "%d ",a%b); }  解决方案 %是求余运算,得到 a/b 的整余数。整型变量 a 和 b 可以进行求余运算,而实型变量则 不允许进行“求余”运算。 C从入门到精通 8 17. 错误的比较两个指针:  错误举例 char s[80], y[80]; char *p1, *p2; p1 = s; p2 = y; if(p1 < p2)...  解决方案 不要试图通过一个对象的指针来比较对向的内容。 18. switch 语句中漏写 break 语句。  错误举例 switch(grade) {case'A ':printf( "85~100\n "); case'B ':printf( "70~84\n "); case'C ':printf( "60~69\n "); case'D ':printf( " <60\n "); default:printf( "error\n ");  解决方案 由于漏写了 break 语句,case 只起标号的作用,而不起判断作用。因此,当 grade 值为 A 时,printf 函数在执行完第一个语句后接着执行第二、三、四、五个 printf 函数语句。正确写 法应在每个分支后再加上“break;”。例如 case'A ':printf( "85~100\n ");break; 19. printf()/scanf()中类型不匹配  错误举例 虽然 WINDOWS 下一般不用这两个函数了,但是与之类似的 sprintf()/sscanf()和 fprintf()/fscanf()还是经常使用的。 如果格式字串中说明的变量类型与后面的参数列表不一致,printf()将导致输出结果混乱, scanf()有可能导致程序执行结果不稳定,甚至导致非法操作。 扫雷英雄榜——C常见错误及解决方案 王牌9 9  解决方案 初学者或许会以为类型不一致也无所谓,因为 C 语言可以自动进行类型转换。这种想法 是错误的。类型转换是在编译时已知原类型和所需类型时由编译器产生代码来完成的,而格 式字串对编译器来说只是一般的字串,编译器并不理解其中的含义,也就无法知道其中的类 型信息;另一方面,从 printf()/scanf()函数内部,虽然可以理解格式字串,但却无法知道后面 变量表中的各变量的类型,对 printf()/scanf()内部来说,变量表只呈现为一段连续的单元字节, 唯一可知的是这段连续单元的起始地址。 20. 忘记加分号。  错误举例 a=1 b=2  解决方案 分号是 C 语句中不可缺少的一部分,语句末尾必须有分号。 编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部 分,这就会出现语法错误。改错时,有时在被指出有错的一行中\未发现错误,就需要看一下 上一行是否漏掉了分号。 { z=x+y; t=z/100; printf( "%f ",t); } 对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和 PASCAL 不同的)。 21. 输入输出的数据类型与所用格式说明符不一致。  错误举例 a 已定义为整型,b 定义为实型 a=3;b=4.5;  解决方案 printf( "%f%d\n ",a,b); 编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。 C从入门到精通 10 22. 指针未初始化  错误举例 int *p; *p = 0;  解决方案 DOS 下,这将有可能导致死机;WINDOWS 下将导致一个非法操作。切记,使用指针前 一定要初始化,使它指向一个确实分配了的空间。 23. 忽视了 while 和 do-while 语句在细节上的区别。  错误举例 (1)main() {inta=0,I; scanf( "%d ",&I); while(I <=10) {a=a+I; I++; } printf( "%d ",a); } (2)main() {inta=0,I; scanf( "%d ",&I); do {a=a+I; I++; }while(I <=10); printf( "%d ",a); }  解决方案 可以看到,当输入 I 的值小于或等于 10 时,二者得到的结果相同。而当 I> 10 时,二者 结果就不同了。因为 while 循环是先判断后执行,而 do-while 循环是先执行后判断。对于大 于 10 的数 while 循环一次也不执行循环体,而 do-while 语句则要执行一次循环体。 扫雷英雄榜——C常见错误及解决方案 王牌9 11 23. 输入字符的格式与要求不一致。  错误举例 scanf( "%c%c%c ",&c1,&c2,&c3);  解决方案 在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。 如输入 abc  字符“a”送给 c1,字符“”送给 c2,字符“b”送给 c3,因为%c 只要求读入一个字符,后 面不需要用空格作为两个字符的间隔。 24. 括号不配对。  错误举例 while((c=gerchar()!=’#’) putchar(c);  解决方案 当一个语句中使用多层括号时常出现这类错误,纯属粗心所致。上例少了一个括号。 25. 输入变量时忘记加地址运算符“&”。  错误举例 inta,b; scanf( "%d%d ",a,b);  解决方案 这是不合法的。Scanf 函数的作用是:按照 a、b 在内存的地址将 a、b 的值存进去。“&a” 指 a 在内存中的地址。 26. 忘记定义变量  错误举例 void main() { x=3; C从入门到精通 12 y=6; printf(“%d/n”,x+y); }  解决方案 C 要求对程序中用到的每一个变量都必须定义其类型,上面程序中没有对 x,y 进行定义。 应在函数体开头加上: Int x,y; 27. 同时定义了形参和函数中的局部变量。  错误举例 intmax(x,y) intx,y,z; {z=x> y?x:y; return(z); }  解决方案 形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为: intmax(x,y) intx,y; {intz; z=x> y?x:y; return(z); } 28. 误以为数组名代表数组中全部元素。  错误举例 void main() { int a[4]={1,3,5,7}; printf(“%d%d%d%d\n”,a); } 扫雷英雄榜——C常见错误及解决方案 王牌9 13  解决方案 企图用数组名代表全部元素。在 C 语言中,数组名代表数组首地址,不能通过数组名输 出四个整数。 29. 在不应加地址运算符&的位置加了地址运算符。  错误举例 scanf( "%s ",&str);  解决方案 C 语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且 scanf 函数中的 输入项是字符数组名,不必要再加地址符&。应改为: scanf( "%s ",str); 30. 多加分号。  错误举例 {z=x+y; t=z/100; printf( "%f ",t); };  解决方案 复合语句的花括号后不应再加分号,否则将会画蛇添足。  错误举例 if(a%3==0); I++;  解决方案 本是如果 3 整除 a,则 I 加 1。但由于 if(a%3==0)后多加了分号,则 if 语句到此结束,程 序将执行 I++语句,不论 3 是否整除 a,I 都将自动加 1。  错误举例 for(I=0;I <5;I++); {scanf( "%d ",&x); printf( "%d ",x);} C从入门到精通 14  解决方案 本意是先后输入 5 个数,每输入一个数后再将它输出。由于 for()后多加了一个分号,使 循环体变为空语句,此时只能输入一个数并输出它。 31. 引用数组元素时误用了圆括号  错误举例 void main() { int I,a[10]; for(i=0;i<10;i++) scanf(“%d”,&a(i)); }  解决方案 C 语言中对数组的定义或引用数组元素时必须用方括号。
还剩13页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

yekang

贡献于2014-07-02

下载需要 5 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf