- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。
$ }) U! M5 F* z$ [7 x1.书写标识符时,忽略了大小写字母的区别。
/ t# V+ v, X( k1 W# kmain()4 ]5 _" Q5 C! X& J& O. ^7 L6 P7 G
{
. P) P0 q& }6 iint a=5;$ @. K( W3 M$ a, a/ H
printf("%d",A);; {* w" z% c$ n5 v
}
; k8 O5 [1 v1 Q% U编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。5 c# s$ l: L: k& u2 k6 p. Q
2.忽略了变量的类型,进行了不合法的运算。1 i l+ A# E7 ?0 h) [
main()# u1 T1 I0 g4 r9 O8 u
{
8 S3 D- {7 q" [4 jfloat a,b;
! F" w' W" C/ a% C3 b7 r- X9 A: rprintf("%d",a%b);! S7 V4 i0 q/ [
}- P6 T; F# b5 ~9 m
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。2 ?; `3 |# j5 n) c: I' n
3.将字符常量与字符串常量混淆。# o1 ~( u7 F x- |
char c;8 T, W) q& @) T' d
c="a";
/ {6 A/ M5 N* R* }+ z在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。
1 e7 B. ^$ d( C4 ]4.忽略了“=”与“==”的区别。 w* P9 w# m; l0 I& |) K
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
; r6 Y1 o& r% q; i7 Nif (a=3) then …* |, ^5 f+ q/ O, R' F, E
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
6 S! u3 W( y; G7 P' N: N0 G3 _if (a==3) a=b;% Y) w# q" H; c0 _
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。, I4 f' ]5 R+ c' I. A
5.忘记加分号。
+ f5 }% j( d3 ^* w c7 m. `分号是C语句中不可缺少的一部分,语句末尾必须有分号。
3 y0 t' ^ S: j! ta=1
! n+ Y) t) {0 H8 T. Ob=2
3 E$ N' k& G& O! K' G7 p+ h编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。: n6 v2 J, ]& C4 T
{ z=x+y;# [( u+ M1 w+ Q/ h& W. T
t=z/100;
. x- u! ]9 N: V8 n' v: d/ Sprintf("%f",t);
) v/ i2 K" n: ?6 N; a* i# i}, z' c* I" Y# F$ l% ?5 v
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
6 R1 q+ `7 j# ^- I: T. X6.多加分号。4 Y: M. A: N% h5 @3 H- `
对于一个复合语句,如:
" j+ A) i! c% h+ a$ R& N{ z=x+y;
( g [2 w1 t6 G, \! N9 r9 ot=z/100;2 p- `/ y* a7 n2 e6 v
printf("%f",t);. t/ ?: k$ V% \9 k8 J
};
* V3 Y1 Z+ U/ X5 m8 o8 E6 ^复合语句的花括号后不应再加分号,否则将会画蛇添足。: e+ c7 `3 _: }! y8 i' L: i
又如:/ D U4 o. Q2 D3 ~6 Q( p& X
if (a%3==0);
' ?- q& q4 u" m3 @, g6 _. m/ mI++;
3 A! j/ G. B1 I* `( R9 O本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
2 z1 y& P. O' R' ]再如:
: ^6 L; M# M+ F$ [ U# M6 N5 Zfor (I=0;I<5;I++);( j4 K5 C/ s" q. ?
{scanf("%d",&x);
# V* c! E8 c6 F6 w- n* v4 Y- Nprintf("%d",x);}
, [$ l* Y. \8 u2 ^. u本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。 }8 q1 E1 u( S! z
7.输入变量时忘记加地址运算符“&”。
! I1 B. G% n; y( {int a,b;) y" Q$ }, I3 ^. Y5 f/ @8 `
scanf("%d%d",a,b);
3 E$ _2 _" |( |这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。- L N( |+ w W* @& n0 F" N- ]# h
8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);
* p9 l. e3 w) C" z) C输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
1 \' I8 ~4 P3 @+ v) Z3,4
0 a' B3 u9 E3 s4 t# u- n输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。& T/ x% X# [* \5 N4 C
②scanf("%d,%d",&a,&b);1 c5 |0 `: G0 z9 b" u' Q
C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
: O7 E) u4 ~$ `8 q: V5 g3,4 - O+ X1 m- J' C) ?
此时不用逗号而用空格或其它字符是不对的。
' `7 H t8 u# e9 k7 s( Y; M3 4 3:4 ! c, f4 [8 S0 g+ }' F4 S2 h
又如:4 q! B4 t. Y& E' G2 e
scanf("a=%d,b=%d",&a,&b);& I# f& u8 R3 k
输入应如以下形式:, } u! b% E+ X0 E- p/ h k5 q
a=3,b=4 $ V0 Q5 ]8 p2 c# O, e
9.输入字符的格式与要求不一致。
( I- I; _) V u& C: c1 U在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
. u! M4 T. [; l3 s$ i! [: }( bscanf("%c%c%c",&c1,&c2,&c3);
7 Y0 r3 f, L9 b0 d% n8 n; S" e3 D如输入a b c
, k( S" w' Y! V1 Y2 }$ w, p. i字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
+ F7 u# G: K2 V' x r N+ o10.输入输出的数据类型与所用格式说明符不一致。) g' S; X# y% [8 O
例如,a已定义为整型,b定义为实型
" ]8 Z8 t# g9 \# W8 Ba=3;b=4.5;
$ ~, Y/ P/ a; Z: P9 ~+ q+ e! Oprintf("%f%d\n",a,b);* p2 h; H: s: O6 r" L }
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。. e/ o. d* M* S' ~( i
11.输入数据时,企图规定精度。
- u$ H. E9 V ^' [- q1 k& @/ tscanf("%7.2f",&a);
5 {) x2 [5 X8 a0 g# E这样做是不合法的,输入数据时不能规定精度。$ v+ u% O6 ^. i4 b
12.switch语句中漏写break语句。
: U8 b9 d: Q7 X例如:根据考试成绩的等级打印出百分制数段。 A6 _1 {7 G' x; Y5 h
switch(grade)1 {8 J* b9 | ~, b, W
{ case 'A':printf("85~100\n");
9 Z" u8 J" C& u+ R! X. x* Ccase 'B':printf("70~84\n");
! b0 v3 ]5 {! `6 R2 O3 w* ucase 'C':printf("60~69\n");
9 n% [$ R3 l" d' K% J9 A$ R! dcase 'D':printf("<60\n");# p4 M# Q" v* W4 {4 _$ S3 V0 d
default:printf("error\n");
/ X+ F( t" N8 b. D9 q由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如" P! c# e8 `) x( {8 U
case 'A':printf("85~100\n");break;, C. K! s3 s i$ O
13.忽视了while和do-while语句在细节上的区别。
/ A* H. h4 F4 d; Q(1)main()
* O) f0 Q+ c' k' Q" M( S3 o; ^{int a=0,I;
3 m- _% U% m2 G* {- Vscanf("%d",&I);8 \) d3 `6 X& ^3 ~8 B( a& d5 @
while(I<=10)
4 T+ S! P# p U* l{a=a+I;
, i7 N" F; `9 A- ^" w. jI++;0 U3 m* u# m; W% ~# }+ y9 i
}
' t+ g# K& |; [printf("%d",a);
- S. B. D( E7 y# d/ T, X}
1 h* k# _8 N, b8 X& `+ d" u1 r(2)main()
6 o, w/ i B" i& E{int a=0,I;
) _$ l1 c- U3 [- j/ _2 l Q; Nscanf("%d",&I);
& j" R" ?; Y6 c9 ]do
0 ?6 m1 [" ]% V& r9 I1 R{a=a+I;
3 E: ^6 |; W2 P. l# Z2 iI++;3 G' [! V$ q {0 |- ^! S
}while(I<=10);
; W! y( { Z/ P- ]$ ^9 Aprintf("%d",a);
4 D+ K2 H. B) u}
) h5 S6 t3 b3 n, N7 M可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
! D; e% L/ s0 Z6 w4 Z2 {2 s14.定义数组时误用变量。
3 o' v/ w' C: b8 Z/ Eint n;, p n1 V- E, k# W
scanf("%d",&n);
2 M; T. K& U t5 w! Q3 |8 Pint a[n];
2 D( Q$ \" @( M数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。, C- l* Q! L+ e( q3 B
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。& A7 v1 l4 X4 Y
main(); y, T! O' l( E
{static int a[10]={1,2,3,4,5,6,7,8,9,10};4 b* R; F# F: l3 `) {# [, k& V
printf("%d",a[10]);/ R5 N) e; r; H9 w) W" t
}
+ \* Y/ ^6 A X) W& G8 R: m# n: KC语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
5 E4 X2 v; V2 G8 }16.初始化数组时,未使用静态存储。# ] E3 m$ Z' u$ T: }7 n& ]% \! S
int a[3]={0,1,2};
% I# j# n7 ~, v- Z" Q) V: S- @4 S这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:
% v4 E# I, L; v, p5 B+ Fstatic int a[3]={0,1,2};
/ h. J3 ]8 `" M! b( B/ P17.在不应加地址运算符&的位置加了地址运算符。! d' F/ r+ P: E: D5 d) f/ R8 R/ e
scanf("%s",&str);
1 s% W" w$ M' e; N ?C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:1 Z: ~9 X) X4 }8 u8 }$ O* E' A
scanf("%s",str);1 J" K5 W/ P4 w! M, j# W m; T/ \& k
18.同时定义了形参和函数中的局部变量。0 ~$ h$ G0 N5 c* N5 _
int max(x,y)
% L$ U) L0 [" `int x,y,z;
$ A7 l9 ]6 B: c2 _( c{z=x>y?x:y;
0 u8 {4 W$ X5 jreturn(z); k; g3 I# L+ N
}/ l4 Z, L* [+ \: ~; r8 H* s
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:" l2 x0 n9 u/ B' c6 _
int max(x,y)
r# Z" o# U, c1 S: Wint x,y;
& d- S M4 w }: r& C; _{int z;
1 Y& Y$ A- j" B9 }z=x>y?x:y;
" X d* Z( m5 T3 m4 ^return(z);$ @/ j: f# |$ R& T- A( Y
}</P>
8 H* I/ c2 m5 w/ c1 f< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|