QQ登录

只需要一步,快速开始

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

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

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

17

主题

1

听众

109

积分

升级  4.5%

该用户从未签到

跳转到指定楼层
1#
发表于 2004-6-6 19:01 |只看该作者 |正序浏览
|招呼Ta 关注Ta
<>C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。, ?3 T. d6 P$ K  C# Y
1.书写标识符时,忽略了大小写字母的区别。
' ~9 G$ F& x8 \' q1 I5 ]0 lmain()# \9 e' G. z3 e% s
{
% h3 `6 e0 y1 D9 Iint a=5;
& e* u# N2 [& Yprintf("%d",A);
7 C9 N( C. @% w4 O# m2 u$ m. r}/ X+ }  B- Y3 m
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。; u. z, o2 D9 Z9 }- Y; L
2.忽略了变量的类型,进行了不合法的运算。
8 m: j/ E2 ?, ~main()
1 Y5 W3 G( l3 A6 r{( ]( u& q' D, @1 V; n1 A6 x7 X
float a,b;
' i" U# T1 T) b. f7 i4 Pprintf("%d",a%b);" `* ?0 [# i( j
}
. E8 |* A' B3 \, d%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。9 |' z% I! [/ {& G+ R2 o& C
3.将字符常量与字符串常量混淆。
, {& ?4 I! p6 |, ?' A3 Ichar c;
9 j) r+ G  P) k3 ic="a";
% N  s$ ~5 E* u% w# o. |! b2 U在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。
1 B4 x/ n# ^# |. U$ p( X4.忽略了“=”与“==”的区别。
. V! L- v0 _- {  f! P3 }2 g4 g在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
4 A5 E! z9 g2 J  c, I% e: m' dif (a=3) then …" v; E+ k3 ?3 z% q2 `8 j6 U
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:
6 U2 B4 {- m9 T9 h- }. Bif (a==3) a=b;
$ Y" K' K9 Y8 x4 x& R6 l% D* {前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。% q/ Z: f5 p9 Y; h! J0 f
5.忘记加分号。- j. g, i( [0 _1 d% ^" I- o
分号是C语句中不可缺少的一部分,语句末尾必须有分号。" R+ f( e5 a" P& m) `0 K4 u
a=1
$ V( z) q9 J/ M# G+ N/ Fb=25 q1 \  a' j! p/ a3 g
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
! M+ b, r- O& `{ z=x+y;
2 {5 a6 S+ S# w) y& St=z/100;
; Q$ s( f% l. a2 j9 V$ R! G7 Q& Yprintf("%f",t);
: t# \1 F& S( c2 Q) B}
  \2 {. K4 A$ {6 P% M0 |! `5 ?对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。
+ z" P% N" X/ l" y# \- q1 E6.多加分号。+ U7 j+ x$ `9 K
对于一个复合语句,如:, C) ^* b& I; Z- \9 L3 `! W
{ z=x+y;
; F& z4 k6 J: r2 zt=z/100;/ S5 s7 E  X/ c4 _  O% _5 f
printf("%f",t);
9 U2 F1 z1 M/ |& Q3 t};
1 }  ?2 I$ b) _/ {1 I9 I复合语句的花括号后不应再加分号,否则将会画蛇添足。
% V2 D8 D% F& f- Q又如:
4 F" o( a0 _. t& v. @" b* `* `0 oif (a%3==0);
  p# {2 ^! e: C  g. P+ Q& l& @I++;
) b5 f4 u& d, ^  Z2 j, K本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。! n; L, I- k. x
再如:
# x$ }4 P  {5 O9 [+ l0 F0 C0 z3 vfor (I=0;I&lt;5;I++);
: {" x, }" O2 E; r{scanf("%d",&amp;x);
0 j) m' B  U& U. |6 j! B5 @printf("%d",x);}
* X* k: r- ]8 r, ?- F本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。: _' V* p$ U7 M) ^7 Q. a
7.输入变量时忘记加地址运算符“&amp;”。
8 W6 R. x) I  O8 R7 w- f% p+ E4 h7 Fint a,b;8 x" d' X% N, x+ O" M5 V$ t
scanf("%d%d",a,b);
) b$ B* l- S, m1 D6 T" C这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&amp;a”指a在内存中的地址。
4 |/ X0 K4 Y7 _8 Y" [8.输入数据的方式与要求不符。①scanf("%d%d",&amp;a,&amp;b);+ `8 k0 K: ?" f, P% `
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
* b+ ~3 l! H/ b0 \3,4 2 J/ T& g( G4 ^2 E. Z, `7 b
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
$ i% Y5 E- R$ w9 x% a2 n②scanf("%d,%d",&amp;a,&amp;b);
0 R1 A. Q, D: X9 VC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:: u. e: e& `; R5 L* A
3,4
9 w! E. k8 s& i* K+ L  Z此时不用逗号而用空格或其它字符是不对的。& _/ T* H& q& q2 ]: B# ~
3 4 3:4
. C4 i& Q" ~! R$ x又如:
" n1 Q( g3 |; Escanf("a=%d,b=%d",&amp;a,&amp;b);2 U0 m, t7 g4 l. Y( \/ e# D
输入应如以下形式:
& g6 W. Q, T9 _9 `a=3,b=4
; c- i( G& i' n9.输入字符的格式与要求不一致。# }; i: |" T( h3 l+ ^( l/ @
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
! U- X; h( W$ G) P  e* j* B- _) `" F* Fscanf("%c%c%c",&amp;c1,&amp;c2,&amp;c3);7 A& `# ], d, z
如输入a b c
1 y, b" r) g" ^字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。0 W* x4 `  w2 H$ d$ U  M
10.输入输出的数据类型与所用格式说明符不一致。% ~' r) M' h8 ]3 {7 W+ f/ Q
例如,a已定义为整型,b定义为实型% K6 `3 }4 D# a9 v* N( G
a=3;b=4.5;8 X+ i. s: F. g! W" Z9 ]- \; {
printf("%f%d\n",a,b);
6 |6 ]7 }# g  a$ W+ G  G" ^0 `$ r9 s编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。! X  U3 |( D* o: g8 U" u( v* k( K
11.输入数据时,企图规定精度。4 S- l3 X7 _6 Z& t4 s
scanf("%7.2f",&amp;a);: G/ Q$ H( n- Q7 F" P) u
这样做是不合法的,输入数据时不能规定精度。1 E' o/ Y. ]$ }3 c6 s
12.switch语句中漏写break语句。" m1 P+ I' _  L. X- u
例如:根据考试成绩的等级打印出百分制数段。9 x+ x+ L$ v) ~3 h
switch(grade)) q( }2 G2 W* d9 I; H/ b) [
{ case 'A':printf("85~100\n");% W" ~$ L# V: X1 k
case 'B':printf("70~84\n");
7 p, F* k" ]9 acase 'C':printf("60~69\n");
6 `$ ?0 k2 @0 Ecase 'D':printf("&lt;60\n");
/ `1 b/ V& L7 c4 n9 Mdefault:printf("error\n");
7 [; O) |- i0 D# B. c' V9 z由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
2 v# y9 h6 _! |- i0 Zcase 'A':printf("85~100\n");break;) j! A2 \2 ^+ k; a( `! D7 f
13.忽视了while和do-while语句在细节上的区别。8 ^" ]) `8 g9 I9 a/ q: |
(1)main()) K3 `5 {6 g' e# n
{int a=0,I;  ]9 I* K# y8 s
scanf("%d",&amp;I);
1 h( d( e* O' D! bwhile(I&lt;=10)5 [. ^& U, ]4 {' W1 v
{a=a+I;
6 ]  Z8 d' J7 O$ G; mI++;
, i% I6 Q/ \4 M" Y( d}
  Q0 o( ]2 X7 ?! Q( xprintf("%d",a);
5 Z/ T3 M: r1 _}& d, y  |$ x7 ^
(2)main()7 ~2 K, @6 G3 w5 |
{int a=0,I;
# s. E' ?# N# G1 K) @: Q, B$ \" V9 Bscanf("%d",&amp;I);
$ O. j2 M7 ~3 z" hdo
! {! [9 n, p: G+ K, \{a=a+I;
4 \4 L* M0 s1 [2 oI++;! E% Z" g/ p" R2 @2 C* s4 Z" G! D& F
}while(I&lt;=10);, M5 _1 R1 i: z) A& z. R: |
printf("%d",a);" ~3 r; e: u. q: o5 ?, Y
}$ M3 p) q) b8 n! @
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I&gt;10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
0 A1 Y2 S; \9 q+ q# w% ^" j4 U0 v14.定义数组时误用变量。5 e6 R0 {9 M( ?* w9 j4 L. Q$ l4 [
int n;
2 m) @+ d8 b$ |- F- _! B% n, vscanf("%d",&amp;n);
+ h+ W7 J9 X7 J0 r6 u8 Z2 Sint a[n];
0 `3 @3 h3 {) V; a  H- X" T& E1 f/ X数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。/ O  p( @1 n- ]$ |# A* s
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
% V- u9 F7 m1 Z, w' L, rmain(); U! u/ B$ m9 F. g$ F( l
{static int a[10]={1,2,3,4,5,6,7,8,9,10};& r8 y" d! ?$ t9 B; W
printf("%d",a[10]);: C! m) x# }) X/ x+ t9 T
}" K+ b0 R( P  Z2 h; l: s" `; e# c4 d3 _  R
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
# d* O- |% u7 F# `7 {6 k# G. C- B16.初始化数组时,未使用静态存储。
. \4 @4 E8 i4 B' S$ C: Mint a[3]={0,1,2};
( k; \# I- I' q" P( D; z这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:
' c+ l, U; j- O8 n& l5 T8 @static int a[3]={0,1,2};
2 [% x1 O0 F) |4 Z2 a17.在不应加地址运算符&amp;的位置加了地址运算符。
. Y& \1 X5 v( h4 d9 p, u8 ~scanf("%s",&amp;str);# U/ X- `2 }* j( U2 z7 ~7 b1 i3 L
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&amp;。应改为:3 ]. G* v' g0 V6 b' p' ]
scanf("%s",str);- ~8 T5 ^  O0 ^( N- ^" q% z
18.同时定义了形参和函数中的局部变量。
3 `5 a/ l+ H* s0 f; zint max(x,y)! F+ N2 [7 j& R* ]
int x,y,z;! b" k6 ]2 A$ l
{z=x&gt;y?x:y;4 k0 P6 m" H# v) e# l8 N( K1 g
return(z);* s8 N1 b  d% p$ k# N, c
}' q) V4 @& W" ^/ ^* y
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:" M' U" C7 E# [' L' J9 B
int max(x,y)
8 n& L) n+ {% N" I# O6 @8 }7 m" sint x,y;8 C9 m; d9 Z2 ]( u* C
{int z;9 U* G6 a9 j1 \) S3 W
z=x&gt;y?x:y;
; x) A. S- G5 c5 W* j) o# ~: E- Ereturn(z);. G$ \3 V9 x$ `) b  Q
}</P>
* N; R$ _- t, G6 F1 X3 J% C  O5 k<>以上错误中可能有些不符合新版的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-7-19 12:16 , Processed in 1.269657 second(s), 51 queries .

回顶部