- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。7 q! v$ W( f# u' U4 g
1.书写标识符时,忽略了大小写字母的区别。
# u% v4 ?- y; q O! ^5 n( V# f' _main()7 v/ J4 Q1 x. Y
{* k. c# y7 {. T) @; n2 f3 {- F2 @
int a=5;" R$ S, h' s+ R8 d
printf("%d",A);) N/ w% s: m, w' k* T. Z
}3 B& F; P5 o7 T- f
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
( O; ]6 t9 Y9 N& u& U& q- ]2.忽略了变量的类型,进行了不合法的运算。$ ?5 o2 \' a# A! S
main()0 T* k4 w& V6 o. [- \
{
' f: q ]5 N: R6 Ufloat a,b;
. h1 V ~$ ]5 G) _0 r) `; L" g+ @printf("%d",a%b);
. _. x1 D/ q* k2 m7 Z" y# L! V: S}2 `# b1 X6 a7 N ?7 T
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
8 _8 D& Z5 r O( R3.将字符常量与字符串常量混淆。
* t+ T; V: a# g+ h# b F. v5 j8 W1 Mchar c;7 w9 C6 ?) o% l
c="a";6 J# e2 _9 Y* `% M, Y) m- o* F
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。$ I2 O& L" W: `5 b9 n7 n
4.忽略了“=”与“==”的区别。# O& v, q+ H! \8 b, _, [
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写' R! c4 V4 S. @ k" q. W$ {7 t
if (a=3) then …. f+ H: C) ]+ u/ H* E
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
% h6 d) K- L1 v! Z1 l y, @if (a==3) a=b;9 I* b6 T/ X3 U! X
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
0 r {" n5 K' R) B# |5.忘记加分号。
6 L3 l/ b8 P4 N. w$ ]分号是C语句中不可缺少的一部分,语句末尾必须有分号。
' k8 L, {" ~) \9 l; ^. f- N2 \a=1
( @0 z6 D3 T. k! G7 I; yb=2
, `- a3 N) l, X7 G& B, ^# j编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。* b: t4 p/ {7 K" v4 O" c( I& e
{ z=x+y;1 x5 `: V L* `, ~) {1 h. M( m* m
t=z/100;
6 u- A( e3 K* |( Hprintf("%f",t);
/ R: [* e0 D$ V8 h; ]3 H}, Q9 [- r; W: b1 i$ p$ |
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。: C+ j8 ~' p4 u. g1 ?) E
6.多加分号。4 K% |; n" O6 P K
对于一个复合语句,如:# D4 T# H- i' r: y1 S
{ z=x+y;
* w( I4 @: b3 e8 r i) n* Ct=z/100;3 d; U9 ]; ], N6 l4 I' i
printf("%f",t);9 d! Z1 f7 ^$ l0 a6 z0 R) u
};" M# j9 V5 O& p% R. `" O
复合语句的花括号后不应再加分号,否则将会画蛇添足。9 z4 O7 W% W1 U: s# b
又如:
# _# i' k+ E" [1 {4 G. Dif (a%3==0);. h4 h* ?- a0 v& K. r
I++;
" |6 p9 H' L, X0 i# z2 |) U本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
' }" R% X5 j+ d8 H, Z再如:
& s* M6 F( t; H" ~" efor (I=0;I<5;I++);: y+ V7 w! Q0 k/ `2 {1 O
{scanf("%d",&x);8 G& x2 s8 g3 a, X3 T
printf("%d",x);}, |, \- o, l$ ]( J t, Z. j
本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
8 d+ B6 k# W0 H5 i! ~; l# i7.输入变量时忘记加地址运算符“&”。
2 W( [8 r. A7 o5 z: e3 @int a,b;
! U9 Q' a# [$ m2 D% Nscanf("%d%d",a,b);
; ]" h/ _2 t3 U& @$ E这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。 f1 p' B+ i) {" N, A
8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);
& t- }4 r. z; ^% Z输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:, f- e, b* i% V4 |1 _' G
3,4
: B$ E; ~+ I# g输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
8 p' o6 r5 K) M+ o+ I# V( L$ j0 w②scanf("%d,%d",&a,&b);
) \4 D$ e1 c5 T0 p$ TC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
' a' T8 B& u x6 _. j# K3,4 % G! V3 C) [- V
此时不用逗号而用空格或其它字符是不对的。
( \& v6 k3 |# N5 E3 4 3:4 5 l, h' W8 Q% |6 R4 d b7 z
又如:
- M# K1 U# {& ]' v# i$ m+ U7 a' ]scanf("a=%d,b=%d",&a,&b);, ^) Z; J& _( N, H
输入应如以下形式:- h- z9 B+ a$ t+ z
a=3,b=4
, R: p) V) `( p. p' k; ?9.输入字符的格式与要求不一致。
4 W8 I8 S$ P2 X. T3 j$ ]& N在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。9 f, |' o1 V3 v3 P! A8 F. g3 N9 @
scanf("%c%c%c",&c1,&c2,&c3);% Y- K6 c* o, v; e7 r
如输入a b c ; j2 m" T& V. G6 Z; B K3 X
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。0 l5 R; `8 }9 O2 ]7 S l% o; X4 Z
10.输入输出的数据类型与所用格式说明符不一致。$ A3 ?. H/ P- M9 n9 U, T, Q
例如,a已定义为整型,b定义为实型
* H! b3 \6 J# L6 `6 X) |a=3;b=4.5;, m' ~, T$ O7 }; T, C
printf("%f%d\n",a,b);
, C1 s% k0 P- ?. I+ Z$ n ?编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。3 c0 p+ K6 J( p; O9 n* n
11.输入数据时,企图规定精度。( C/ l' A1 i9 b# ?+ U5 B
scanf("%7.2f",&a);
. A3 R! t |# T1 K6 q z; n这样做是不合法的,输入数据时不能规定精度。2 E& y1 I. K* U, R/ F5 n: h
12.switch语句中漏写break语句。
+ V4 D6 A3 q! K/ r& v, u8 r5 l A例如:根据考试成绩的等级打印出百分制数段。; p. b: x, p1 i
switch(grade)* M# s6 F& D* C
{ case 'A':printf("85~100\n");% Q e. y3 \! f8 y0 K1 p% s
case 'B':printf("70~84\n");7 S8 v, v& u% E* I! o: [: m b8 z
case 'C':printf("60~69\n");) U! t2 q- i" t3 E: f7 ^& l5 k
case 'D':printf("<60\n");0 p. ^ ? a7 h( m
default:printf("error\n"); M) N8 ?2 I2 `* _$ r, m
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
- _" a% E9 P9 c% M7 ncase 'A':printf("85~100\n");break;
2 o/ |( B V5 c: E13.忽视了while和do-while语句在细节上的区别。
* Z) |+ H. F& }2 ?+ W2 c a(1)main()% s& p p, q: m5 ?" N* L. L
{int a=0,I;- h9 y9 f0 B# f G8 K0 L- W) h1 A
scanf("%d",&I);! [0 ~6 ^! C! R* Z( ~/ z
while(I<=10)5 J( s6 n/ S" n8 ?
{a=a+I;
5 o( {* j: s$ u+ [# p/ r* o( B0 SI++;
5 O, F b2 Q: s}
4 K5 B" T* W5 ]* Y) qprintf("%d",a);$ d; x8 [; ]% A, b
}
/ g# s8 r- g4 [6 R: j(2)main()) i, {2 N+ V6 R: q( g
{int a=0,I;
: \" n) Y1 a; q* J: oscanf("%d",&I);
! l( [8 ]+ z6 o' Q4 }% u0 r# Ado7 C- ^' K( @! Z8 N( e$ u, q
{a=a+I;$ W0 P& e. d k7 H8 u1 d
I++;- L- b. @ F7 g$ Z
}while(I<=10);1 ?" j" i5 k9 c4 I# e
printf("%d",a);& H# E& n/ ?. ?% g. D0 p
}
& M* X& o' i% u3 A. X1 u) b可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
. _: n2 N2 s/ T7 A8 [. [, u14.定义数组时误用变量。
; f; j" [% Q' \3 \) v# B3 ?int n;/ v& b% p& J9 G2 _) T7 T
scanf("%d",&n);
, G$ d0 b- ?$ h: e$ r6 \int a[n];
" i, z8 A% H0 `; [数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
$ V3 D6 x! {, a, w- T# a15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
1 z) K8 P* h& |5 \6 Vmain()7 z' P2 {1 m1 M( s0 x
{static int a[10]={1,2,3,4,5,6,7,8,9,10};, `' C/ I: t: @7 d9 T. {
printf("%d",a[10]);( M* u- p9 J3 P0 m
}( G8 _3 e0 h8 L1 [' H- z! s
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
. f, }, S/ `1 A8 i# r! _16.初始化数组时,未使用静态存储。4 a8 k4 K! d [$ h! t
int a[3]={0,1,2};& u/ |8 d8 K# Q+ I7 F7 \) o2 C0 t
这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:1 ^2 Z( G3 H" n* `6 z/ v
static int a[3]={0,1,2};
! |1 A4 q' x+ S7 w/ k17.在不应加地址运算符&的位置加了地址运算符。
0 R4 `. r3 v7 T+ Oscanf("%s",&str);
: k- v( T* _3 T' WC语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:- u4 W0 P, S! P, w. U
scanf("%s",str);
# H$ _; U* k: Y$ }9 N: r18.同时定义了形参和函数中的局部变量。
! P; } N1 q& @" F- m2 T4 ~5 C! iint max(x,y)
5 e' O+ L4 q+ W1 |( Y" kint x,y,z;( |. J4 \$ d9 X5 A
{z=x>y?x:y;0 t+ q. {; G- C& d
return(z);
1 Z# Z5 V) y0 s. Y5 h6 |}: y8 a( p+ I8 A* T3 c! y. A# v
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:, e) d' C, e2 K: D$ |& M) o( l3 E# l
int max(x,y)& K# s; I; q" O$ M* C; s& \6 q
int x,y;/ N" I" f3 H2 m, X4 o
{int z;
. Y$ ~# _$ n+ z2 }4 j# q% {z=x>y?x:y;
2 o# c# R8 P/ k8 K( Rreturn(z);6 Q% T8 H: S* d6 J w
}</P>% \6 f8 I* w. f3 c5 f- G
< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|