Chinaunix首页 | 论坛 | 博客
  • 博客访问: 198498
  • 博文数量: 264
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 2740
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-03 13:25
文章分类

全部博文(264)

文章存档

2011年(1)

2009年(263)

我的朋友

分类: C/C++

2009-06-04 12:25:55

c语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学c语言的的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。
5 s' Y+ ]- {: D( g5 s( _4 Y% w0 M" T7 V& M: A3 w
  1.书写标识符时,忽略了大小写字母的区别。" v& m, y  N, r; W
0 Q. c' \* l* j$ W
main()# a4 G0 I) t2 P, |
{$ r% b: I9 i3 d
 int a=5;
5 y9 ^% W/ U; X, S. j4 V$ Y+ y( j8 ? printf("%d",A);( g# q2 x& N. w$ e: d2 u
}4 G" x& [- j. [7 l' v8 a  E
  编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。+ w# d0 C* o- P" }& |7 \3 Q; P
+ l# R, D: y8 {# g: K, s
  2.忽略了变量的类型,进行了不合法的运算。! t6 h5 }  `& S* ]

8 u4 a$ d1 H! N( I7 ?8 D& kmain()
( L7 C$ C0 J1 w% v0 w; M& v{0 O/ d5 |! l3 |: ?' f+ B
 float a,b;! \! l! ]4 C4 A" X9 r+ ?/ m
 printf("%d",a%b);
7 R+ q6 f5 W# l1 I5 T# O}
, C" x6 Y5 a8 F/ R. f8 x+ R  %是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。9 s; g# K+ g% B& |+ n9 G9 b1 W8 v

! J8 e4 Y" U# f1 c  3.将字符常量与字符串常量混淆。
4 D7 \1 D4 B/ E4 ^4 H8 q# K7 H: _  A; u2 n$ E9 l  j
char c;
3 x# q# [& m7 T' J% Uc="a";
2 I. R. v3 \; t! j) V7 J  在这里就混淆了字符常 量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加 上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。! N5 K' t. z! q7 j
9 I% F# L! B* Y* M
  4.忽略了“=”与“==”的区别。6 C. I  Y2 _- W

% m' X* F! P6 v4 I' b* E  在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
7 X$ p5 o, `; \8 Q: K. G
" K) M# }- n1 ^" \# U0 V% gif (a=3) then …
0 R6 I% ]: L4 d8 ^0 ^. T  但c语言中,“=”是赋值运算符,“==”是关系运算符。如:
$ Y# l$ k3 R; h/ u4 C/ ?
) A- i+ E3 y! \% X2 mif (a==3) a=b;  v- X  e$ M( w' g
  前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。# s$ f2 F! O/ m1 A+ g/ Z$ i. n5 e% Z

# M! Q8 v. C) b8 B# [9 i  5.忘记加分号。
1 N3 c' ^. b! E2 j8 D( \0 B" j. A% u+ n
  分号是C语句中不可缺少的一部分,语句末尾必须有分号。$ }# R: ]+ N* g% h! o( ?
3 D9 P* o! Q2 S  m1 X3 ]
a=1
( ?* a2 y; }7 I3 B' y% y0 J/ ib=2; ?" x$ N4 I: c! w$ _; ~
  编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。1 b+ g0 J2 ~2 \8 F. R! i6 B
. a' u) v) P7 w% r
{ & _+ N6 [+ b/ \
 z=x+y;
: V/ X( c. c8 K' ?( E" M t=z/100;
8 C2 e' H/ F8 g# y( n& E" o printf("%f",t);  d& \2 F. B$ k1 s' L& l, J
}
, w9 J0 r' x; K6 D# N# l  对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。( j0 p1 j# w' S7 f- j% v& H$ h# U
& \! l2 m" d9 s8 w% g
  6.多加分号。& A' W' g8 ~/ F$ q9 M! V2 j9 _

$ ~4 \. H: y4 |& z6 c/ d' m6 P  对于一个复合语句,如:# }0 z, C7 @- e' W' P$ Q
# K5 q4 c- l" @" c7 q- d
{) s# J1 {! E$ K
 z=x+y;2 w  M% L6 V1 K! O+ E) `% y
 t=z/100;
" L/ O4 `  z  d) p# p printf("%f",t);7 N: l1 g6 @; i3 V5 M0 `; ~1 |
};. u1 \4 r) H% P& @4 d  x. v
  复合语句的花括号后不应再加分号,否则将会画蛇添足。& t# z' ~# B8 g. V  }2 v6 W
0 c6 G) Y2 _+ T5 K3 G, x" `
  又如:
