QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2498|回复: 0
打印 上一主题 下一主题

[转帖]++C语言中常见错误++

[复制链接]
字体大小: 正常 放大
solucky        

17

主题

1

听众

109

积分

升级  4.5%

该用户从未签到

跳转到指定楼层
1#
发表于 2004-6-6 19:01 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
<>C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。
+ V1 X. r, w3 S4 b( T- [4 h8 f1.书写标识符时,忽略了大小写字母的区别。
" X6 }0 {% M0 S9 {9 Q% u" hmain(), M8 f; E/ b7 R0 c+ t
{9 W( q" B0 V; K) @* k6 |
int a=5;
: I1 f3 {9 z1 H& ?4 W$ Vprintf("%d",A);2 f+ W' C6 y  A' y2 b8 C9 ?3 z
}9 j$ V2 b$ n( h7 p
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
1 R* b2 g' B9 n& O( d2.忽略了变量的类型,进行了不合法的运算。
% p7 l  K2 T) ?7 _main()
4 E+ o0 V5 K" b{. \1 ^4 z; `1 |5 f1 ?
float a,b;
* {" X' P6 U: X8 Z! Bprintf("%d",a%b);
% N7 N' o2 \! z2 D2 C8 K}
% C8 R0 v; Y5 l: v, k" u& V" E- t%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
9 ]9 ]; e# X! q6 U! _0 j3.将字符常量与字符串常量混淆。' f: ]' `5 \& ?8 C
char c;5 ]/ m0 l) v: ~9 o
c="a";* y7 J, C* b% G/ F4 W
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。1 l4 Z0 V1 x3 {4 p% Z
4.忽略了“=”与“==”的区别。
2 C& z' ]* e6 Q5 w; Z在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
) N# B- V. T+ s* C' Nif (a=3) then …6 H# i: ~0 s1 U4 r' H6 V" [
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
3 D5 G7 ?* W( z3 q, O, }if (a==3) a=b;+ N, m. ~) C5 k# A0 e; g8 t
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
7 \; c$ m' t" G; H* {' D+ ^5.忘记加分号。9 b: s$ @" e' Y+ @) y& N: f  |; U
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
& k5 w- Z1 ^6 T3 A' E& a1 @a=1
2 X( w) f6 G8 `$ M+ J& k( ^9 @9 gb=2
! x8 f1 v# A9 U7 z6 G7 |  C8 o编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。$ g4 Q3 V5 C1 o8 X7 n5 W
{ z=x+y;
' B* ?0 ]# _. C) Y, H' ct=z/100;
9 b3 n9 K9 o. r/ J5 uprintf("%f",t);3 K% R! E+ l* ]1 @+ r3 C; p
}. J# K8 z0 X$ R+ k
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
1 o- S- o1 Q: ]. x+ H% j+ _6.多加分号。% h; ~/ g7 q+ F9 N. z
对于一个复合语句,如:
  S2 B# w" ^6 V6 f, x{ z=x+y;8 C/ I) i/ @# `" Y$ y$ c
