- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。% B' g, [ I% G; }/ Z
1.书写标识符时,忽略了大小写字母的区别。
8 L0 ~' _$ h% V) D- f- Vmain()
, P T6 ?9 N; r% O, P9 Q' I4 D5 ~{
$ V: U% Y' l0 k. `' k4 ^int a=5;$ q5 t; q3 G' L3 n) [. Q# K
printf("%d",A); ]7 e# d5 A8 |( l$ S! x7 x# J
}
& K" T: r; I4 ^2 n* [& @编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。) s4 W: _+ B' F S* x: e$ N- ?% }
2.忽略了变量的类型,进行了不合法的运算。* N5 m @1 |' Y
main()
# N) T( B" Y. ?' P{
1 r! k8 X* X4 A |' R% m3 vfloat a,b;
/ |8 n- }3 \) D# W' F3 Eprintf("%d",a%b);# ?0 }4 c' |; A2 k, ]9 Z/ s
}+ z. P- H$ h' h: X! h
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。! {1 F1 i7 _! ]& l
3.将字符常量与字符串常量混淆。$ [* t" n- F* S) K; i
char c;
' o9 f4 M7 z% `* F( \$ e3 mc="a";
" N! a! f! Q3 @8 r: [0 B在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。$ x3 g* k4 \9 `9 ?3 \
4.忽略了“=”与“==”的区别。$ E9 X7 V2 I; [; W, j& u' f
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写# R+ d1 i5 V/ X) i4 O7 o
if (a=3) then …
- W& _& Y' C" k* n但C语言中,“=”是赋值运算符,“==”是关系运算符。如:1 N" a, p; }5 M, U
if (a==3) a=b;/ \1 y/ [$ c3 S# H
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
( o6 i( C% X6 T* w) e& G5.忘记加分号。
" i$ v& r' _1 X5 y. x& u. V, i分号是C语句中不可缺少的一部分,语句末尾必须有分号。
: C( ]- f+ ]" V/ P3 Qa=1- W/ r, A: K: } F
b=2 j4 f: \# G' }/ P. m4 H( @
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
3 Y }2 ^' c0 y* f{ z=x+y;& T; a3 |+ o$ O( u5 \4 p' Z: K
t=z/100;+ X% _. @3 L6 D$ h, K
printf("%f",t);! |% l" E3 s) M1 ] N" e
}
; i4 t/ m. F$ L4 `0 V3 e对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。+ X3 ]7 X0 M- i& ~7 X' k! w8 n
6.多加分号。, T% f& w0 G' `& B
对于一个复合语句,如:# U U* S* @0 ^7 K! ?4 q9 B
{ z=x+y;
# B2 w* v- _3 N$ ]* X4 J$ ?" H3 P: {t=z/100;
( ~5 w8 x2 K# k+ n/ Q! H Gprintf("%f",t);
6 C/ ~$ G% ]7 p3 [3 p" Y};5 h8 g" d# B* B6 c9 f) g( X
复合语句的花括号后不应再加分号,否则将会画蛇添足。
( [2 }/ x: M$ P又如:: z% H1 R$ s6 o- X
if (a%3==0);
0 w+ t: j5 y* l5 D y, `" E4 ^6 iI++;
/ B5 [0 E# t/ L- R# F本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
' T5 X$ W: Q) @8 _! ]3 p# a再如: t# ~) ~- C3 u5 w. [% {/ ]
for (I=0;I<5;I++);
% J5 ]3 \, H) Y1 m{scanf("%d",&x);
' }1 e8 {8 f6 Iprintf("%d",x);}
( Q, f9 n& X/ i( P% W( k" u本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。" `) h# q3 _. \$ S4 s9 g$ ^
7.输入变量时忘记加地址运算符“&”。% a# |3 N% e# Q
int a,b;
. b9 ^$ T% V1 W6 C5 P3 |- rscanf("%d%d",a,b);
- j( R5 O! B, ^% m这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。) P& k+ D* O3 k
8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);
) F7 {5 _ d. f; l# G4 q2 D& g% j1 Z输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:( G+ ], e3 Z% T' ?7 }- q
3,4 ' f1 e# E8 m3 s( P; `+ J; z. E6 e5 X, N
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。2 O. Q, g6 k: R2 {/ l; P
②scanf("%d,%d",&a,&b);
% s$ A' F* p* {6 W: b" U7 N: H3 ^C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:& X* h4 Z8 K1 X3 |5 p. s
3,4
+ B5 O& }7 a& f此时不用逗号而用空格或其它字符是不对的。
% t8 ^! C( G& [; F8 u( ?0 F3 4 3:4 : _8 P' ]' R) D x3 d
又如:
* T- e3 E# u5 |scanf("a=%d,b=%d",&a,&b);" V# E0 X4 }' v1 R$ Y+ Q. f
输入应如以下形式:
6 i+ D; I$ B, e6 g0 l( Z1 \8 ba=3,b=4 ' \5 K) l3 O) v8 a8 e
9.输入字符的格式与要求不一致。3 w/ {. p1 Y( e- |4 A9 N
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
* ~* ?- A6 z% J A$ S/ Uscanf("%c%c%c",&c1,&c2,&c3);
/ O) h |6 z, Z/ R1 G如输入a b c 4 A/ N H% `( g8 e. s" Z' p8 N
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
; V, ]) `) U; i- m4 x- q) G8 B10.输入输出的数据类型与所用格式说明符不一致。
- d0 E5 {, G0 ^+ R例如,a已定义为整型,b定义为实型
9 ~2 R, u+ J: V. E; n5 w m% Ja=3;b=4.5;
: ]+ d$ d+ }5 j6 Yprintf("%f%d\n",a,b);
8 T: ^; P9 H' m% \3 W编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。& J |0 d" x d4 C. t3 T) |7 e
11.输入数据时,企图规定精度。
/ m {7 v) Z4 v9 Uscanf("%7.2f",&a);
( \/ ^2 x. t$ ]3 O6 Q9 U这样做是不合法的,输入数据时不能规定精度。
3 R- d" n$ F+ e0 L12.switch语句中漏写break语句。' @/ S, m# |+ w" ?- Q7 }
例如:根据考试成绩的等级打印出百分制数段。
. I0 o( E' _! ]6 D T+ Jswitch(grade)
. e1 g; ?: c) E; S1 G2 x0 y. [{ case 'A':printf("85~100\n");
2 v! x8 g; [8 C- ocase 'B':printf("70~84\n");
2 D2 D9 d3 K8 H% |6 q3 rcase 'C':printf("60~69\n");
( r! x7 A& ^# |8 [& o8 |7 c K4 fcase 'D':printf("<60\n");
4 {4 _: A- X' ^* R, a& \default:printf("error\n");
3 q+ g9 M5 \; f6 C* Z$ d- u由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
8 J! d/ {0 @/ Dcase 'A':printf("85~100\n");break;1 q" `+ L" O) D) @0 j; a
13.忽视了while和do-while语句在细节上的区别。
- n' H/ z# k& D" ?9 w(1)main()
+ k9 `' i, Y! V% }8 [7 `{int a=0,I;
$ `& p* i2 g. o. Lscanf("%d",&I);$ d. A' }$ U9 z7 [1 i* ?
while(I<=10)
1 z. u+ ]& K( r" }{a=a+I;) M6 q/ R: y' \6 @' k2 W! K. T
I++;
$ o( p: @6 W& \) G# v! J& q}( D5 f; D/ x3 r; C0 d' o
printf("%d",a);
! E$ G% W4 F/ p( ]2 B8 Q}
$ P) s1 J0 n; b' ](2)main()
' d- T* ?+ `8 ]% w! v8 O* ]9 X{int a=0,I;
: e9 C1 B8 {" P! Cscanf("%d",&I);
7 F7 r! I/ _1 X' ?$ |% R" E i& gdo9 N( P8 C+ c: m0 n. M
{a=a+I;
6 c7 A# p3 b5 [/ i- \9 F; hI++;1 \: Y" z9 ]: [
}while(I<=10);. E( G) C7 C) A
printf("%d",a);
% q# E: M6 F4 _5 P. n7 R ?: K}) j! }1 [/ v0 s9 R# G
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
, r v4 n" G$ ?- D4 t14.定义数组时误用变量。
; @, a# Y. [- r9 ~0 @, W7 qint n;( K# S* c# _# f
scanf("%d",&n);0 L5 ~! O+ S0 H# `3 m
int a[n];
5 D+ c3 `+ P+ N T7 t! M6 ]1 d数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。, b4 v$ x4 S# @% _0 ]( S
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
* U1 z1 ]) o/ G7 O9 Q4 v- zmain(); ]/ O; T; M) T0 @- j( E5 P5 o
{static int a[10]={1,2,3,4,5,6,7,8,9,10};
0 r% R7 L, z' ~printf("%d",a[10]);4 ~" p/ ~* P" I. k4 B8 B, h! U) b
}
; q0 R5 z, v- ?% V* F! nC语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。8 l3 d: i/ H4 {* O7 G9 R! d3 _; V
16.初始化数组时,未使用静态存储。$ M) I% n, C2 k0 g
int a[3]={0,1,2};
! B0 J* B6 C" U k- y这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:' d6 U8 v* O+ x/ m' H6 ^6 j/ _7 p+ E+ d
static int a[3]={0,1,2};
' ?0 X- E8 W2 {1 J( E5 u17.在不应加地址运算符&的位置加了地址运算符。2 S- L) W) v: u* J2 `: x2 b
scanf("%s",&str);
+ z, `0 X/ N `3 X7 f* g; [4 ~C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:, @4 q. {6 ?- p
scanf("%s",str);
' J# n/ M) h1 o18.同时定义了形参和函数中的局部变量。4 D# k1 P+ d) [" c) {
int max(x,y)! M9 B h0 i8 ?/ m: ]* L- }3 f) ]
int x,y,z;- X8 w) Y+ R' i. z/ m
{z=x>y?x:y;
# g- [5 @" u* r7 m; n( T1 {return(z);0 h; [ q: A0 H6 @, e, m# ~1 `' V
}
9 M H; {% M, `- v1 v形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:( s& {. C+ c4 J' s3 _, i
int max(x,y) W) g/ N: N, t, K
int x,y;5 ?& `0 k# v0 F6 Z8 C7 w: u2 K
{int z; R/ C+ w& p6 c* U* y$ G
z=x>y?x:y;& H9 w+ g/ D/ [. V b) U- \
return(z);3 C+ s# p6 E N8 V0 M9 ~+ t
}</P># Q+ ]. C, l9 C) i4 X
< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|