2 [5 }  N' n* o+ P( B
, Z, @, b6 T* g7 s" W) J+ Sif (a%3==0);+ M3 s/ \& g+ C: B( t/ y
I++;
( _' M- J" W1 J1 ]9 P( o# b3 _  本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。: R% D  o: u7 b* P
! \) e4 e% ]8 o2 I" b  e8 D
  再如:
  w4 A2 Z! F( Z, a. b% N
2 F; C! r  F* q% vfor (I=0;I
/ C0 N  t; T+ `5 x/ |! W
  F# Z7 ~6 X  N% k" c3 z9 N  本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
2 F9 L9 h+ t( j! v1 F1 [7.输入变量时忘记加地址运算符“&”。, N& Y6 R0 A' I2 t' ]

8 |$ v  _7 B! ?int a,b;0 E, v! E0 b8 R6 z2 ^
scanf("%d%d",a,b);
4 m3 k) N6 o0 O  这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。. U# P9 T. `$ W/ ?  ~- f# D, }

; W1 ^  `: r/ v. p5 ^8 }  8.输入数据的方式与要求不符。: q2 Y: @7 G' u- }; }
7 k5 N$ X7 Z! B6 p, [
  ①scanf("%d%d",&a,&b);
# \. h8 {7 R% h& Y$ \- N& K- a( G. T1 b: t/ x7 C
  输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
" e4 Z0 c2 g; W, J" Q5 ?' i
/ D2 p# |1 t3 D# |3,4 / b9 V2 J  H4 B. _0 Y' L+ s: o* |

: x3 a9 C* W) t% l  输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。. L  R3 }, E' H0 U1 }; o+ K
. ?9 g' u. O# \' |0 j
  ②scanf("%d,%d",&a,&b);
; h0 H, }) k6 |& g& g
" O4 a" Z2 E7 ?1 |! h  C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:( `+ Y4 b0 t" {8 Z. j

7 B0 x; q& X7 b/ N- ~$ ]* \, Z& w3,4 8 f, i) V/ G5 G# x: Q; ]( ~) y4 J
8 c; @3 d+ Q, z0 B" X  w9 d
  此时不用逗号而用空格或其它字符是不对的。8 F# j% P8 x  s8 w8 e# {* L7 M6 S
- W$ `# J0 M6 Y$ t, g$ Z
3 4 3:4 * o6 A# N$ Y3 l, q4 ~: j

9 f+ t  S4 G% c  H; s) V. O% _2 L2 N  又如:* e1 y7 i/ }) r" g$ h

: X  ^* S; C# A/ g2 i2 p+ U4 Jscanf("a=%d,b=%d",&a,&b);) x5 S4 H2 t. j" q2 q
  输入应如以下形式:
! O# X! ^0 m& i$ o* u# s( g
/ G, l/ {" q; W5 ~' r0 ?a=3,b=4
+ ?/ l5 u5 j* d; K8 j* k8 u4 o1 b/ M1 A# g
  9.输入字符的格式与要求不一致。
( F+ _  c* ]! _6 M) n7 p/ S
; u" X  ^. N, f) E1 t. d1 M  在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
1 z& L6 u- a; T( ?
- w7 e% @- d) s: rscanf("%c%c%c",&c1,&c2,&c3);/ P8 z4 X% x- ^  r8 V9 u3 e: S
% r2 c9 U4 Z; I$ n4 \, J$ Y+ A
  如输入a b c 6 k+ l" [. s8 @3 e) ^0 i

7 |: l) a' l+ Z  字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。* M0 ?$ Y/ t% `( x
; h8 Q) z7 j% _1 w  n% t+ m& v
  10.输入输出的数据类型与所用格式说明符不一致。