t=z/100;! ~9 Y; t! v5 P5 h8 R% w
printf("%f",t);4 `% y6 P; x  A4 z& p" _2 m+ r( O
};
( c! D2 e2 ~* C! S# o4 x复合语句的花括号后不应再加分号,否则将会画蛇添足。
" x0 K* L: m+ C* W( s6 L# y3 L又如:
- O4 b8 b3 @& t' F' ^1 _' Fif (a%3==0);# ^% C: V  e& S* n( G
I++;
. ^5 c" C: R: c# Q9 D7 c6 p+ J本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
$ X) p$ V% W% J  {再如:1 ^$ w8 I' m' Y. ^( u1 l7 m# ?% `/ }) r
for (I=0;I&lt;5;I++);
7 c+ G& E6 g$ U{scanf("%d",&amp;x);5 t) k' N- ?7 [, }
printf("%d",x);}
4 ]. z2 H" L- n* V- T本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
& H: ?2 t( ~6 F) D  H1 H. g1 E7.输入变量时忘记加地址运算符“&amp;”。7 d3 ]5 d7 F5 `8 Q' t- O5 T9 @$ H
int a,b;
! X. w: H3 b" ascanf("%d%d",a,b);! z8 M) ]4 l5 `: a* U, X
这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&amp;a”指a在内存中的地址。
0 ~" \1 C4 J; d0 Y- |/ K$ v% {8.输入数据的方式与要求不符。①scanf("%d%d",&amp;a,&amp;b);
' W" v2 h* W9 ?% a( O输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:7 D% p2 y3 V1 T  z) a0 n$ y" ]( T
3,4 6 r% t5 @! w2 h
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
% J( W8 k" m3 X②scanf("%d,%d",&amp;a,&amp;b);
% t- Q% u4 V5 h: HC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:' U, Z: J9 b/ `: H6 b9 w
3,4 , B5 Y( y+ q" h; {9 t
此时不用逗号而用空格或其它字符是不对的。
% f$ h. Y" E' F* w3 4 3:4
* q" R" ~' Z6 K又如:
2 e  C& U) Y) h- Mscanf("a=%d,b=%d",&amp;a,&amp;b);
- `9 \9 k) f. f2 h输入应如以下形式:$ Z+ z; e7 Q5 i* s; ^5 r! i
a=3,b=4 8 j3 m" a- X2 D) [
9.输入字符的格式与要求不一致。
9 K- {- D" Y. ~1 q# s4 _% W& L  t1 q在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
7 C/ j% n) V* e  lscanf("%c%c%c",&amp;c1,&amp;c2,&amp;c3);
+ K. o  x, C2 V' p  T3 I; H/ N5 w如输入a b c 2 n- j- t7 L" N" e! {- O
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。8 ^6 @5 u% p$ ]: M+ p9 `: N6 I3 V
10.输入输出的数据类型与所用格式说明符不一致。
& p6 D% U$ o- W# Q) B+ l1 ~+ Y+ x例如,a已定义为整型,b定义为实型
6 n* J" z3 P+ G& La=3;b=4.5;
+ Q$ ~$ Z' j$ L3 n. aprintf("%f%d\n",a,b);! s6 n2 z# q# z* L# P: @
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
( R" O7 U1 i  f7 D  D11.输入数据时,企图规定精度。
4 ^8 w! ?- A0 ?5 o! j: M4 ~scanf("%7.2f",&amp;a);+ X& e2 `. P& w* _' K
这样做是不合法的,输入数据时不能规定精度。
; t( K5 D  h. C0 M: k" o# b$ {  O12.switch语句中漏写break语句。4 Q1 i' p, |3 J: E% ^' W# Z
例如:根据考试成绩的等级打印出百分制数段。
  K' \6 i% g  A, @switch(grade)3 Q$ t; }( `- y5 y( i
{ case 'A':printf("85~100\n");
/ Q/ D4 t: l7 C) Icase 'B':printf("70~84\n");
4 J  f8 {5 f/ k7 m- g' pcase 'C':printf("60~69\n");
2 }5 P  o7 R1 Rcase 'D':printf("&lt;60\n");- [  X/ p" y3 |
default:printf("error\n");: i# v6 d2 Y4 Q7 M. C4 T
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如( }2 r0 @; E7 p! t+ b0 G3 m
case 'A':printf("85~100\n");break;0 \5 g" {3 e: e5 X4 u8 Z) B8 }
13.忽视了while和do-while语句在细节上的区别。% n( k' D8 c* A: {; A
(1)main()
$ a( s8 B0 s4 n- N{int a=0,I;: B9 F9 w, K. I! l& Y# [
scanf("%d",&amp;I);
/ v$ c; c0 Q/ Kwhile(I&lt;=10)
4 G3 q. O$ p6 \, L" {0 C) v{a=a+I;
; t% W% R3 _9 {: \" BI++;- C: L8 [/ D  h4 p
}
# x. k9 L  B$ t8 T9 C' [: Sprintf("%d",a);! r; R1 ?% `3 B" n0 ^8 ?! W' K
}
( t  _0 f# z: F' i% Y$ z% D% ^(2)main(): V6 |5 L" \9 ^, q' W  E& ?1 d
{int a=0,I;$ \/ b5 C5 M0 y1 A+ o
scanf("%d",&amp;I);! k: g! F2 A/ E+ j/ W5 z& x! F8 ^/ a
do
$ j1 a& V$ _0 |{a=a+I;6 s! N! I4 d# a6 t4 [1 ~
I++;
3 z: I* R3 `: ?( U) N}while(I&lt;=10);# I% r* U* k8 K
printf("%d",a);6 Q$ O- K: @8 K2 V" [7 R- a
}5 ^$ s) n1 l+ L- T7 @$ q
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I&gt;10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
( f7 ?( V5 j/ q! t14.定义数组时误用变量。4 c2 K. ~% k, z! u$ n; l0 T
int n;% t9 C" N& [) }$ L. m, e
scanf("%d",&amp;n);
2 T. ?+ B3 \* R% O( b8 v; qint a[n];
* {9 a% v* U" \+ z& |6 k4 Z( p数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
7 T8 v/ O" F0 X& u6 `" ]15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
0 S, ~& [  J: G$ e7 Imain()
& K& P1 y# C. l, b{static int a[10]={1,2,3,4,5,6,7,8,9,10};
$ ]. ~* e  W' B, L/ Z+ Sprintf("%d",a[10]);
5 K+ K& V! Z/ \; Y( t/ X}+ n7 S& X, H6 N( i3 o# Y, F
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
2 @' ]; ]$ L6 W# q16.初始化数组时,未使用静态存储。- v* m2 V6 |: }, [0 w
int a[3]={0,1,2};& g. K0 `( m4 A6 H2 n9 [6 D. j
这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:0 Z0 z. Q- r0 y. y# M' L* ^
static int a[3]={0,1,2};) Q1 K& |0 F( r) h4 h
17.在不应加地址运算符&amp;的位置加了地址运算符。
  k& b( _$ m5 D4 Tscanf("%s",&amp;str);
4 `4 e1 h0 N4 ^$ {0 Z  ]! CC语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&amp;。应改为:
$ ~" I. B. Q1 m! G) ascanf("%s",str);# [8 O+ X5 L/ j* A* @6 {# F. U2 g
18.同时定义了形参和函数中的局部变量。' \9 V1 l' [( h, X) Q( T
int max(x,y)
1 c( M+ g' ^) ]4 l) f& Q2 Tint x,y,z;
) u+ y2 {6 k/ k+ L0 c0 Q8 \{z=x&gt;y?x:y;
6 h8 v. D- i9 v. W- jreturn(z);+ X1 ?8 A) @1 d* }
}" h! T! N  ]8 E( r9 U
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
: d( ]2 N* Q; H1 l3 iint max(x,y)
% w1 F+ N8 d/ }' T+ uint x,y;
; @& H  c. P. Y* u! f{int z;
1 u' L1 ]4 e+ n: Nz=x&gt;y?x:y;$ T3 z: G  Q( J( ^5 `  w
return(z);
1 S6 Z. h# g# E: D% D4 }( J% i7 x}</P>
# y1 R$ u% v. g2 J0 s; @<>以上错误中可能有些不符合新版的C语言,比如数组的初始化,新版中就可以是不是静态变量。由于是转贴就未加修改,以保持文章的原貌,请各位自加区别。<b>版权属于原创作者!!!</b></P>
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏1 支持支持0 反对反对0 微信微信
笑一笑 只牵动苦涩的嘴角 我的寂寞谁知道 我害怕 用真心面对这世界 只好越来越沉默
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2025-5-12 07:05 , Processed in 0.429361 second(s), 50 queries .

回顶部