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
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
* 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
" 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
; 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
' ?# 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
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
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 ~『本文转载自网络,版权归原作者所有,如有侵权请联系删除』