- 在线时间
- 0 小时
- 最后登录
- 2006-3-12
- 注册时间
- 2004-5-30
- 听众数
- 1
- 收听数
- 0
- 能力
- 0 分
- 体力
- 262 点
- 威望
- 0 点
- 阅读权限
- 30
- 积分
- 109
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 27
- 主题
- 17
- 精华
- 1
- 分享
- 0
- 好友
- 0
升级   4.5% 该用户从未签到
 |
< >C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。
+ V1 X. r, w3 S4 b( T- [4 h8 f1.书写标识符时,忽略了大小写字母的区别。
" X6 }0 {% M0 S9 {9 Q% u" hmain(), M8 f; E/ b7 R0 c+ t
{9 W( q" B0 V; K) @* k6 |
int a=5;
: I1 f3 {9 z1 H& ?4 W$ Vprintf("%d",A);2 f+ W' C6 y A' y2 b8 C9 ?3 z
}9 j$ V2 b$ n( h7 p
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
1 R* b2 g' B9 n& O( d2.忽略了变量的类型,进行了不合法的运算。
% p7 l K2 T) ?7 _main()
4 E+ o0 V5 K" b{. \1 ^4 z; `1 |5 f1 ?
float a,b;
* {" X' P6 U: X8 Z! Bprintf("%d",a%b);
% N7 N' o2 \! z2 D2 C8 K}
% C8 R0 v; Y5 l: v, k" u& V" E- t%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
9 ]9 ]; e# X! q6 U! _0 j3.将字符常量与字符串常量混淆。' f: ]' `5 \& ?8 C
char c;5 ]/ m0 l) v: ~9 o
c="a";* y7 J, C* b% G/ F4 W
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。1 l4 Z0 V1 x3 {4 p% Z
4.忽略了“=”与“==”的区别。
2 C& z' ]* e6 Q5 w; Z在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
) N# B- V. T+ s* C' Nif (a=3) then …6 H# i: ~0 s1 U4 r' H6 V" [
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
3 D5 G7 ?* W( z3 q, O, }if (a==3) a=b;+ N, m. ~) C5 k# A0 e; g8 t
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
7 \; c$ m' t" G; H* {' D+ ^5.忘记加分号。9 b: s$ @" e' Y+ @) y& N: f |; U
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
& k5 w- Z1 ^6 T3 A' E& a1 @a=1
2 X( w) f6 G8 `$ M+ J& k( ^9 @9 gb=2
! x8 f1 v# A9 U7 z6 G7 | C8 o编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。$ g4 Q3 V5 C1 o8 X7 n5 W
{ z=x+y;
' B* ?0 ]# _. C) Y, H' ct=z/100;
9 b3 n9 K9 o. r/ J5 uprintf("%f",t);3 K% R! E+ l* ]1 @+ r3 C; p
}. J# K8 z0 X$ R+ k
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
1 o- S- o1 Q: ]. x+ H% j+ _6.多加分号。% h; ~/ g7 q+ F9 N. z
对于一个复合语句,如:
S2 B# w" ^6 V6 f, x{ z=x+y;8 C/ I) i/ @# `" Y$ y$ c
t=z/100;! ~9 Y; t! v5 P5 h8 R% w
printf("%f",t);4 `% y6 P; x A4 z& p" _2 m+ r( O
};
( c! D2 e2 ~* C! S# o4 x复合语句的花括号后不应再加分号,否则将会画蛇添足。
" x0 K* L: m+ C* W( s6 L# y3 L又如:
- O4 b8 b3 @& t' F' ^1 _' Fif (a%3==0);# ^% C: V e& S* n( G
I++;
. ^5 c" C: R: c# Q9 D7 c6 p+ J本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
$ X) p$ V% W% J {再如:1 ^$ w8 I' m' Y. ^( u1 l7 m# ?% `/ }) r
for (I=0;I<5;I++);
7 c+ G& E6 g$ U{scanf("%d",&x);5 t) k' N- ?7 [, }
printf("%d",x);}
4 ]. z2 H" L- n* V- T本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
& H: ?2 t( ~6 F) D H1 H. g1 E7.输入变量时忘记加地址运算符“&”。7 d3 ]5 d7 F5 `8 Q' t- O5 T9 @$ H
int a,b;
! X. w: H3 b" ascanf("%d%d",a,b);! z8 M) ]4 l5 `: a* U, X
这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。
0 ~" \1 C4 J; d0 Y- |/ K$ v% {8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);
' W" v2 h* W9 ?% a( O输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:7 D% p2 y3 V1 T z) a0 n$ y" ]( T
3,4 6 r% t5 @! w2 h
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
% J( W8 k" m3 X②scanf("%d,%d",&a,&b);
% t- Q% u4 V5 h: HC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:' U, Z: J9 b/ `: H6 b9 w
3,4 , B5 Y( y+ q" h; {9 t
此时不用逗号而用空格或其它字符是不对的。
% f$ h. Y" E' F* w3 4 3:4
* q" R" ~' Z6 K又如:
2 e C& U) Y) h- Mscanf("a=%d,b=%d",&a,&b);
- `9 \9 k) f. f2 h输入应如以下形式:$ Z+ z; e7 Q5 i* s; ^5 r! i
a=3,b=4 8 j3 m" a- X2 D) [
9.输入字符的格式与要求不一致。
9 K- {- D" Y. ~1 q# s4 _% W& L t1 q在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
7 C/ j% n) V* e lscanf("%c%c%c",&c1,&c2,&c3);
+ K. o x, C2 V' p T3 I; H/ N5 w如输入a b c 2 n- j- t7 L" N" e! {- O
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。8 ^6 @5 u% p$ ]: M+ p9 `: N6 I3 V
10.输入输出的数据类型与所用格式说明符不一致。
& p6 D% U$ o- W# Q) B+ l1 ~+ Y+ x例如,a已定义为整型,b定义为实型
6 n* J" z3 P+ G& La=3;b=4.5;
+ Q$ ~$ Z' j$ L3 n. aprintf("%f%d\n",a,b);! s6 n2 z# q# z* L# P: @
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
( R" O7 U1 i f7 D D11.输入数据时,企图规定精度。
4 ^8 w! ?- A0 ?5 o! j: M4 ~scanf("%7.2f",&a);+ X& e2 `. P& w* _' K
这样做是不合法的,输入数据时不能规定精度。
; t( K5 D h. C0 M: k" o# b$ { O12.switch语句中漏写break语句。4 Q1 i' p, |3 J: E% ^' W# Z
例如:根据考试成绩的等级打印出百分制数段。
K' \6 i% g A, @switch(grade)3 Q$ t; }( `- y5 y( i
{ case 'A':printf("85~100\n");
/ Q/ D4 t: l7 C) Icase 'B':printf("70~84\n");
4 J f8 {5 f/ k7 m- g' pcase 'C':printf("60~69\n");
2 }5 P o7 R1 Rcase 'D':printf("<60\n");- [ X/ p" y3 |
default:printf("error\n");: i# v6 d2 Y4 Q7 M. C4 T
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如( }2 r0 @; E7 p! t+ b0 G3 m
case 'A':printf("85~100\n");break;0 \5 g" {3 e: e5 X4 u8 Z) B8 }
13.忽视了while和do-while语句在细节上的区别。% n( k' D8 c* A: {; A
(1)main()
$ a( s8 B0 s4 n- N{int a=0,I;: B9 F9 w, K. I! l& Y# [
scanf("%d",&I);
/ v$ c; c0 Q/ Kwhile(I<=10)
4 G3 q. O$ p6 \, L" {0 C) v{a=a+I;
; t% W% R3 _9 {: \" BI++;- C: L8 [/ D h4 p
}
# x. k9 L B$ t8 T9 C' [: Sprintf("%d",a);! r; R1 ?% `3 B" n0 ^8 ?! W' K
}
( t _0 f# z: F' i% Y$ z% D% ^(2)main(): V6 |5 L" \9 ^, q' W E& ?1 d
{int a=0,I;$ \/ b5 C5 M0 y1 A+ o
scanf("%d",&I);! k: g! F2 A/ E+ j/ W5 z& x! F8 ^/ a
do
$ j1 a& V$ _0 |{a=a+I;6 s! N! I4 d# a6 t4 [1 ~
I++;
3 z: I* R3 `: ?( U) N}while(I<=10);# I% r* U* k8 K
printf("%d",a);6 Q$ O- K: @8 K2 V" [7 R- a
}5 ^$ s) n1 l+ L- T7 @$ q
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
( f7 ?( V5 j/ q! t14.定义数组时误用变量。4 c2 K. ~% k, z! u$ n; l0 T
int n;% t9 C" N& [) }$ L. m, e
scanf("%d",&n);
2 T. ?+ B3 \* R% O( b8 v; qint a[n];
* {9 a% v* U" \+ z& |6 k4 Z( p数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
7 T8 v/ O" F0 X& u6 `" ]15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
0 S, ~& [ J: G$ e7 Imain()
& K& P1 y# C. l, b{static int a[10]={1,2,3,4,5,6,7,8,9,10};
$ ]. ~* e W' B, L/ Z+ Sprintf("%d",a[10]);
5 K+ K& V! Z/ \; Y( t/ X}+ n7 S& X, H6 N( i3 o# Y, F
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
2 @' ]; ]$ L6 W# q16.初始化数组时,未使用静态存储。- v* m2 V6 |: }, [0 w
int a[3]={0,1,2};& g. K0 `( m4 A6 H2 n9 [6 D. j
这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:0 Z0 z. Q- r0 y. y# M' L* ^
static int a[3]={0,1,2};) Q1 K& |0 F( r) h4 h
17.在不应加地址运算符&的位置加了地址运算符。
k& b( _$ m5 D4 Tscanf("%s",&str);
4 `4 e1 h0 N4 ^$ {0 Z ]! CC语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:
$ ~" I. B. Q1 m! G) ascanf("%s",str);# [8 O+ X5 L/ j* A* @6 {# F. U2 g
18.同时定义了形参和函数中的局部变量。' \9 V1 l' [( h, X) Q( T
int max(x,y)
1 c( M+ g' ^) ]4 l) f& Q2 Tint x,y,z;
) u+ y2 {6 k/ k+ L0 c0 Q8 \{z=x>y?x:y;
6 h8 v. D- i9 v. W- jreturn(z);+ X1 ?8 A) @1 d* }
}" h! T! N ]8 E( r9 U
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
: d( ]2 N* Q; H1 l3 iint max(x,y)
% w1 F+ N8 d/ }' T+ uint x,y;
; @& H c. P. Y* u! f{int z;
1 u' L1 ]4 e+ n: Nz=x>y?x:y;$ T3 z: G Q( J( ^5 ` w
return(z);
1 S6 Z. h# g# E: D% D4 }( J% i7 x}</P>
# y1 R$ u% v. g2 J0 s; @< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|