- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。
! _) l3 I- f0 K( a8 l* @. l* L1.书写标识符时,忽略了大小写字母的区别。
- n! Y! s, ^% t' _: o( a: umain()1 Y) P1 a$ w' P$ A. {- {0 S0 t
{
7 i. n9 c0 B4 K& a% d3 n! vint a=5;
: A: v8 B6 S7 h/ Fprintf("%d",A);! h7 K! m2 L* T" s) q
}. w2 H# U% W' \) c" J# q j
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。/ _' j9 X, t! M9 R# k
2.忽略了变量的类型,进行了不合法的运算。* a/ q) e& ?% V! W% X6 @2 _7 b& T
main()
0 N% P2 k* C" J9 L* ]{1 m4 ~% E2 g, b$ j) _% G) x
float a,b;) _* r. |% B+ e4 A6 Y
printf("%d",a%b);
( ?9 K. N7 ~; c3 }% R( X) U}" u4 [! L2 Q5 f1 ?- {
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。% s& I1 t, L( Y3 O/ P3 A1 Y6 Q
3.将字符常量与字符串常量混淆。
: b" Y# _, g& |char c;+ m% h& _$ @0 t$ b# Z3 ^
c="a";
* q4 S0 ^3 @7 R# Q: Q+ \3 C在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。
3 `6 B& w2 v) K4 X7 V6 `4.忽略了“=”与“==”的区别。
, v& n, W1 e5 `2 s8 k: A/ H/ O8 e在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写7 q% X$ W2 V8 ^7 {
if (a=3) then …. a& G6 U0 |, U- p
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
0 t- c- ]/ Z3 [) S X: Pif (a==3) a=b;6 d4 ]+ {( w/ l' I- {
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
* Z. R9 H+ M% P5.忘记加分号。2 l" ?# Z$ ~# I: C
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
% ?% j! t+ G# H. f- i4 u$ r+ m/ }a=1
4 H3 h$ O3 E. e5 Pb=2
$ g! ?- z- [9 q# U7 X- H1 z编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。 e/ I' \4 u4 C8 A
{ z=x+y;: o, n8 x( U# D
t=z/100;8 r. ~7 m" S$ j+ G$ `/ E/ ~
printf("%f",t);
n& E( d9 J0 Y u2 g}- S: J0 J6 Y' i' K H
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。7 g( Q+ w1 ^3 P8 M6 t
6.多加分号。9 g) e, b* s& i" U) A" R# `
对于一个复合语句,如:
5 V0 `- s" I) c! J: E& k{ z=x+y;5 M0 A! F& Q' D! u( o
t=z/100;5 e$ ] u# ]7 e0 C* r. Q$ O3 j
printf("%f",t);* g3 K0 g" I0 d9 I* V
};8 ]: o2 r4 `) ?& j0 j: v
复合语句的花括号后不应再加分号,否则将会画蛇添足。0 m: @" z/ Y* g3 V2 m$ t
又如:
) u, O* |9 q+ d( @if (a%3==0);
% A+ J0 f0 k$ X+ FI++;* N1 o3 P; e4 u2 O
本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
; w% M0 U+ T' T再如:
0 E% I! X- G8 z, X) M, t! \for (I=0;I<5;I++);
8 e: {' f/ T$ J# t{scanf("%d",&x);, L7 `0 }- R" K3 R
printf("%d",x);}
0 Y! f) l t. w+ {# B) h/ s1 j本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。$ U5 x: C i& i. K2 \
7.输入变量时忘记加地址运算符“&”。, @# }4 A6 F8 h. J8 K" V
int a,b;
4 W* I4 W8 u( v2 z8 N' L8 C3 I# iscanf("%d%d",a,b);
1 R y- Z' O5 f- A3 b这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。
: ?: K7 v7 z9 b3 j% e8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);; {6 \3 u0 c# H" I ^
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
: `. p1 ?, @0 G9 `7 f* H3,4 ( h2 O' J$ E7 R0 f
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
- J8 j; N) n& L: O5 N②scanf("%d,%d",&a,&b);
3 u/ v3 n c4 i. B+ [+ ?C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
' }/ M$ m; B# V! A, J& R" h3,4 6 M2 Z# ]) k; Y3 ^" O8 Q8 \+ t% u
此时不用逗号而用空格或其它字符是不对的。
5 q! X9 K. Q7 g& p3 4 3:4 : Y- l6 L* ?' p6 \9 u) x* Z
又如:! D( w; P, u+ P6 ~ K; ?
scanf("a=%d,b=%d",&a,&b);
9 M4 _$ s0 j* F% V* R9 l# Z输入应如以下形式:* E* {% Z- |% q$ J4 R
a=3,b=4 & Y# e5 M/ }* q' Z
9.输入字符的格式与要求不一致。
' X; V+ X* v6 L+ |8 C% B1 _( p0 B+ T% f在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
; a, t B% o1 A7 ?# j3 }) x; qscanf("%c%c%c",&c1,&c2,&c3);* v# s, f: d* Z+ r. ~% X& _- V
如输入a b c
- f/ ~: D$ t, H$ X. i8 ~ Z8 t字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
* c3 d6 b+ \/ D10.输入输出的数据类型与所用格式说明符不一致。
. r+ A+ y5 j/ Q) B9 S3 t* N4 Z例如,a已定义为整型,b定义为实型! H2 y7 _# t+ |: L) O N I- ~; K
a=3;b=4.5;& Z1 _( h- k7 w4 c; L0 F
printf("%f%d\n",a,b);$ u% M6 p) H9 s) T/ Q/ p: K! @
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
: n2 j; L3 } ^ {: B4 K. A( E$ B11.输入数据时,企图规定精度。' `0 v- o7 @5 U5 p" K
scanf("%7.2f",&a);6 ]: m! Y Z! n) f3 C. K
这样做是不合法的,输入数据时不能规定精度。. u# t" e, o2 F) `
12.switch语句中漏写break语句。. r4 @/ X- {# K( |
例如:根据考试成绩的等级打印出百分制数段。
2 ?$ u; c- ?+ O, q; Gswitch(grade)6 u9 x- a- \: [6 Q, r
{ case 'A':printf("85~100\n");: r% J g$ `- c3 \1 f/ c3 e, J
case 'B':printf("70~84\n");2 q. a5 f0 Y! r2 i! H: V O# l
case 'C':printf("60~69\n");
: v* v b* a t7 P1 y6 b5 [case 'D':printf("<60\n");
1 Q2 ~1 N2 t8 _, R6 J" b P6 g( a- cdefault:printf("error\n");1 c' |& K3 o7 Q0 h
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如6 r) N/ a( u; Q, [8 Y
case 'A':printf("85~100\n");break;+ W0 [/ V5 U4 ~% w3 X; I% Y; j
13.忽视了while和do-while语句在细节上的区别。
" t5 J( f, Q& [8 N- j5 p& n+ G(1)main(), n; j4 C6 N7 f9 F' W
{int a=0,I;- T" G9 Z, A! L( Y4 h
scanf("%d",&I);
9 \& f1 U1 l' A( |! }# I# a8 [while(I<=10)
$ C3 J5 I5 \8 O{a=a+I;0 b* v6 ]0 K' _1 I/ J2 p
I++;
' E. u8 ~2 Y" @+ _}+ c% n& Z! b/ L1 {0 Q7 n! j+ e! b' d5 L
printf("%d",a); @/ q n) f% O7 l+ X/ T7 v2 o
}4 f8 _6 C3 C- j; _ V
(2)main()
2 v: e F# H! a( P: x{int a=0,I;
# _% u3 d+ c) Y7 K2 q) p# Vscanf("%d",&I);7 n& E n2 I1 H g7 }9 k: ]; j
do8 G, G. J; ?4 p" K) U y" _
{a=a+I;
. |% C' t" M5 G8 @2 D% TI++;0 R' m1 e Q1 m7 G
}while(I<=10);/ c, F8 F1 `) P' k8 ~
printf("%d",a);
% `) _1 t! P3 Z6 f} w/ E# F" D' n3 P* K- i$ P. j
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
9 D. N1 J7 j8 D# U" n' i' ~5 M14.定义数组时误用变量。' a" w% N0 A! ?# [+ b; M/ c% p
int n;" U4 o! }7 @5 u$ @& d, {* e$ u, l
scanf("%d",&n);
# c/ o0 N' q8 c- X! J# Mint a[n];
" t$ m" m5 V0 u w: e数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。+ P3 x& ~* o+ M, Q$ K5 T$ G
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
5 I( A- g6 Z- j2 wmain()! z% V+ F1 y3 }. B7 N3 n9 z: k- I
{static int a[10]={1,2,3,4,5,6,7,8,9,10};
3 G u4 f3 b. Bprintf("%d",a[10]);
$ U$ K% h- o# m& V! C9 u}
2 R( B( j* A9 ~& W" N$ Q' GC语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。3 p4 q. h) O1 M( P; S/ n2 G/ Y
16.初始化数组时,未使用静态存储。
+ `# L" Y/ d/ W1 ^+ wint a[3]={0,1,2};
# `) A, ^# ^; b* D) W1 N* S这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:
6 F! F s) v, W$ Sstatic int a[3]={0,1,2};# c1 `8 K3 @, ]+ |3 I- c
17.在不应加地址运算符&的位置加了地址运算符。# C* L- N1 g& k$ ^9 X
scanf("%s",&str);. V: t$ Z) X- P
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:
: M) d5 G- d8 ?1 |: W5 i+ vscanf("%s",str);4 [! c& {+ q: h1 \' Z/ e, H* w) ~
18.同时定义了形参和函数中的局部变量。1 q7 D1 Y: {0 b) w# O8 ^
int max(x,y)
4 a7 B' T/ v$ j% C0 _int x,y,z;. Z! r! _3 h3 u
{z=x>y?x:y;
" e4 U6 v# E! F: S- Z0 k( ~return(z);- M& G* _3 a# p7 [5 [" n/ M
}. o9 V* W2 d- {5 Z6 R8 D$ X
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:& F- Y3 c) y+ @1 [+ B
int max(x,y)8 ?1 w' C% I, X- V( U
int x,y;. ]* x- q3 g) k5 H% E7 C
{int z;; B3 ~3 s; Z3 f" v
z=x>y?x:y;
9 `" o0 Q4 e# E5 d Y7 x+ o& Ireturn(z);3 P7 ^' B. Z( H8 S% B$ Z! d5 e
}</P>
- p4 `3 ^7 H2 Z. z( _# B< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|