9 A* P( O0 l: j# l. C
! _  P0 \5 }% [+ S; c9 J  例如,a已定义为整型,b定义为实型
! z5 z) z2 f; |) x( |6 C  F; G% Y! g/ W4 E! b% l2 \) ^" {, F) q
a=3;b=4.5;
% ?$ {' l" t/ Xprintf("%f%d\n",a,b);, p& C* j) Y/ f3 p  T0 U- `* S
  编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
& ^% A% W+ \8 n
. A1 S' }" O  C/ c- K4 f) [3 j  e* b  11.输入数据时,企图规定精度。
4 l/ F5 L( R. [* y9 ~* U9 T& a" T
: `, T: x1 z8 X3 r( Dscanf("%7.2f",&a);7 M( E3 n) q/ ^2 {3 a! \1 f! e' c. E( R
  这样做是不合法的,输入数据时不能规定精度。
6 s: D) I7 S  g1 c  
) R8 ~4 h5 e8 I2 B$ d; Y  12.switch语句中漏写break语句。
9 k% D* ~6 C; X& R: E7 r5 [( M, @2 w" e) l8 A6 r; V8 g
  例如:根据考试成绩的等级打印出百分制数段。
9 ^8 Z/ ^" j9 x5 @' F  C( T2 J* j: Q, p7 y9 Z7 h) m
switch(grade)
7 _' I7 ^/ W# C. Z) F5 s3 @{( p4 M! L* b6 G1 q0 Y! z( X
 case 'A':printf("85~100\n");/ i# {+ @: g+ o- Q
 case 'B':printf("70~84\n");
  D% y) M5 [7 ?8 G7 S. t  ] case 'C':printf("60~69\n");
, I, Q* L& g: D4 ^& y* A4 L case 'D':printf("
$ h- S# ?6 h8 K- Q/ {. N$ K% c! z2 o6 x  由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
+ Z+ ^' I& A1 V8 o: g/ s# [, F! n. }4 u1 b0 C8 y
case 'A':printf("85~100\n");break;
3 o5 Y9 Y3 Q5 n% i( p5 o9 }0 z  13.忽视了while和do-while语句在细节上的区别。1 ^4 h) a  G7 p7 S4 v8 u8 ?

& ?: g7 g* }' b8 q  \' U4 ~  (1)main()" W/ E! m# v3 j2 A. L1 Q' j* {

6 p2 P0 a$ ~" A4 Z{int a=0,I;
( N  r& W* Q  ~9 s: Y, E" q$ P) m% S! yscanf("%d",&I);
/ V# P2 q6 y( ]% l* b$ H& R# ?while(I
- E' r8 P: x- k2 \8 z  (2)- F0 f) |; G+ h1 q/ e2 a

0 d# [! j% ]. h" `+ Z* kmain(); t6 X2 C" W7 h3 r
% o8 ?8 a* R0 `7 C/ g4 [9 ]7 ]
{int a=0,I;
" t7 B- K/ Q) y7 Mscanf("%d",&I);
8 V2 ?5 f2 }, o4 Ldo* ~/ C" ]1 b. [( c. F$ `8 I# N
{a=a+I;
" @$ @) `2 i/ e, XI++;4 K/ ]8 \/ U9 r. d
}while(I! C5 V" r" z1 h2 ]5 e" ~6 b
  可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而 do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
8 C2 R, q& F. ]" M& u) C$ x6 t3 y8 M
  14.定义数组时误用变量。- }& l2 s) @$ x5 R7 r( _

9 r# x- @8 h3 j9 Q- F' v3 L7 [int n;/ z2 K/ X4 ]3 f% a2 x
scanf("%d",&n);- Q+ H/ }7 |( T: \
int a[n];9 }0 d7 F! G5 H% _1 b
  数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
' H/ U( E6 n/ `, S 15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
3 ~: d6 y# W4 @- s: o/ X6 R8 C4 C+ t5 V
main()  H0 ^& h1 t* w$ \9 P7 P( ?
{static int a[10]={1,2,3,4,5,6,7,8,9,10};4 [( u/ ~3 T" X; Q" d8 }
printf("%d",a[10]);  c3 g2 C; }3 ^0 N+ u1 s. a' h
}, ~' @# L4 ?8 a% T8 J5 _' l0 d
 C语言规规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。5 j; T: S/ l' {+ K: ?
3 M# ], j) j- u; u% n- P
  16.初始化数组时,未使用静态存储。/ ~* w: a5 b; V6 k

3 `7 B6 c5 s% E* o- }, Y0 D. Pint a[3]={0,1,2};- c1 I- Q2 U1 P+ _; ?* ^- ^1 `
  这样初始化数组是不对的。 C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:* e: b  v3 N+ ^# `
4 T/ B- c3 g( L" E; x2 _
static int a[3]={0,1,2};
( d+ y' I, P2 s* W  17.在不应加地址运算符&的位置加了地址运算符。
% M" i$ W; O; H% w1 Z3 u- g' G# Q, p% N, A1 l6 ^
scanf("%s",&str);0 n' K. @* }1 V; K; I. r
  C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:
) ?8 B% u# t3 _7 l* a9 n8 H8 q) _! p7 i6 ]& k( S5 s3 s
scanf("%s",str);& H7 X2 j# m5 Q8 m2 ?# k
  18.同时定义了形参和函数中的局部变量。
4 D5 Z" `( v- |& @  p+ q7 M
* {( _* ~, j+ gint max(x,y)/ v. l6 A6 ]6 |0 m3 y
int x,y,z;  {0 ]# y# v6 Y( @4 O3 x, I) V7 m
{1 |9 |6 S# h  [* T
 z=x>y?x:y;
( \! ^# e/ V& B1 o: N; K) D+ t5 T return(z);+ x7 \& e7 }) J( _
}
6 K, |! o/ u5 m. C/ U) g( b4 U  形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
! A9 E' k* D4 P
  ~# o. \) H. i6 Zint max(x,y)
: r, w" d# A- z; q4 K+ Z3 P+ N% r8 Fint x,y;
: T1 R! X4 Z9 h9 R1 T{0 D' v( k8 `, t/ C# |& s
 int z;
+ [' _  |0 B- D2 y0 `, C5 Q z=x>y?x:y;& R5 x5 @% _" V! k
 return(z);
5 |5 P* ?7 h7 H8 Y6 M2 p; A# }+ A}
阅读(191) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~