- UID
- 2
- 斋米
-
- 斋豆
-
- 回帖
- 0
- 积分
- 1897
- 在线时间
- 小时
- 注册时间
- 2009-12-26
- 最后登录
- 1970-1-1
|
C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。' U4 V" A3 _5 \$ P% n n) p. }/ B! c" E
4 j+ f* l! s1 ?9 z" s2 @/ h' W1.书写标识符时,忽略了大小写字母的区别。- d) c4 E; \# s! S* a: V/ z
main()
( ]# H0 [! u/ C; b. u: N{* c/ n7 u, a2 {/ E* @
int a=5;$ o; K; f1 x! \) ?9 e0 e
printf("%d",A);. [1 l3 p" z% _! ^5 i
}
9 I/ i# Q: X" Q5 r编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
% M/ e& B R4 }# g' h2.忽略了变量的类型,进行了不合法的运算。, }# T! A$ R- C, T# H4 S
main()5 i7 y. D! _' L" Q- [/ p/ ]. n
{ Z# m# B0 C5 Z q
float a,b;
& u4 X' d4 c3 w* [* f' Bprintf("%d",a%b);
" ?# s# R; {9 b5 t}
6 ~+ g. f7 J, z%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。/ g* U$ \- O# Q; l: y
3.将字符常量与字符串常量混淆。
+ R1 B) o5 l, a# _' Hchar c;
$ c" v# V+ L t' Bc="a"; h: D' b+ z ~4 C5 y
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。/ g' x$ V8 t+ O8 |% l0 u
4.忽略了“=”与“==”的区别。
1 ]! X% ?& m1 d* }, n在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写2 z7 j$ q5 P$ I6 a! `
if (a=3) then …
}- _% E' W3 d' k! Z但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
1 S B$ r* S4 ?) K0 w: e8 L4 h$ eif (a==3) a=b;) h, z, Z% k0 E3 e4 _
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
; j( G; f6 o3 H5.忘记加分号。
+ _# ]0 A, i1 J6 Y+ \# j分号是C语句中不可缺少的一部分,语句末尾必须有分号。) Z) M: G. |# Q# z, S
a=1
) i5 h* U: ?2 Q) D% t3 Ub=2
+ k q9 |; p0 K编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。 [/ x E ]6 E) ?
{ z=x+y;/ k5 L, Y% U; H; Y4 q
t=z/100;
0 |3 |! J. c; f1 @printf("%f",t);
6 \& }4 Q4 E7 ?; F}
, W2 S4 _* ]% B/ ?% C+ H" A" V对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。4 _6 h# p0 g; P- i) J" R( P- c8 [7 A
6.多加分号。: ]' A( O- @& x) e4 |
对于一个复合语句,如:) ~( M6 Q2 \$ ^
{ z=x+y;/ L' N# C+ k: b6 ?. {
t=z/100;
/ t" c# Y" Q' Aprintf("%f",t);
. V" t) h2 d5 ^5 }9 z9 U};
" R; H( c% Q* T% q) E9 [8 U复合语句的花括号后不应再加分号,否则将会画蛇添足。
. e, O3 G- @: K0 ^6 L又如:
; l: `& y7 i# f* V$ wif (a%3==0);
: Q- p# U8 ~) r! r, E4 DI++;
9 Z9 L' Q3 ~& @7 c G本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
. W1 P7 `$ X; t2 `+ S# v; F0 G再如:; T9 z8 ]0 o( h; H
for (I=0;I<5;I++);9 K! m* E- ]- R# d$ b
{scanf("%d",&x);/ X: }9 p O& t& n6 m; w1 j# _, T$ J
printf("%d",x);}
; h6 [2 [% M) o' J本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
$ f" B1 D6 m# O; ^% E' E5 ?8 p% ?7.输入变量时忘记加地址运算符“&”。3 V* q8 _* N$ b6 S7 p9 m! o
int a,b; d, ?5 j% I1 J. X
scanf("%d%d",a,b);
% A! G& A; f3 x' I9 d! s( b这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。3 H8 U% X" Q9 U! I; i& R# y. D7 s9 S; {2 h( \
8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b); K# N" R2 Z, `& E: f$ U
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
5 v9 o+ I" S( N, I3,4 0 C8 c; @ s% H o1 Y) w
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。9 F3 q, e9 L: d" M3 H+ P+ p8 K$ a+ Y
②scanf("%d,%d",&a,&b);
6 t' K& K" U P: \: `& z1 yC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
0 K% ]+ m( n8 L! p: l3,4
$ G0 G( K7 ~: I& q6 |- P8 k5 f0 V此时不用逗号而用空格或其它字符是不对的。1 d+ k. G, u* D7 i. J/ p: [$ n8 {
3 4 3:4 7 @9 _' Q$ t1 o: n( W1 `% q
又如:1 ]. ]! I. B+ j! x9 E$ d7 ?, f* S9 E
scanf("a=%d,b=%d",&a,&b);
4 ~; Q+ I) I# L0 Y1 `输入应如以下形式:0 v" K- Q5 N. ]/ c! @$ G9 W. W
a=3,b=4 2 ^8 E: I# V9 J I2 H# o. ?
9.输入字符的格式与要求不一致。
x- t9 c7 K8 Z. {, ?2 r) p0 m- `在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
& E E4 N* o" i& O7 |scanf("%c%c%c",&c1,&c2,&c3);
' b+ G5 d: ]( R& I. J! y# T如输入a b c
' S6 ?0 u) o1 H, O l, N, V- N字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。9 H# r/ [7 F) q( s
10.输入输出的数据类型与所用格式说明符不一致。
( s8 Q, Q$ y2 p6 o例如,a已定义为整型,b定义为实型
# y) S) G9 a, s6 b5 l# ra=3;b=4.5;
) a! F& g" ]$ p6 M1 O$ Cprintf("%f%d\n",a,b);! \5 j9 f: c( O/ A% a: l; s7 V
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。4 h6 t7 {( ]! x, j% }8 N. | B3 D
11.输入数据时,企图规定精度。' { Z% I: o' C# N0 ]) k+ d
scanf("%7.2f",&a);) i8 T5 |7 d6 ~& U) H8 ~8 r6 s
这样做是不合法的,输入数据时不能规定精度。4 m$ @7 o/ Z6 N5 n! q
12.switch语句中漏写break语句。! Q! d; D& v1 X9 T: J
例如:根据考试成绩的等级打印出百分制数段。
( T/ n9 A8 I* Y! n0 X+ B3 x9 mswitch(grade)
- {( q- a( Q) h{ case 'A':printf("85~100\n");3 \6 |" K( T) y) o: V/ U3 G
case 'B':printf("70~84\n");
9 [0 O9 l# _. ^0 D6 _! n( hcase 'C':printf("60~69\n");
) j. V$ z% c; wcase 'D':printf("<60\n");6 m, Z, v% W0 f4 u* M4 r+ t& Y
default:printf("error\n");& Z8 N( U$ g# J/ b" U+ ~5 g
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
2 h/ o% o" y; |- E9 l5 kcase 'A':printf("85~100\n");break;
V9 j% l, ]! Z7 a) w13.忽视了while和do-while语句在细节上的区别。
" s! M) p* b/ g$ l3 ?(1)main()
- o( f% Q( G. |" j. j6 n" T" W{int a=0,I;
- O! D. y9 ^2 A0 B1 n! G9 jscanf("%d",&I);
* Q& y d$ f' M. s2 L8 [while(I<=10)7 P/ Q/ c2 r; p) u4 p; U J
{a=a+I;
8 |6 ]4 ?" }! \( N7 [! iI++;
( j% L1 ~" B0 }8 @}
! V s; H+ L& f5 {1 S8 M( m1 c ]printf("%d",a);: R% T5 D9 B: ]) k( a
} c& Y) M7 O" T
(2)main()% ~3 P& J- j3 W4 \$ }! W0 @
{int a=0,I;8 h5 Z% d7 ~4 p# o
scanf("%d",&I);
) l* j4 C: W% R- bdo
9 f6 J4 G3 q$ o{a=a+I;
( Q0 G% t9 S$ Q6 D. }$ _I++;
/ I2 I4 Q& [ K9 h: O}while(I<=10);3 K* [, C9 q. e7 y
printf("%d",a);0 E. E$ Z* K! B& m' B( @, l
}
, @- n1 f. _% X2 n0 F+ X- |$ y可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
1 J ^; f2 x, Q& j& H0 \* ?+ ^! D14.定义数组时误用变量。$ b0 z& N2 U8 R) j2 a+ E
int n;
4 f, U, f& C- ]4 vscanf("%d",&n);
! w; G) I& G8 q/ P1 P0 R8 ]. o. h3 Xint a[n];
% o" t: q2 K9 p3 d0 Y数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。' B' L) N& t! k( a1 @1 V1 C
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。. ?, S( R5 p u* W' } V; D
main()
5 |: E' x I2 L& j0 d2 V7 @8 g{static int a[10]={1,2,3,4,5,6,7,8,9,10};
2 j- ]. [* ~+ Xprintf("%d",a[10]);2 {5 _3 w, {1 q
}
; ]5 p1 v9 e0 T* q7 z# a$ jC语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
$ h+ w |& m" n4 U0 b, C, v6 J' c `16.初始化数组时,未使用静态存储。, t% m s3 K. \
int a[3]={0,1,2};
; w9 X: h9 P8 N& U/ G: O这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:
* X8 o. S7 V+ Bstatic int a[3]={0,1,2};
1 ]9 g1 t$ P* G- Q3 s% d17.在不应加地址运算符&的位置加了地址运算符。% U9 U% J% g/ S& E: e+ N) N5 |3 {
scanf("%s",&str);! ?0 T- r4 c5 f% Z
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:
/ W* [1 X g' X( Gscanf("%s",str);
* h) J2 G# R# l' `* M18.同时定义了形参和函数中的局部变量。
2 @& N3 S. N+ R, R, b+ {% B. wint max(x,y)
$ J' J# W: T9 k3 J" V/ @int x,y,z;0 \! t E2 e6 i- }/ t
{z=x>y?x:y;
+ ]& K! {! ~0 h6 q# Nreturn(z);
, w0 ?& X$ n* Q% @! ^5 [4 o}
5 P7 k+ f4 y, ^! u8 O K# ]形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
4 @" M+ O X4 {+ dint max(x,y)
( W5 I! |3 j: I$ I5 gint x,y;+ q7 M" G2 k' K! R
{int z;1 |1 o* {4 F6 p6 r4 J
z=x>y?x:y;1 j: p# ^5 E6 t# z
return(z);- [3 y: ?; M/ N) `1 H4 U0 U
} |
|