- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。
% i: C, p$ K. T/ l+ i N0 D1.书写标识符时,忽略了大小写字母的区别。+ \$ x {. H. {. j
main()
6 }& T1 \' [, e; I3 U% m3 H+ V{+ n1 _% R0 O- y& F+ x _8 f
int a=5;
1 ]4 G- s/ k. m6 s- n* h( Q! \printf("%d",A);
% y# }* O# ^4 ]}
2 ~ L! N$ M7 h编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
# J1 @, s( j1 T# `6 i: ]: r2.忽略了变量的类型,进行了不合法的运算。. N& P5 u+ [$ m4 E: ^4 x& L
main()
' h' H$ ~) m: I/ Z- @+ e{
! C, ^' C2 R; k4 O; ifloat a,b;
9 t, m2 M, m4 Yprintf("%d",a%b);
. O+ ^/ ?# ^1 p& X* P* \% W3 X- m7 g}
v% B6 w# a7 J; v* U/ q%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。8 v. |# M! V& J( I! w! @) E1 l
3.将字符常量与字符串常量混淆。+ I* I% g* Z" f6 m \2 T$ T1 [" X% |
char c;/ i0 ]* [7 J( _7 K% v
c="a";1 z/ b" C; a- m. p
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。, d2 |' k: P# y$ `' X1 |
4.忽略了“=”与“==”的区别。
! ~ e$ O- ^# W在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写6 ^- b% I# |9 W" H' d' V2 f
if (a=3) then …
- Q8 v6 h8 g! w8 N+ Y1 g但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
) B0 X' {7 Y7 Q- C. E# ]3 mif (a==3) a=b;' B9 R6 k# X% u6 F+ e( j
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。: T4 w# f/ R+ K% H6 q* {' t
5.忘记加分号。1 M2 k! ^7 r: b
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
7 D4 d! ^* @7 h; }5 Q' I2 Ma=1/ G1 a/ g# ~) |3 z1 Z7 i0 G6 y
b=2/ u6 u$ M+ N% b0 i
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。/ d1 p$ a* g4 f: X
{ z=x+y;& w' L! M) w. W0 j O, L
t=z/100;6 y* i& g8 y+ Z7 K
printf("%f",t);
4 {( g2 H+ x) Y9 F. |; u! t% l}
' U9 N3 k4 }. d# e7 R对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。' P3 s$ q9 |7 {% e
6.多加分号。
" c- N* q5 } l对于一个复合语句,如:* p: y; c0 {9 \
{ z=x+y;
1 T2 L( l5 C; j3 x, V5 @; qt=z/100;
& `5 V' }% v1 i3 yprintf("%f",t);
( f% G$ b" B+ x8 F. C};5 t6 W9 v/ q: a! H# p* ?8 C* w
复合语句的花括号后不应再加分号,否则将会画蛇添足。
. X3 z5 L$ {+ ^/ j又如:0 {+ Q5 \' M% {" W: N% a
if (a%3==0);
( t+ g) u, Y$ C2 ?$ v* W( uI++;
+ h! m- ]( t A J8 c, {本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
3 v5 }) T- H; H再如:! A7 Y3 r. R$ H2 M& [6 s q6 l
for (I=0;I<5;I++);& o2 Q9 L$ w$ |
{scanf("%d",&x); a. U, V) _0 A* L P' [' X8 l
printf("%d",x);}
$ ]. o# a I. V- f本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
) Z8 T; W/ L' t# ~; ^: i2 B7.输入变量时忘记加地址运算符“&”。3 O/ t8 L3 C! {+ u7 t7 w9 L/ e
int a,b;5 [1 @- f! y- \( E: A% j* z8 ?
scanf("%d%d",a,b);8 B! H+ ~& [' [( n# d) |( S8 D& W
这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。
6 b$ o; [$ Q5 J% ?' g; I7 H2 \$ p8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);
) D" l$ q# r- h$ Q$ j输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
! N; \0 s2 c& k) u# s9 W3,4 * K% O# H/ }% N z O& z
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。) ^, k; u+ [( s2 y n }9 f
②scanf("%d,%d",&a,&b);
7 K+ ~, t `9 f4 b I {C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
& c; s, x6 K6 y" T" p# y; X0 u& ^' ~6 r3,4 % ]( T8 S1 ]5 X( a
此时不用逗号而用空格或其它字符是不对的。
0 F- m' x5 T6 ]5 z C! Q3 4 3:4 # i+ A( t1 g$ B: j" n, _
又如:
( Q; R2 X/ ~% R* Uscanf("a=%d,b=%d",&a,&b);
4 E+ {% ~/ F/ V! q输入应如以下形式:/ ]7 q, B( d: T1 B/ x! s9 L. a
a=3,b=4
3 A( l. |9 j: m9.输入字符的格式与要求不一致。/ v! z4 y. @: b7 h# \2 C. y
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。3 d- `/ ^" Q" r6 B' i
scanf("%c%c%c",&c1,&c2,&c3);
% u. e6 m# V3 Q' J# ~如输入a b c 6 t) P' S( v1 |" B2 a: J S, U
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
8 I& c3 d% [5 l+ j: x10.输入输出的数据类型与所用格式说明符不一致。
- \* Z) z8 u4 P& R6 i$ I" h$ H例如,a已定义为整型,b定义为实型
2 D: u4 m) }; ^, Y5 [$ pa=3;b=4.5;
7 N( W2 m8 ~; S, Bprintf("%f%d\n",a,b);
$ ?3 o2 ~ F6 K$ k0 o; Y) y编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
/ K( @8 |# W" u+ z, s. V4 G11.输入数据时,企图规定精度。
# g% I! M5 ^2 escanf("%7.2f",&a);
. Q- o) a% |( ?- C这样做是不合法的,输入数据时不能规定精度。* i9 ]- ], L8 \: n# t6 ~
12.switch语句中漏写break语句。
6 C$ ]9 |8 h* c! S2 A7 K. w+ C, e3 r8 \例如:根据考试成绩的等级打印出百分制数段。
5 x6 }4 N: q# q- D4 V. x& Yswitch(grade)7 K* V& u! R8 J4 Y" m) A6 N
{ case 'A':printf("85~100\n");4 j3 b* F! n: L
case 'B':printf("70~84\n");
+ L) O, F* v. Ycase 'C':printf("60~69\n");
3 _' M# ~8 @3 e4 |case 'D':printf("<60\n");
3 }9 N; \- B a' i# O% p) |% e0 t ^default:printf("error\n"); s6 a% j P/ i
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
3 l$ h# x9 T0 X* u3 y9 A4 Icase 'A':printf("85~100\n");break;
( W6 J3 C; z3 O* ], a13.忽视了while和do-while语句在细节上的区别。
1 x$ x. |. B+ o, d1 C(1)main(), l; c# l* T7 j
{int a=0,I;4 ?" R- P( F% o9 r7 [4 ?0 _" A
scanf("%d",&I);
1 ?6 G8 K1 H1 q7 ^ Y! Vwhile(I<=10)
: x7 ^4 i0 Y! ]7 G. F/ T{a=a+I;
# Y, C2 C6 W8 |( QI++;3 B# A; L/ k4 [8 f4 i; ]. t
} \# @2 N& F; P) I
printf("%d",a);4 S* Q" z# W# D$ K. l: E
}
2 D; Y. O1 P7 f+ g+ r" A; W7 U5 [4 q(2)main()
2 N- `' o% r0 u+ F$ |: m- m{int a=0,I;/ p; c% o, ~* Y) I
scanf("%d",&I);
- I$ d: d8 ~$ Rdo
* D$ A: J8 H) S0 Q{a=a+I;
- s$ \/ O! j1 h& dI++;/ I6 f6 Z$ M* |8 p" |* k0 t
}while(I<=10);' ^& B6 s! q' H7 e' T* m
printf("%d",a);
4 v# _5 J C& c$ ^3 ]}
" A k. h% X2 e: W可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。) o9 u1 x& e* R9 n0 b) k
14.定义数组时误用变量。0 }' [6 B8 ]" r% a8 z) w4 w2 Y
int n;! ~) P6 c5 v4 z8 _1 x8 C
scanf("%d",&n);
& E* N, W# N9 \1 t3 uint a[n];
+ G- x. S! [1 }# X数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。$ v( l+ P0 W0 _% @6 Y5 z5 U
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
; u! j5 G$ k& \( q( R3 j2 Wmain()
8 h0 I# ]2 G$ b{static int a[10]={1,2,3,4,5,6,7,8,9,10};
9 A) E0 R1 H: l3 K2 ~( D4 Yprintf("%d",a[10]); W0 l# c* |1 d$ B. j! ]% `
}% r: g& ]- C$ z) W# L9 c$ X A
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
5 B6 y( t$ W8 F: e6 `16.初始化数组时,未使用静态存储。
$ I& D+ [# c% \ H- Y* T6 Fint a[3]={0,1,2};
3 A9 k& n9 w% u" C这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:9 n( o; M$ g5 k! o
static int a[3]={0,1,2};
# V" ]+ K C2 P17.在不应加地址运算符&的位置加了地址运算符。
' l2 Q. p% \& E; Tscanf("%s",&str);# {% A4 M* B Y" U1 {1 x% s
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:( n! e3 f$ [* B/ m% q
scanf("%s",str);
- M1 q7 k: d- G: i8 G% {$ S, U2 a" f18.同时定义了形参和函数中的局部变量。( b2 j; e, l/ Q. _) C4 r0 [4 D
int max(x,y)
0 T3 `# Z" f& x" d3 q; g, qint x,y,z;. h) v$ J5 {9 k( f8 ]9 A8 m5 f5 L- P
{z=x>y?x:y;1 c2 v4 c6 B) x
return(z);1 _6 j' _: f8 l# ~9 ?2 C
}3 q0 `) R. |# R8 l
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:# P; b& ?" y- o6 _8 d( ^
int max(x,y)
& K% D9 K) w2 }, N, Z6 iint x,y;0 E1 j( o9 @% N! u( I9 O4 X" D! f
{int z;
3 [8 g& b6 O7 u9 ` Y8 |z=x>y?x:y;1 O/ {6 Y: ~' {# ?4 i$ H, X% t
return(z);; l! G" v: z; _) T# [4 f' x
}</P>$ @9 L L" q0 P8 @* `
< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|