- UID
- 2
- 斋米
-
- 斋豆
-
- 回帖
- 0
- 积分
- 1897
- 在线时间
- 小时
- 注册时间
- 2009-12-26
- 最后登录
- 1970-1-1
|
C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。
$ [; A1 b3 w$ a2 H0 h' R3 {" h. c' t! }( z" r1 s4 R
1.书写标识符时,忽略了大小写字母的区别。5 ]: J, ^( c0 y" x
main()9 Q0 V. I' V! @( ~; z/ n$ ~
{
! }3 U6 z- `5 {) C2 U1 ?int a=5;
9 R. C: c7 x9 o3 f6 {# r: M4 s Kprintf("%d",A);
- G. n0 o; e/ S7 V" _6 f# V}, _, B# K8 N, t% T8 b# k+ O, \( r
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
) j$ S7 I5 d4 J2.忽略了变量的类型,进行了不合法的运算。$ b: I8 R O! B7 ~: D
main()
# k) l8 G4 T* B" x) f# ]$ A# Q- Y{
6 O; @& q @1 {$ J. P% M3 x2 G( J- pfloat a,b;( s5 { \8 @1 _! t4 e: e- @
printf("%d",a%b);
, Z6 C( J# g; ~7 U: f7 I: g" j}" ^1 T( x# C9 i; s$ R% ]2 l
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
. v3 J8 e, N. i: ^3.将字符常量与字符串常量混淆。
. U( k& J8 T& g# }6 O9 U/ y9 q7 Lchar c;
( M% B! A' t- e# Z& vc="a";
, G+ m% g- E/ b在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。, y) K$ O- m$ Q- u6 q4 ]4 _# H
4.忽略了“=”与“==”的区别。
- X! F3 ^9 A+ C6 s! A( Y在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写3 j/ u3 ^; V' i
if (a=3) then …) C, J; {/ H& t- V
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
3 `2 h3 U( {2 U. D, eif (a==3) a=b;7 U3 T) S3 J; m U( p' i; y; ^
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。5 _) a q+ F) L8 }5 B# k1 }
5.忘记加分号。# a9 a/ u6 [8 H+ b1 h
分号是C语句中不可缺少的一部分,语句末尾必须有分号。! ~( [7 w, R8 B u
a=1& i, }* {$ h4 {! x
b=21 T# r- O% g6 w+ S0 N o
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。6 @5 @0 q7 s- g9 T
{ z=x+y;, v, I4 r6 }* m4 M7 |
t=z/100;
4 p, Q) k0 v; c+ S" x) i) V1 Iprintf("%f",t);
, B6 g7 s+ a; ~8 d9 b}
( ]# h6 E7 A' J, I+ L$ R$ W) C# k5 I对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
9 s( w2 U; R. B* t: C8 b% G6.多加分号。4 _& G1 U' h! u* ?# t. f
对于一个复合语句,如:
( o7 h# f, Q% P{ z=x+y;$ N: V! U5 Y- l! j b
t=z/100;- ^' `4 ~1 }3 A" F
printf("%f",t);3 [, _- a# y5 o
};1 p9 w: s* b. o d$ Y; k
复合语句的花括号后不应再加分号,否则将会画蛇添足。
8 [' A: |5 y8 P* T9 S, d+ s: P又如:
# Q- |6 e( J, d' hif (a%3==0);
. j! p3 Y4 x, I2 TI++;" V$ e6 X2 p( \7 y r: Z' d/ y: h
本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
% m: w ^3 B; ^: c4 F再如:( n' _7 u1 N# T- C
for (I=0;I<5;I++);, O. R, Z' X j& n- e
{scanf("%d",&x);/ w2 }1 F) i3 i9 n$ p2 J
printf("%d",x);}5 G& b) l8 p7 f, q9 n" a( n6 B( {% i
本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
: W+ |: Q" Q1 v7.输入变量时忘记加地址运算符“&”。3 ~$ B7 ?6 T1 m! Q5 @
int a,b;
9 n) ~# ?7 i, s" W/ C8 Oscanf("%d%d",a,b);
# L- T1 Z+ ~6 G9 l这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。
1 ~; M* I- F! Q) @1 v8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);; M2 R: D2 s# M1 ]
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:- H: L: w) ?# Y% s1 ?
3,4 , p/ S# ?& i$ h, Z
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。( {1 X6 S; @! J4 @" v, `
②scanf("%d,%d",&a,&b);
, ^4 |% q6 G8 r8 D1 t( |C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:- t& h- g2 W+ ^* W6 @; o- @
3,4
) N- T5 H3 B5 k+ x: c此时不用逗号而用空格或其它字符是不对的。
: L: i. Y- D5 h9 i3 {; J3 4 3:4
1 E( W+ E) C2 ]% T! c4 j$ k又如:8 e& h0 Z6 |+ V
scanf("a=%d,b=%d",&a,&b);- f' M5 R! J A! E1 g5 _
输入应如以下形式:4 n. Q- {9 s8 B6 V
a=3,b=4
2 m1 Z+ I* |1 ]3 m0 {9.输入字符的格式与要求不一致。. _8 x, z; w: u5 g2 n9 l d2 f/ j
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。' N, e N& t$ Q1 O
scanf("%c%c%c",&c1,&c2,&c3);' \9 ?0 ?0 k& J g; e
如输入a b c
! }' o2 Y: z8 z( D: J字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
. [6 H R* D; [7 @; p10.输入输出的数据类型与所用格式说明符不一致。" `4 A+ R/ ^: v- k' ^; c1 Q5 h, m
例如,a已定义为整型,b定义为实型) F0 ?' o8 O- G7 ]* g4 t% b: g
a=3;b=4.5;' x, N8 u* o/ p( D$ H" T. z
printf("%f%d\n",a,b);
/ N) Y- N+ \) w! _: A/ w编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
8 i% C$ t+ Q3 F: ? ]# ]1 W" `5 W+ H11.输入数据时,企图规定精度。
) V4 D! l5 P) V2 nscanf("%7.2f",&a);
, B* F/ D9 e9 q% D W" U这样做是不合法的,输入数据时不能规定精度。, `4 t) @: T+ |
12.switch语句中漏写break语句。" m) _$ d F# |
例如:根据考试成绩的等级打印出百分制数段。% d( `, n- {- H% r2 e, N$ j
switch(grade)9 @4 S+ G% u l) r( k5 m7 M
{ case 'A':printf("85~100\n");
# X l( ^! U3 ~5 [9 e& ] jcase 'B':printf("70~84\n");8 [6 J& @+ U9 H9 Y5 @3 M
case 'C':printf("60~69\n");- B2 y! e) S: c: L* s9 T" P5 _
case 'D':printf("<60\n");
" I; i7 S' X4 @3 K. h( Ydefault:printf("error\n");
5 P$ D, g8 `. `4 F+ v由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
7 ~- z& z- Q9 O& K, P% Fcase 'A':printf("85~100\n");break;
0 F: A* d P, a: r8 x2 e* z. A) V/ ^13.忽视了while和do-while语句在细节上的区别。
/ R8 S8 X+ h1 ~! S(1)main(), ^2 b0 _1 N2 x2 C) h
{int a=0,I;
+ z& w% M' P4 `scanf("%d",&I);# g' o$ _( o# x8 Q: E4 Y$ O
while(I<=10) e0 A: y: i) n* c
{a=a+I;
* S1 Q( \& E* D TI++;! A3 N+ V4 n6 g
}
( |# H2 s$ {" B* |/ Oprintf("%d",a);- C% H ~! T5 h; e# [5 O9 D
}
: c* W: W" \, r/ Z+ }6 N(2)main()
" Q n6 |- S+ X) B, I0 U+ T{int a=0,I;3 Q7 p+ [% s( S L: c+ b
scanf("%d",&I);
" Y0 t2 T/ o# q- ^5 W. ]6 s2 qdo
/ {. q. L; e& X0 k7 ~{a=a+I;5 X2 K7 N% A; E& t
I++;2 }. o3 i7 ^& d( ^' _9 n# t& k
}while(I<=10);
5 |8 N: [/ g% S$ c4 B' L `% |, c9 Fprintf("%d",a);
% J! x6 A5 T9 A+ m2 O}
% a3 |% c1 ?7 P; `1 W可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。6 ~# `0 L% a9 R
14.定义数组时误用变量。
% t0 v0 p: ?: [( h4 mint n;
% w. A# }2 d) g/ W3 qscanf("%d",&n);2 g+ @9 M9 Y# J7 A2 a; T0 I( ^6 \
int a[n];
2 t9 l, d# E$ }数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。 B6 u- `6 G. V9 r7 j
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
# C, d" P# w( R) u4 i8 lmain()
, M N) |) v8 ~" c1 U& M{static int a[10]={1,2,3,4,5,6,7,8,9,10};
5 X& L- }+ Q7 ?! p2 Z5 `printf("%d",a[10]);! E1 c, w9 j, k, _
}1 w6 _/ y2 b, c, s6 x) F; f
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。% t7 Q( m+ S6 h A
16.初始化数组时,未使用静态存储。
* H- \) p, c, p. _' sint a[3]={0,1,2};
' F8 }' ]" N0 s/ M1 W2 k这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:
- ]) Y' b; C# O7 |9 i" bstatic int a[3]={0,1,2};; x2 V. {8 b9 f: a, Q0 D
17.在不应加地址运算符&的位置加了地址运算符。
# w. a4 S) G( W2 c& ^& r) j% Iscanf("%s",&str);' N; Z/ C* Z5 F3 q! Y; a! K) @4 `* ?: E
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:0 m6 w+ F1 g4 r6 W; r
scanf("%s",str);, w g$ @$ g! B3 z, R" @* y
18.同时定义了形参和函数中的局部变量。0 }8 w3 }8 |: S v4 Y7 d
int max(x,y)1 s% c3 [. ?% u# f9 w* i- N
int x,y,z;1 v2 p- }- u+ ]4 Q$ V
{z=x>y?x:y;' m& d) @) B* q7 Q
return(z);$ w; ^! x2 Z( Q% \0 a
}1 t5 X0 ]0 C* I- }7 L, t0 _
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:+ [6 T# k" c- F/ s
int max(x,y)
0 N% t6 }; Y; J% O8 Dint x,y;2 b" p) _: Z- o4 F) e& g7 B
{int z;) w" p# U9 p- B3 V2 Q
z=x>y?x:y;
# s. a( k3 r; ]return(z);
* g5 j3 X- ]' a0 c0 I} |
|