- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。
) L: O% ~4 |& o6 \1.书写标识符时,忽略了大小写字母的区别。# J" ? P0 _1 f
main()
4 q% v+ n# _( J; C$ X{" Q, `9 G5 d+ N. B; n6 H' ~; ], u
int a=5;* U. g" m/ j: E6 c4 b3 b3 |
printf("%d",A);# P( _4 o# P- M) d. w+ F
}2 X: a3 T& Y; j. I, G
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
# R% `. N- [! E6 E" H K1 s1 [' Q; y2.忽略了变量的类型,进行了不合法的运算。7 r Y3 P) e) w" c9 Y
main() H6 ~5 ^. I. j$ `0 `8 Z) z
{
7 K/ H% f0 D2 Y* Y* ~2 ufloat a,b;* ]5 Q* e. f* G W) R
printf("%d",a%b);
) q$ l, q1 u0 M8 e; E}8 |2 O: `, ]; j3 b: N+ `$ A9 J
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
( f5 k% i# Q, S3 i% A3.将字符常量与字符串常量混淆。 c; j+ }% ^# C+ o$ h0 a0 Y
char c;
( a( b1 y* _& T3 N' }c="a";6 ^( p# Q* C9 F3 J @8 T( C- \
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。; v* }! M# K- S: L& u
4.忽略了“=”与“==”的区别。8 e) S+ Y D4 `' _9 d; O
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写4 B: {: I8 N9 Y5 Y+ r9 u
if (a=3) then …% h1 `1 w j/ s) P) F
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
: i6 A1 @2 w1 }( Rif (a==3) a=b;
2 Q7 E8 c+ s) N" f& i7 e前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。% Q; ?9 J2 }6 t4 q, {
5.忘记加分号。
) M: f8 z' @7 P, y0 @分号是C语句中不可缺少的一部分,语句末尾必须有分号。
! K/ ?6 P/ ^7 Ta=1+ h5 U$ I# v" W, {
b=2
9 C& _4 C2 k6 S$ s1 h# ~/ S编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
2 `9 v. g8 \, }2 K{ z=x+y;
3 x0 a& D8 _$ `' p7 J4 Nt=z/100;
+ G" {- J5 y5 w+ G& |: dprintf("%f",t);+ a! ^+ P0 Z/ x* e, E/ U
}
Q$ p5 l' n$ m7 a% m: p$ L对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。: P- _6 w: z: R
6.多加分号。
# r/ g) F2 X4 s+ m4 x对于一个复合语句,如:
$ L7 {5 q9 T" N8 z{ z=x+y;+ R4 a- L! O6 `$ d0 Q9 R+ L" _
t=z/100;! X9 P v6 P5 ~& [' L$ p
printf("%f",t);6 `+ u% }0 Q( ]; b1 i7 l
};
, i6 ?+ @' P; J" @1 `复合语句的花括号后不应再加分号,否则将会画蛇添足。0 c; S3 v) r! Y% }* G+ h
又如:8 a( G W! N3 K' ]
if (a%3==0);0 L# j1 l4 x( r+ \% ^
I++;
9 [+ U3 s1 V# O9 d本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。. U5 d: c, E! G4 ^: p; o
再如:
, i. J9 ^" S) `: x# H+ h8 Mfor (I=0;I<5;I++);
4 m3 h* u$ _- e6 h X* M{scanf("%d",&x);
9 ^4 E2 P# \1 k( fprintf("%d",x);} r% l6 m$ k8 ~/ ]. ]
本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
% `, n2 ?8 [# w! K7 l& j7.输入变量时忘记加地址运算符“&”。* u2 }$ J3 f% k! X5 V/ A" ]
int a,b;0 U; t9 q3 Q/ S
scanf("%d%d",a,b);
5 L9 ]2 [3 Y# @4 H$ y. G这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。* ~; [) j( x- A0 A/ q. I: v! V
8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);5 ?& @" B7 J' F5 @8 M
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
; w1 I7 e% ?7 x, G' n. Z7 b h3,4 7 I2 h3 S- S& i
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。" C; ~, y( C& c5 j
②scanf("%d,%d",&a,&b);
" w/ z8 w2 ~+ x$ {( a3 c% mC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:; _% s2 r/ s4 @. c$ k; y5 b7 I
3,4 0 N, e3 m2 v, ?% W( h
此时不用逗号而用空格或其它字符是不对的。
9 R) p+ P' a- A3 ?# W3 4 3:4
6 I; `; M: E0 s, @" U/ U又如:
) @3 q7 _9 t8 E' A8 _" @scanf("a=%d,b=%d",&a,&b);0 L, X$ `. F ]: U7 m
输入应如以下形式:' \& N& O6 W% P2 h. J# l y. v# r
a=3,b=4 & |+ s8 B0 r% O* \# F- T
9.输入字符的格式与要求不一致。
: A. e' Q6 i' {) y1 L3 ~在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
/ D2 d" K+ W: I$ n! S3 Escanf("%c%c%c",&c1,&c2,&c3);! R3 R) E- q. k- B
如输入a b c # q1 j& Y9 G8 J' i# f
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。$ }8 u0 B6 e; ~+ T: U# v' F
10.输入输出的数据类型与所用格式说明符不一致。
* K6 z% i9 x9 D# C$ l9 [7 K3 o例如,a已定义为整型,b定义为实型
/ d1 K3 `4 ]( H8 ga=3;b=4.5;
, O+ h. B. ^* `6 q6 uprintf("%f%d\n",a,b);) N. m6 E# e& C5 u6 ^9 f% \
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。 H% a! J6 m1 l# S
11.输入数据时,企图规定精度。
. {/ N( h& }" Z5 Y. z+ U1 \scanf("%7.2f",&a);
; v) R D! n7 p/ i* h. I这样做是不合法的,输入数据时不能规定精度。
0 u. ~8 D2 @8 p: D# W/ K# n: v/ h12.switch语句中漏写break语句。
9 l! I& I- f3 Y3 o例如:根据考试成绩的等级打印出百分制数段。/ J T- f! R1 X' N
switch(grade)- C9 G: t$ J) f6 s
{ case 'A':printf("85~100\n");
" ?5 W W B, P/ |, z6 xcase 'B':printf("70~84\n");
7 m; z5 b$ p' k( Wcase 'C':printf("60~69\n");6 o% _+ k0 J# t6 s0 Z( i' h
case 'D':printf("<60\n");
, X/ ^9 z7 R# Tdefault:printf("error\n");& J" n5 A+ y+ Z) q5 r
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
; U9 e5 h) }7 dcase 'A':printf("85~100\n");break; ]; R- u6 g. A) U
13.忽视了while和do-while语句在细节上的区别。
1 x0 H- S+ I# Y5 @2 d(1)main()
2 i% x6 H2 P9 u! K: K0 m{int a=0,I;6 i7 T! V8 A- U/ M% d: {/ `
scanf("%d",&I);
) G& b' j. n1 i' Twhile(I<=10)
# N8 M6 c- f* j$ V{a=a+I;
3 l- ^2 a$ |$ o T5 W- w0 [I++;
% ~+ S& @0 a( T. d}
( P5 A3 c; H( f+ F6 n- yprintf("%d",a);
: V3 |5 {) @) m8 L' M P1 T) {} ^- [0 F; b! r# n5 y/ f
(2)main()
$ v1 j& z, ~2 o1 j2 B{int a=0,I;& u# j+ w5 L; ^( K- c' R" N% i) ~9 A" G
scanf("%d",&I);, f, `: I' m$ }/ r: e9 C; x
do2 E% \, N( u" o2 ^: \
{a=a+I;/ F9 h+ N4 c- b- D) M, x3 d
I++;
: [8 K* x" W9 y7 T3 ~}while(I<=10);1 T' }$ o! @6 ^3 P0 D; K
printf("%d",a);
J9 W* m; Y# z6 A |}# u; O1 C4 _$ Y% [, i& o& |
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。6 g9 D7 n5 ]6 e u% b# H
14.定义数组时误用变量。
! C. }8 d# D# s" Jint n;2 L; q. y0 L" f0 r4 ?& f
scanf("%d",&n);
! {& x% f& E8 M% C; H6 p1 B" A* tint a[n];
- }$ ?3 _' e3 b! ]/ @2 E& g$ f数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。0 `- a) {: P; T( b
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。! B$ |' ~5 o# [9 e9 e
main()
1 _8 ~$ T, e4 m# g# ~{static int a[10]={1,2,3,4,5,6,7,8,9,10};
; k! {0 d g" x* X! e& L6 `3 Nprintf("%d",a[10]);+ E+ \9 i8 S5 K+ u
}" ^! Y& H* H& A
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
9 ~; c/ n" z; q' w! |1 C! X16.初始化数组时,未使用静态存储。
2 f) z8 J% G( g* k& r" u; eint a[3]={0,1,2};
' _' ?) R5 L$ W( N% F* n; x这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:
7 f I# _9 T I+ dstatic int a[3]={0,1,2};, L. D7 @8 j# Y8 X; q& w% h
17.在不应加地址运算符&的位置加了地址运算符。; _# L* l {, U# Y1 D6 g) L
scanf("%s",&str);: t* a/ n- w! [; @
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:
6 Q0 z3 a+ t9 E, v5 pscanf("%s",str);
- A# L' V/ F) A8 W) L3 E9 N2 D$ N18.同时定义了形参和函数中的局部变量。" j' q& z/ U! l" w1 v
int max(x,y)
5 k H V7 I4 m0 Y$ M H9 A# B! P U) Fint x,y,z;
, L$ e5 D- _9 h* j7 T9 l; H* L{z=x>y?x:y;" ~7 O* v. V9 \0 B
return(z);
" r* E% [0 ~& F- ? s}) s9 B* ?0 w2 ~
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
4 r3 |& o! n7 ^/ z/ j. [int max(x,y)# }4 c3 e! G% f5 J8 M2 \
int x,y;
4 X; g- E( [3 @ b& J{int z;
6 V- E' D1 e+ r$ a5 U: }7 F' `z=x>y?x:y;# e3 K9 [# B9 ^3 V
return(z);3 }2 h; |7 W7 m; b1 r; H
}</P>* W. u M2 z9 t7 W9 P- k
< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|