淘先锋技术网

首页 1 2 3 4 5 6 7

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

本帖最后由 lifree 于 2019-12-3 15:38 编辑7 |5 i' _3 D- x" M/ O

) U; m$ }9 Z  v% E% z" }

C编译的程序对语法检查并不像其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,通过对C的学习,积累了一些C编程时常犯的错误,以供参考。% U) P) W. V1 t: u  ~

# n7 V1 F; b0 H  O4 c

# S+ V7 j% g4 }. x1 f- A

thread-254608-1-1.html

3 A: s! F; s" a5 R

6 L2 ]  W2 O# }5 \) e8 Y1、书写标识符时,忽略了大小写字母的区别。6 |8 N9 d5 D7 {" J

" H" N+ @# c# a7 `5 Zmain()

% y3 v1 N- ?9 z2 ~0 F7 k) Z+ v3 |{4 Q# J& m& |8 v. _0 E2 X

int a=5;

3 Z) {; {. H, [& \- t  r8 `printf(“%d”,A);

5 R  f; z  r) L+ X( o$ k: l}: M* h5 ~. j+ U" i0 n

- q! a: t  N( z# ]8 ^- G编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。# j: E0 {0 K- d! L, q

7 _, c/ ~8 p% ^- v- R9 o

* V2 B3 m9 L, m# A9 `

2、忽略了变量的类型,进行了不合法的运算。( a- R4 k% P! C7 p4 V

2 }( I% u" R4 L6 h) Kmain()) `0 v( x3 s4 A; z: o

{

) j; X  w& v, Y, D* R# `float a,b;- |2 d$ Q2 J* H# V) ]! o

printf(“%d”,a%b);2 ~8 V5 {% d( M/ l0 N* c

}( Y/ G; O3 [: @1 F9 S# q3 q4 ~( x% w

%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。- p0 [$ A; @+ e$ ^3 U

8 G' F) Q  U0 \; T: Y; L3 [6 T7 ^; o

1 ?, g0 R1 `4 D) m7 Y

thread-254608-1-1.html* T5 s) {1 W! Y- v: W  \4 W4 D

+ j0 K  A$ x' K1 T1 M) y, T

* j1 F3 Z% F% T. Q2 \3、将字符常量与字符串常量混淆。- ~5 C- ^2 u' j- {# g. \% Y3 ]) J

. L3 q1 @; Y- L% ]5 A) M& P$ `

char c;

, ~% ~. m# X  H9 ~c=”a”;

4 g$ b% \( C+ y

* I* K; t$ N; B0 i在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a’和‘\0’,而把它赋给一个字符变量是不行的。. e/ [/ t+ {0 B, X; V1 @+ h

0 ~% w3 Y9 e6 n# |+ N' ~, A( l  E9 C, ~7 b9 u7 x! w

4、忽略了“=”与“==”的区别。, R3 Q# z: ^0 L0 O% ?: ?

& K% d/ |2 u. q8 X

在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写

. T5 E& [' C3 B& y& H1 F: bif (a=3) then …

0 j0 ?( v0 W1 {: G, C4 G% O6 Q* Q9 R' G

但C语言中,“=”是赋值运算符,“==”是关系运算符。如:. J) ^0 B4 f. y* E' v" h5 ~

+ w9 s  d$ D7 I6 {if (a==3) a=b;

2 ~  G  Z7 ^$ x- A前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。

' e2 _  j% Q% Z3 f4 W# q  e: y$ O, E% @

' W3 a7 u. c+ t# v, r

thread-254608-1-1.html" S/ o) h2 w; Y4 ]4 y# z

* @3 L! t' Q, o: D/ Q2 n6 z

( B; ]+ w- T- y$ J* s+ [& t7 `+ Y* `" w1 |3 Z7 {* p

2 ^! ?! M. K4 x% V; j

5、忘记加分号。

1 s/ l, a& l2 o8 v4 W分号是C语句中不可缺少的一部分,语句末尾必须有分号。

( M2 T2 }& p5 z/ F5 _  C7 t( y$ m* c3 v; l) T4 C. x# J$ Z/ V) l; Z

a=1

4 b5 P$ z# b: K0 ^5 Qb=2

3 p* u) y. S' F* W* `. O2 F8 f% o: Y) Y0 Q  m! _# T

编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。

& W/ J+ @: M. R$ A" c  z; m2 [7 }( b{( [% {2 h2 M! M, l( x" T

z=x+y;

9 j- X" |3 \3 ct=z/100;

( S8 S: f% n# J1 I5 Yprintf(“%f”,t);

% ?( q8 Y7 m( r$ y' F. s7 F}6 v: k+ g0 I+ a* s/ a& x' ]. p3 @2 q* P

对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。

2 g1 ?1 f3 L2 i/ U, b

9 V3 C9 J2 i8 P. B. N( W4 \  W; G& k. N' p4 Q2 e

6、多加分号。

8 q6 k8 l* z2 s- Y5 U8 }

9 O9 }& P+ n$ a- m$ [3 q对于一个复合语句,如:

1 q7 R, I! ?- z* _3 I4 f, ~  j{

: ?5 k. H' [" f8 t4 C1 `z=x+y;

8 @" j& a3 W% i0 P+ it=z/100;

9 U1 e) I$ c7 P1 d8 H- x6 pprintf(“%f”,t);$ x/ ]* I9 j4 ?& |8 v, ^0 i, a/ q

};% B4 u* G8 [% z/ x% H: z/ t$ V

复合语句的花括号后不应再加分号,否则将会画蛇添足。又如:. ^- c& L7 g2 K$ R$ G1 Q( E

& l  O0 Q3 S0 e) m- Mif (a%3==0);/ Z2 U  r% j& h" m

I++;

[5 g/ d3 o0 N" S$ v本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。再如:

3 S, `; k- {9 X+ r

5 Y& ^8 C, ~) Y' m+ z7 M; Wfor (I=0;I<5;I++);

# t6 O) V6 |( u) A" L{

4 V8 V( J) j2 Y8 _2 ~' v" ascanf(“%d”,&x);0 B6 H' J0 X- U3 a& s2 B

printf(“%d”,x);

2 b3 B$ w: j' D7 @! t  C3 _; x}3 a) K5 D/ M6 m. V8 l

本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。

; I6 H  m. g, G2 @* |  k

: q2 C* \3 v" j2 k: f

+ h1 n5 G( t! E. K( L: O! e

thread-254608-1-1.html; X1 y- W$ k2 G% W' |0 @

+ p' c5 m0 X" E" {

1 \. v3 k+ G1 S+ i5 p7、输入变量时忘记加地址运算符“&”。; s+ _9 z0 z" o1 `9 E' t0 s

4 s) Z* z6 c/ E& ?int a,b;

* C2 j2 q: T9 J( \2 fscanf(“%d%d”,a,b);% E. x; g: L4 g) b

这是不合法的。scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。3 ?/ M$ g0 N$ B! l8 q/ T& g3 Q( Z6 \

: u( Q, ~# j& @& w5 b9 |2 C, B1 l; x+ O) Y

8、输入数据的方式与要求不符。l6 e5 N, g+ m; z$ {7 \& Y. E1 \

+ h' L# |/ Q% o7 c# \/ o$ D①scanf(“%d%d”,&a,&b);$ ]0 Z  h- i; a# E

输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:

# s8 |2 p, H1 I7 I: R" j& a% u2 C; S6 i; u( q/ H9 Z+ ^

3,4

! V- g5 s( L/ Z5 i( J输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。/ A) v5 i$ ?! z( g2 i. c

②scanf(“%d,%d”,&a,&b);

& e8 n) @* t0 h2 p0 `( ?8 n# e& jC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:

2 c6 |) ~& R3 R

5 [. @, j0 B- D7 F' T0 I3,4# [6 b4 \! ^  D- r/ `" k

此时不用逗号而用空格或其它字符是不对的。

% H/ I+ S8 R. [( {$ ]3 4 3:4

4 X5 J& s+ h* r: h. r% Y/ z0 f" k又如:3 F; t' F' H! y' c1 I

8 Z. K6 k5 W, Q3 e  z, @! cscanf(“a=%d,b=%d”,&a,&b);, o( f" S  e% O( J, z

输入应如以下形式:

; G, x+ g# e: @' La=3,b=4$ F5 \  }9 c5 y8 v5 ?# j% A

p3 ]$ L& h. S+ J: L3 d$ _- l- B8 j; ~! f8 K+ T+ I( n

thread-254608-1-1.html

' ?# p% l  l# S* R0 n( s3 X- Y  u/ I+ B5 r* o# o

' Y# I; ]1 Y8 F* ?9、输入字符的格式与要求不一致。7 \% \7 a5 |. I" W/ _; l  ?/ Y

/ i5 s2 k# n' X4 E' g, u在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。2 J# q5 o- K# b4 C  b! |- T, C

scanf(“%c%c%c”,&c1,&c2,&c3);

% j- \$ g( O8 K. _1 T如输入a b c' ^. M" c" E3 n5 ~

字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。

2 [( [) q3 Y& g# g- ]) E/ `

9 b' B0 z" u8 x2 B

; y* P# X9 R8 X10、输入输出的数据类型与所用格式说明符不一致。( ~4 f* u2 N9 f! q

9 O- z! M+ s: j- m7 [; l1 H

例如,a已定义为整型,b定义为实型

1 l$ [! w7 |8 d* T0 M$ y0 |a=3;b=4.5;) S0 G, q" S# v6 t

printf(“%f%d\n”,a,b);, \, j  l: b2 o" ^9 A, F2 E  h6 f1 h

编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。- p  O! z- w( r) q

0 ]! A+ ~6 V5 ^! p

0 b: K5 E8 n3 d  Z- p6 f11、输入数据时,企图规定精度。

* X; o! O, [4 W1 y( D5 ~: q: R# N, s8 j8 I4 z' c* f8 Q- y% B# i

scanf(“%7.2f”,&a);4 Y: I& _# i. _

这样做是不合法的,输入数据时不能规定精度。

" V, I, D+ u6 X% o

, a' @* s3 E( g) s& F( ]  N12.switch语句中漏写break语句。

% ?. z3 h+ M8 x( N

]2 a. @1 ?9 _9 l7 T: L例如:根据考试成绩的等级打印出百分制数段。; b. `: r3 G% Z! Y. O

switch(grade)

4 G4 s1 S0 j- w; ~{

: b8 E) z) N* S. H3 Zcase ‘A’:printf(“85~100\n”);

& d& B& A! g# L+ `6 Wcase ‘B’:printf(“70~84\n”);

( }/ V. S% v4 b. `case ‘C’:printf(“60~69\n”);- z6 }1 T  s8 U

case ‘D’:printf(“<60\n”);

3 m& J, W1 l$ \$ _: y& I$ d9 G4 cdefault:printf(“error\n”);

- [, ?% f5 l1 ^+ B3 g* n}

% D9 o/ r. U  J: X6 e由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如

/ E# i- V3 @, m: d* @case ‘A’:printf(“85~100\n”);break;7 j0 k* {4 {; t3 G6 T  }4 g8 u. }

- r' T- e6 c5 i( w$ `

- Y3 y& f$ b+ d

thread-254608-1-1.html

8 }* H( t% C1 B0 \7 {9 @! m/ A2 D: I' u, f

- `5 B1 H  E* X1 n; L! y! c

13、忽视了while和do-while语句在细节上的区别。% M  r8 S: X8 o, P6 M

/ v4 b% q( U8 ?" v

(1)main()1 I5 V) y7 G4 y7 V( ~) M

{

5 \; {8 b' E& u9 J+ v' A! }int a=0,I;

+ P; a+ p+ u; L+ ~: R7 C8 \+ escanf(“%d”,&I);1 @# G9 H" b& K5 V

while(I<=10)

& {/ l0 e# }6 `) g8 u{a=a+I;

0 T* _# O5 ^) ~/ |$ C% j" ZI++;

& O1 A; V: Q6 r9 \! f. j' r}, @/ [; Q- M5 _; d

printf(“%d”,a);

# `0 J( [; e, V/ q7 [1 S- h}% T5 b0 T1 H6 \# L6 G- R: L

- y. p, |3 J/ b& c2 k  p

(2)

" \4 N- y1 t% h$ r4 k2 bmain()% S+ W' ~9 ]9 L* W

{

- K  h, V) u4 B- vint a=0,I;

. I' d4 ]7 u% Xscanf(“%d”,&I);

7 m. _. U  }% I4 [; Vdo

8 j+ w1 O0 @' U4 ?{a=a+I;

# I. B6 F; N1 T0 Y/ WI++;

5 b6 ?) f3 n! y6 `}while(I<=10);* e+ ^& P8 f, \

printf(“%d”,a);1 d" h4 w" G% E3 J$ `

}

- r+ Z/ j" m+ m! P" Y& H, F& A3 D+ _% P9 {5 u) x4 @  N

可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do- while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。B0 s: x+ D, @7 h$ h, D

4 K) b9 R' Q7 V

2 {8 I9 R) y6 e

thread-254608-1-1.html

1 q" c2 J/ k' [0 V9 ?/ C( f4 g. s: ^" J& w3 S, T

$ a- i0 d1 q4 o1 I4 S% T

14、定义数组时误用变量。8 c& U) V! g7 ~: }

( q3 c8 P$ |, Y7 S, E, r, M1 J

int n;7 p) c9 p! _/ X! g

scanf(“%d”,&n);

6 S2 l9 n6 E1 E+ sint a[n];

7 ?& [$ x$ V7 a$ @) ?4 X数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。1 J: O0 ~( \' F0 J

' r& i) A% e( E. x0 |4 l

+ @' B: K8 F" }, x15、在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。

8 O/ l+ L- o9 ~, K. u2 _! A1 d

. I. I& p& o) J6 u* M  |main()

( p* X9 Q; d! f% V. r/ _# Y{

9 n, E0 E) [4 g- hstatic int a[10]={1,2,3,4,5,6,7,8,9,10};

6 u  H3 ^) V2 s, E0 H5 pprintf(“%d”,a[10]);

+ v# v9 `; g- y4 z. b) q}

. S# w: u, h  m: m9 r- ~

. c4 J, |7 r# GC语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。- E4 F5 ^; X4 E7 e" J  v2 Z

+ {4 g# |! a) v4 w16、在不应加地址运算符&的位置加了地址运算符。0 \/ j, A2 t- F: `, l

0 K( `% _! ^  C. f

+ C% d# }) V0 J+ B9 X

char str[20];" ~! C* k  d1 I- b

scanf(“%s”,&str);( s1 ?, C4 b  u2 N, U0 {

$ T) B9 u) m. K

; j; S& Q0 E& r, h6 P8 q! }5 A" W! t) i; J; J6 p+ F. b2 P& }

C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:

2 h1 c1 m/ c9 T" u: A2 y( fscanf(“%s”,str);$ p+ q( n" X% Q+ c5 v! I' W

% v* ~0 K6 B1 S5 J' v7 U! B& T  {

9 s0 Q- X: _) V2 O5 Z# f1 T4 d

17、同时定义了形参和函数中的局部变量。

1 V. X& O2 i8 n  T! y: Bint max(x,y)* W7 ?* ?% o7 }9 \4 x

int x,y,z;+ `! G) i" G2 F, l4 c  `

{

( S4 C) v2 d' |2 P2 y  e% Dz=x>y?x:y;

- H+ b5 w0 J" i, Oreturn(z);/ n  [5 {5 G% m- N1 b% O6 D

}3 _+ w" E( R6 \- [0 G

1 ?1 p( _/ l/ a5 }形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:% m- J( I. f" \1 v) N2 Z

% f4 k& _# ]9 P+ V& I% ?

int max(x,y)

7 _6 C0 _/ w8 M& I" Vint x,y;+ f, l& G: Y  w. m4 Y9 R! c

{

9 S, h. @* ^+ ^3 o, G6 N8 Q/ hint z;4 ?& U. o$ r7 N* G

z=x>y?x:y;9 ]6 T( m0 [. j1 G* v

return(z);

. |& u" x6 d* P" R; S6 R; o+ T. k" X+ l; D$ m

, `; G( M, h% w. C# r; B

$ I; \( Y1 W; K0 U' a0 ~『本文转载自网络,版权归原作者所有,如有侵权请联系删除』