- 在线时间
- 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编程时常犯的错误,写给各位学员以供参考。
5 _$ `/ m3 `1 W6 W$ `1.书写标识符时,忽略了大小写字母的区别。
! j) I1 }# U0 q, g9 J4 p+ Q% @# J! gmain()
& M% @ N: b. V4 C{
! M: P* ^* w3 w5 M9 g2 Gint a=5;3 b) w: b1 X! B! q4 [' N
printf("%d",A);# d* J. j+ o& j
}
" B, \3 K+ t: N/ ^7 T编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。( x* ]/ e: s$ ]" c8 }
2.忽略了变量的类型,进行了不合法的运算。
n, k( z$ Z. A- Gmain()
4 N3 v# T% u9 V3 T9 u4 O! i8 O( a{
# d9 j5 J* t% bfloat a,b;# h; D7 p0 o8 x" I& Z
printf("%d",a%b);, d6 r+ ?4 B5 r2 k) _; j8 R7 ?2 G
}
0 X& n4 a8 R# y- U1 O%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
& W y/ w4 K" E7 x9 M6 c( l0 P8 A3.将字符常量与字符串常量混淆。3 N. h' Z- |( y
char c;' J. z, b# I! I
c="a";$ O% Y! P+ O4 Q
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。: n- j- S5 `0 o# _! g- v: Y
4.忽略了“=”与“==”的区别。+ ~& X; W9 k6 W! t3 l
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写# a- u' t- [+ S- z3 u: W
if (a=3) then …
; f9 n" r' z S; F% }& d5 \. [0 d但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
; f! m3 c( ?* U' jif (a==3) a=b;
: F* v) }3 D% E' I' e前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。( r% ]# W3 r" u# z6 w7 d& P8 N
5.忘记加分号。- Z4 K+ `! ^8 j- m
分号是C语句中不可缺少的一部分,语句末尾必须有分号。* X2 p. K, m' H2 r* o
a=1" N/ g. ^' `& d4 ~8 b) ]
b=28 i6 q) P* \- T- o- ]
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
1 ]; r _, X, O8 i: D& J' d5 r{ z=x+y;
# ]2 M! f" I9 l% B9 i" O& pt=z/100;3 ^5 |$ Q" P: R. w2 B9 Q4 Y+ S' I! ^
printf("%f",t);
4 d) \7 \1 a8 w* S; a9 q2 @" ?% o6 P}/ V8 G( T& \8 n, Q+ }7 x; q! w0 A. e
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
) o7 u3 B# f9 d& x* W) s" s6.多加分号。& I: e u+ z( |0 t
对于一个复合语句,如:+ h" q% y+ {& l& V M
{ z=x+y;6 S5 W2 ?& T" c1 g' }
t=z/100;% C# n3 [: b( z% u9 ?! J8 H8 B1 i
printf("%f",t);
+ f, q, N5 \% v8 z};
' @' v2 O8 L2 A$ h! ?5 X# G/ J) b0 i复合语句的花括号后不应再加分号,否则将会画蛇添足。
# u4 Z/ M7 i P1 _又如:
" ^' H, `; X( `* G; G6 l5 D" cif (a%3==0);# K4 _* L: ^0 B. \2 w- z' l7 M
I++;: K5 }* ~9 m2 b% Y% p2 l
本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
; K6 w: A+ ]( G; T0 Z1 M再如:
' N( L- |' J% E: T2 C5 m; R$ {for (I=0;I<5;I++);$ i5 `7 y( C- S5 O7 p: ~
{scanf("%d",&x);
) Q, r' I% \! R9 Z. u' P- n$ j! Pprintf("%d",x);}
. `; k8 K- N& J本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
6 I9 U, _7 q3 p% u7.输入变量时忘记加地址运算符“&”。 ]( l; ^) r' o, z
int a,b;
. I$ i9 A+ F1 K* c oscanf("%d%d",a,b);
8 w; V+ V7 B, m! z这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。
2 \- {' P9 N+ j% G3 h- R8.输入数据的方式与要求不符。①scanf("%d%d",&a,&b);2 x$ E, N2 h4 P& d% l7 b% {: |
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:* w. @4 v( y! m4 ]+ v: t5 s
3,4 ; d. `% S0 m5 G% B7 v2 |
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
/ d7 [5 G5 H( p) { | s& u2 I②scanf("%d,%d",&a,&b);& _4 Z N O8 q
C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
6 `7 b! B& S: N) U3,4 8 u' k0 c" e( v+ L
此时不用逗号而用空格或其它字符是不对的。
+ I! l" D2 K. b- X* N3 4 3:4
' O$ g" f; p$ j/ o9 }( J, }又如:$ v7 K9 `" ~" c# l5 z' Y
scanf("a=%d,b=%d",&a,&b);# p' ~, h8 U" @: c+ F
输入应如以下形式:0 ~! |5 l) Y/ l) \" i) g, ^
a=3,b=4
; i" V4 y* B3 u3 C# N- g6 O: x9.输入字符的格式与要求不一致。
7 k3 x( r1 x6 Z' l" Q; r- E在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。$ S5 D- l9 g& g0 O# U
scanf("%c%c%c",&c1,&c2,&c3);
( ^) o2 F& H6 E/ G如输入a b c 3 J+ [: c. Y" c) t" y( A
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。& _ a) C" m: y: W4 M7 ?( Y
10.输入输出的数据类型与所用格式说明符不一致。
7 L- @5 y6 C& \* H例如,a已定义为整型,b定义为实型
6 g' N, w) U& C( wa=3;b=4.5;
) }& Y. @3 L3 Mprintf("%f%d\n",a,b);
\. N, r( X8 m9 v编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。" w; Z, h% G& F' @6 T% n
11.输入数据时,企图规定精度。
( m, [. e( ~; `2 e1 A+ x/ Cscanf("%7.2f",&a);% A8 J9 \% j+ ^7 o+ p8 w% N* R% {
这样做是不合法的,输入数据时不能规定精度。
$ U0 v) G- `) y0 O2 `12.switch语句中漏写break语句。
; B8 i1 ^$ T/ S# F) N8 H例如:根据考试成绩的等级打印出百分制数段。
2 h' o2 N. L5 G3 t2 E$ [ o. Z3 s7 z% iswitch(grade). i+ g1 N5 y+ ~6 o
{ case 'A':printf("85~100\n");
7 ?- b; A7 l; L' Z1 m- Pcase 'B':printf("70~84\n");+ C; F, _5 a; |( s/ w* e
case 'C':printf("60~69\n");$ D" R0 s" w0 h6 ]
case 'D':printf("<60\n");: F8 M! d* C! \! i' E" C
default:printf("error\n");
5 a3 u f/ K, E& T J/ \0 B, d% v# U由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
1 j9 R: a; p# S6 v7 y& w5 o) Hcase 'A':printf("85~100\n");break;$ Q( K5 i5 q( ?- g# {2 p" o
13.忽视了while和do-while语句在细节上的区别。2 ] w; `" Z6 c1 z3 t
(1)main()
0 u& J u7 y. Z+ z! j5 ~{int a=0,I;
' t8 l" e% a; g+ Gscanf("%d",&I);
" S+ r: M, `( q6 s) _8 k3 m. Gwhile(I<=10)
" T* V" q( W8 P{a=a+I;& Z) q+ `* |& w$ G1 ^0 v; Y
I++;. M9 ?# G! k* k- q8 q
}
$ |+ e3 G) n$ y, `4 n! kprintf("%d",a);
: c H, _- |2 O1 M}! D* O4 v) {! v0 ^* ?8 @
(2)main()
$ M* [# T8 @: k% h' R5 \" F{int a=0,I;
+ v6 N5 M: T9 ?) A' cscanf("%d",&I);
+ T5 O+ Q# l, B$ Q8 ~ ~. Bdo
" Z; D5 S' l! H6 T" b- g{a=a+I;
8 }! P: s+ N# _ ]4 _I++;' n/ e* }& ^/ {. r" V" M9 }
}while(I<=10); Z- t1 }( X+ L+ U" \" I/ c( E
printf("%d",a);
( S; P, @5 P, l- D}! z5 c3 U! P, G, _9 t) V. K2 P
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
% _0 \, ^3 A0 Y( o1 ]) n# k2 P( H14.定义数组时误用变量。% z( y; A, @! D
int n;1 ^& N% W& s* c, f' [4 z
scanf("%d",&n);- E# g8 V% q4 x$ [0 h5 z
int a[n];& e$ Z: Z# X7 ]9 L( ^ w
数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
) H; E* d* F" [, y* C: b& p$ ^ @7 }15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
0 C$ N- S3 O3 `- V! E% W3 tmain()
9 Y; y* B% p, l; p" n- }{static int a[10]={1,2,3,4,5,6,7,8,9,10};
0 Y9 @6 {& {5 }# v* p4 mprintf("%d",a[10]);5 r4 q1 q, n; d; W9 p/ o/ o3 ]; q' W
}
/ I' U' ?4 L+ c8 t. @/ h3 CC语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。: Y6 f6 c) r* B' N$ S- K3 x( T/ r2 @
16.初始化数组时,未使用静态存储。+ G! w; q& \/ @
int a[3]={0,1,2};# H& b5 o* M, |
这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:6 [- `4 Z, d3 w9 x
static int a[3]={0,1,2};2 Q, _" y J3 i6 {2 k6 R7 t; ^
17.在不应加地址运算符&的位置加了地址运算符。
" `% |$ q2 B+ [3 r! x3 M. ]$ Hscanf("%s",&str);% l9 G, a$ B! L# v5 R& x
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:
( D$ {6 _) R1 `# c7 ^7 w) m8 d4 `3 n$ Jscanf("%s",str);
3 N' z. }9 @2 Y, L& J18.同时定义了形参和函数中的局部变量。
6 w) i7 s) V$ {; Y* {4 ^% Gint max(x,y), a7 Z$ \6 L ~! v' C9 S9 m
int x,y,z;
5 ]. K6 d2 w3 ^! m% Z" W+ E( r e{z=x>y?x:y;
4 n6 N. p$ r% C8 Oreturn(z);
) B( P4 H0 ^% V}9 P. {6 u( B7 n
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
8 \) Z0 e% r# d* m+ a; |+ Pint max(x,y)7 a4 R6 L; Y; |1 N* W7 W' O
int x,y;- f& Z' n3 f9 e, L: O6 O
{int z;
( h* W. n5 W8 i$ Fz=x>y?x:y;% b T0 ?8 G$ e' J1 Y' ^/ @
return(z);
* e1 K' t* |0 _}</P>
: n+ c/ E6 `! Y% ` j< >以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P> |
zan
|