QQ登录

只需要一步,快速开始

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

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

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

17

主题

1

听众

109

积分

升级  4.5%

该用户从未签到

跳转到指定楼层
1#
发表于 2004-6-6 19:01 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
<>C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。; N+ j( w7 t* P; b2 g
1.书写标识符时,忽略了大小写字母的区别。5 ]4 G' A1 H# H
main()6 e3 y2 h7 l7 Y
{6 B; u* q) c& D$ U; d& b' p
int a=5;1 t; j) ~% }2 [% F* ]* L) C5 e
printf("%d",A);1 R9 G! `% F3 i) F/ ^5 U- i
}0 V% [9 i0 L. f' d+ {
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
/ y0 H0 ?1 z# d0 f5 d6 U# K: Y. ^2.忽略了变量的类型,进行了不合法的运算。
1 q& C2 o% u" w5 ^- i+ T: bmain()
8 T/ X$ I7 b9 \) Y: ^% A{' e5 g" J7 k9 P; P/ e" B# \
float a,b;0 n' ]- G; ?" k4 {" v
printf("%d",a%b);( U! d# P6 V6 v+ P, k
}
8 p1 V' R5 W7 `8 O3 d$ X7 H%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。5 T7 c( v9 W. W+ v$ W4 w/ t( S
3.将字符常量与字符串常量混淆。; f% X9 P" S2 h2 o2 l8 u& Y! C8 n
char c;
2 c, L: X2 h* I& n9 jc="a";# ~- Z0 Z: P1 ~: \( c
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。
6 R& {; V. k0 V+ |8 ^6 m4.忽略了“=”与“==”的区别。* Y5 I. b6 I4 \& T
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
9 x9 \8 a: b$ s+ n0 Tif (a=3) then …1 X, h$ @* g) [
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
+ b8 Q: h7 X/ sif (a==3) a=b;
" Y2 K7 Z, H. B# O& S前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
* f/ y0 o+ ~0 Q' d! g3 p+ W, A5.忘记加分号。- p* W  U- q7 B; V+ m
分号是C语句中不可缺少的一部分,语句末尾必须有分号。
& C/ }& E; s+ t$ za=1
9 E* u. K4 t( q5 j  bb=2: a) g$ k: d7 Y: \# M- h
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
7 A  M+ U7 O% K1 d7 _; w4 w- ?{ z=x+y;
" A7 ^5 R3 J7 a# n/ w3 Qt=z/100;) E' N/ w, q8 r0 i& Z' [
printf("%f",t);; b7 a! v9 b  {
}9 E5 g. G0 W5 t. a, c& k
对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。2 i/ ]( J, h% s/ O" U8 L
6.多加分号。
* l3 O* J4 q' @, S对于一个复合语句,如:. R5 d, t7 ?5 }% M' h  `6 y
{ z=x+y;
* s! i  x. a* H# X: p( Dt=z/100;
. u8 [' |9 I: O' E( Vprintf("%f",t);
' N6 ^" e- Y' a  ^9 A6 B};" e1 L! Z7 ?4 J' m" v# f# z
复合语句的花括号后不应再加分号,否则将会画蛇添足。
, e, b2 i. P  b. x; D又如:
$ I) M9 t4 ]3 B2 z& Y- Z4 Nif (a%3==0);: S5 H2 q! G5 w0 |7 d
I++;% i+ l) x; y' y/ i* b1 B& J
本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
, i+ Y) G$ {( J8 g6 T7 n4 Z再如:% h) y* U! [- }8 l( q# F
for (I=0;I&lt;5;I++);) F, r9 y) d+ i, R6 }
{scanf("%d",&amp;x);- L# {6 v' I/ d* r: d& @
printf("%d",x);}
( x4 H4 T7 {# Y& l* R! J! m2 C- y本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
( ~0 T& t4 P) m7 Q7.输入变量时忘记加地址运算符“&amp;”。
2 n0 z5 I4 h$ C& b/ K9 Rint a,b;' K1 }2 K& `1 W. S! B1 [
scanf("%d%d",a,b);
$ t- t( e% o( s- a* l这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&amp;a”指a在内存中的地址。! S. @, c, L- m0 l( e7 B' W3 I
8.输入数据的方式与要求不符。①scanf("%d%d",&amp;a,&amp;b);
& t$ _1 L0 L' N输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
5 w+ g- O9 H! t% k; f- o3,4 * ]3 ^6 a: u( q/ Q
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
! m! w, C6 \3 X②scanf("%d,%d",&amp;a,&amp;b);
, V* V2 U& F+ b9 g1 L5 c: [' r& IC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:) s* H: k% @& ?; G  X0 b3 K$ |6 g
3,4
3 T/ R2 F- c- b4 \此时不用逗号而用空格或其它字符是不对的。) E1 V. S, l) O# [0 o
3 4 3:4 + Y: _, |9 k: [# [" \4 t$ H: ^
又如:
# [8 S) F% Y1 G6 [scanf("a=%d,b=%d",&amp;a,&amp;b);
! D8 b- e- K. r" Y* Q" G+ I输入应如以下形式:5 G9 m" G8 M  y
a=3,b=4 7 V8 B" ?  A4 X6 S& X
9.输入字符的格式与要求不一致。
- ]5 Q7 J% [% w' `$ x1 Q2 H在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。  T* }8 v5 @9 P8 g& U5 W/ b
scanf("%c%c%c",&amp;c1,&amp;c2,&amp;c3);
0 X- b- {' ?5 V( L3 h如输入a b c
  X7 J- C% L8 K  \/ e字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。2 d3 z- Z' n3 x% h# J1 s  A
10.输入输出的数据类型与所用格式说明符不一致。
  ^( u( D6 K4 \# ^  [例如,a已定义为整型,b定义为实型
% @4 w& g, Z6 t8 ]+ I/ @6 S# J! _a=3;b=4.5;
1 W8 l6 M* u6 `0 V  C. P' Vprintf("%f%d\n",a,b);* a7 h; E: i  _0 V' H( T+ R
编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
' n/ G% j. }6 B1 g" V3 _7 J9 R11.输入数据时,企图规定精度。
3 q0 b' S4 C3 Z5 escanf("%7.2f",&amp;a);
+ D2 h. ]- S) _; G这样做是不合法的,输入数据时不能规定精度。
% h& g9 K' o3 j9 @12.switch语句中漏写break语句。$ M( Q$ I. }! _3 b0 C& s. C
例如:根据考试成绩的等级打印出百分制数段。
% y" K7 O' \) M- t3 k$ Iswitch(grade)# u$ K$ _) K7 N, I$ \, ^% }  i  d
{ case 'A':printf("85~100\n");: [/ r" }2 N8 U7 _8 f; b
case 'B':printf("70~84\n");' h2 _0 }+ j( }8 _+ ~. x
case 'C':printf("60~69\n");  m' S- \0 X* L; z. G' G! ]; u
case 'D':printf("&lt;60\n");# g& o* C: T" G. n8 I) w3 k
default:printf("error\n");" A- C  B  i8 p+ d- I2 }8 k
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如1 {$ L4 n% i+ N: H/ R7 j
case 'A':printf("85~100\n");break;# ]. {+ t" q% k  e; e( @
13.忽视了while和do-while语句在细节上的区别。) q3 M0 i* r, ?
(1)main()
1 n! k" l+ v  k/ A  Q4 r{int a=0,I;! Y) f6 W5 M5 E( ^' O. J% U
scanf("%d",&amp;I);
5 t  _8 L  z5 M! U/ \6 `' jwhile(I&lt;=10)7 N) M2 l# n5 V2 }/ o" J
{a=a+I;
0 Q& ~, ~% u# a8 q% XI++;. c" n  w2 K: n  K& p+ w8 G
}
" i& U" }! I( ~printf("%d",a);
5 ~6 G' C; [" Z' D+ J" M7 I$ o  k}
% t2 K, ~) Q+ M(2)main()% W! t* p& Z( Y2 T: H5 M
{int a=0,I;" i& e& u( W# A4 g; o2 T  }* K6 U. p8 m+ l
scanf("%d",&amp;I);
/ l$ `, R3 v2 mdo
& b! s/ o9 }3 H5 V' I{a=a+I;
6 k9 e8 E% y) I8 D- M3 k# ?+ UI++;. O8 x. V% k  i, P9 d  ^
}while(I&lt;=10);
4 y6 g" H( \, C, Cprintf("%d",a);
, k4 p5 V, ~' N( m2 b) j/ D}
/ f+ j: t; M( x5 v可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I&gt;10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
) h7 _- S$ F: H0 X2 ]1 v! ^+ m14.定义数组时误用变量。
. C4 k3 B  M* rint n;0 z9 v* g$ g* Z4 [% N7 c) m
scanf("%d",&amp;n);( r. l" g" _/ K" }3 U
int a[n];" D" J- s' I" D) X! z
数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
  X7 X8 v, O' s- _5 w15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。$ Q) z- b- J' v3 \' k
main()
. `, e2 [6 Y! k+ F$ M( o{static int a[10]={1,2,3,4,5,6,7,8,9,10};+ |3 K4 _8 Y  S
printf("%d",a[10]);6 N+ _# \7 V# D" Q7 D5 [& G
}7 a: E5 P4 |  Y% T& _
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
( H5 y' \0 d( @1 `4 E$ u* Q- b0 N16.初始化数组时,未使用静态存储。) g% B1 A( ], o; t6 j
int a[3]={0,1,2};
) ~) Q& r! w5 }1 Q) s* N2 v8 N这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:/ ^! A) z) W5 X+ b
static int a[3]={0,1,2};; c7 [# T6 @8 O; N( E; o- N! r1 [6 S
17.在不应加地址运算符&amp;的位置加了地址运算符。0 I/ }( e' ?; w3 t; x
scanf("%s",&amp;str);
+ ?$ d5 F! L8 N4 GC语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&amp;。应改为:, ?/ o& E! z7 u( V7 G7 N
scanf("%s",str);, v0 o; H! E  F4 K* i) c
18.同时定义了形参和函数中的局部变量。$ P  A: S' \4 z+ U+ w6 O' z0 H
int max(x,y)
. `: |) K6 B1 r8 u( H& uint x,y,z;
) q! M. o/ Z; e! H{z=x&gt;y?x:y;
7 v4 ]; h9 ~9 i. O- f1 wreturn(z);
/ q' K* k( @0 T2 [/ [) X}' L/ W# f( i  `( K
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
- a- H: d, y/ l' T7 V0 v/ Uint max(x,y)0 D4 a- Z& X( L' b9 ?1 D
int x,y;
$ p+ c' G1 n+ m6 y+ p0 r{int z;8 |7 z0 Y7 ^0 j( c% n
z=x&gt;y?x:y;% Z+ T9 V5 z* w% D
return(z);
# Y2 b6 \  t. }# L}</P>
0 Y: _, S  t3 V  s1 `<>以上错误中可能有些不符合新版的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, 2026-4-17 07:19 , Processed in 0.426582 second(s), 51 queries .

回顶部