QQ登录

只需要一步,快速开始

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

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

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

17

主题

1

听众

109

积分

升级  4.5%

该用户从未签到

跳转到指定楼层
1#
发表于 2004-6-6 19:01 |只看该作者 |正序浏览
|招呼Ta 关注Ta
<>C语言的最大特点是:功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。7 q* K$ k0 Y0 H: t5 K: A9 @
1.书写标识符时,忽略了大小写字母的区别。( P9 B+ @# }/ y& h' `
main()5 E2 m* d+ b$ W5 `* G
{
, }+ P" Z" t! V4 yint a=5;- b: F! U1 r) S3 Y- X7 I: D
printf("%d",A);
4 {; {' m! \2 [& G. ^) x' `6 D}
) K7 [$ l8 X* M/ y编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。9 ^/ h& r! P& S: M! R( Z) |
2.忽略了变量的类型,进行了不合法的运算。) ~, ~( N$ B9 N7 P6 a4 K& B
main()2 ~* R# l" x- g4 C0 T; @) }
{
1 \# l! }; b! V! ufloat a,b;1 m; ]1 S) U% |- ]/ A, m
printf("%d",a%b);
9 l8 M  e6 v; e7 W* |4 e}( r0 I8 z, E- \. v/ v4 O
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。
- K) g3 I- {/ k! k; P$ [3.将字符常量与字符串常量混淆。, Z" V5 k' N: x4 w# k; R
char c;5 Y8 _) @1 F5 L
c="a";
1 {, {$ K# {- m在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a'和‘\',而把它赋给一个字符变量是不行的。& \/ J* Y" v8 X% ]% ^0 z& o: g
4.忽略了“=”与“==”的区别。
$ J7 M) Y# t6 P+ _) R在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写
. {: f3 T4 T/ S; k; X3 Q4 Eif (a=3) then …' l/ L: v6 N& C' ?# N
但C语言中,“=”是赋值运算符,“==”是关系运算符。如:2 n8 q5 `, Q/ H8 a; W6 d% q
if (a==3) a=b;2 B7 m+ f3 b* o& R
前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
, W0 |" S$ Y$ m% _. c5.忘记加分号。! ]# n9 D% q# V: Z4 l0 V# S
分号是C语句中不可缺少的一部分,语句末尾必须有分号。% s& i5 h& z+ O( O2 d& m0 _# x
a=1
3 F# q! r% o8 f! R: Ub=2& |9 j; i# C2 a. f- n3 e
编译时,编译程序在“a=1”后面没发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误。改错时,有时在被指出有错的一行中未发现错误,就需要看一下上一行是否漏掉了分号。
) B& B! Z* X% y4 p{ z=x+y;( @; M3 ^0 |5 B/ \& L" s* b
t=z/100;  W% \9 {# @0 _8 H. G8 ~
printf("%f",t);3 K& X: t; q% v* w
}
. N+ o8 K" T6 O/ m对于复合语句来说,最后一个语句中最后的分号不能忽略不写(这是和PASCAL不同的)。2 V  ]* W/ J. U: }( Q
6.多加分号。. }4 v% x( v8 C' N& Y% {% e0 ]
对于一个复合语句,如:; O/ t9 g5 s# R5 ^7 O
{ z=x+y;) E" H, g$ f$ v" P. u7 k
t=z/100;$ E3 e- I4 c4 [* D0 a
printf("%f",t);; }% e! c  P$ F1 I& J; N& h
};
4 O/ A8 c+ d! H6 L3 F复合语句的花括号后不应再加分号,否则将会画蛇添足。
9 x' b- p. @7 I; D' I) r/ q又如:
: F0 G) t; E4 R) }6 uif (a%3==0);  c$ g$ W) M3 h
I++;
5 j: O6 N) O  M' t" Z本是如果3整除a,则I加1。但由于if (a%3==0)后多加了分号,则if语句到此结束,程序将执行I++语句,不论3是否整除a,I都将自动加1。
+ R/ D  f0 @1 q1 U7 q+ Q8 H再如:- \$ f$ D: l% j, P1 f/ a. U
for (I=0;I&lt;5;I++);0 }8 z$ I% T& }$ u8 {
{scanf("%d",&amp;x);
! h. [& N( S4 \8 ?' E5 }, qprintf("%d",x);}
8 C# B7 y2 k/ q9 V; ?5 N$ v本意是先后输入5个数,每输入一个数后再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它。
( \& \& ?3 O7 q  L# ?% T2 J5 ^. T7.输入变量时忘记加地址运算符“&amp;”。
% ]' j' e2 ]9 i  A! Wint a,b;
8 y% R! f7 }- y# l3 `; [# |6 wscanf("%d%d",a,b);1 |1 K4 A8 W; i3 C  W/ w" _
这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&amp;a”指a在内存中的地址。
1 X9 p5 T; Z0 @2 ?# l8.输入数据的方式与要求不符。①scanf("%d%d",&amp;a,&amp;b);3 d6 ]  x6 L$ q" t. {) Z, l1 M
输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:
* v5 D  z' t2 m$ |5 z4 ^3,4 1 P, s) H9 R) [" R) i
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。6 d) B3 u2 I. v: _' C* p
②scanf("%d,%d",&amp;a,&amp;b);
3 X* a# g& S2 KC规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
+ T, o+ N" _2 W. t3,4
3 [9 o; E% m9 c" {此时不用逗号而用空格或其它字符是不对的。+ ^: j$ S5 ^: b" l& A
3 4 3:4
& {2 d: Q6 y9 ^# Z7 n3 G" D- z又如:
$ F0 ~) a: t' k5 l8 ]8 Hscanf("a=%d,b=%d",&amp;a,&amp;b);  m, o8 V( B5 A& Q; m
输入应如以下形式:
! G9 @8 f) ]2 u/ C. p* C; La=3,b=4
/ }/ O8 {& @. h" Q. T* {9.输入字符的格式与要求不一致。
0 M; H# a8 v; p5 F, b' O0 _- N+ J- a在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
0 g- k: x) Q- R  w8 zscanf("%c%c%c",&amp;c1,&amp;c2,&amp;c3);
% P( u# {. Q6 j5 L如输入a b c " r6 O8 |8 B, k* s% K/ \9 [3 }2 k% g
字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
9 Y0 W- P  r) h0 z- w! |10.输入输出的数据类型与所用格式说明符不一致。, i! ]/ r9 n% T, ~' g
例如,a已定义为整型,b定义为实型
4 F/ Z" J; L/ t- Q" {; D9 r/ k2 S1 [  ~a=3;b=4.5;
8 M* Z2 n& N4 W! D* Cprintf("%f%d\n",a,b);
' d5 ^) k+ }, P1 I* S2 G2 I编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
# T, D+ j% J% t8 o" P3 D1 v11.输入数据时,企图规定精度。
* J: }: @; [) \1 F& U0 kscanf("%7.2f",&amp;a);3 E2 ]3 }6 Y' K
这样做是不合法的,输入数据时不能规定精度。
0 `+ ]2 K6 O7 x12.switch语句中漏写break语句。7 l0 E: \; Z% j
例如:根据考试成绩的等级打印出百分制数段。
% b" s/ ?7 \& u" Yswitch(grade): U( o9 _# D9 V
{ case 'A':printf("85~100\n");
! G1 _6 `# w1 c. _case 'B':printf("70~84\n");
5 ]0 _' a- D" G9 v0 {1 E( Rcase 'C':printf("60~69\n");; m7 `5 L8 I8 T: G; _
case 'D':printf("&lt;60\n");, ^3 P# E/ o: a- c
default:printf("error\n");
% t" D. p% V. Y' D, I3 L& ?" j由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如
( E. b8 K& @, h6 v2 ccase 'A':printf("85~100\n");break;
4 q& `1 p% j8 q3 y5 n13.忽视了while和do-while语句在细节上的区别。4 n+ ^- @. X/ G- @
(1)main()4 P2 i/ p; E2 F
{int a=0,I;! q6 {% O% Z0 ]
scanf("%d",&amp;I);* V# q7 S. q, S# c
while(I&lt;=10); Z2 Z4 v2 y# A* |! x' s- }( m
{a=a+I;
8 B! B1 ~7 u8 y* t4 [, b, OI++;
: _! ^2 B/ r# f3 l' u* [3 f+ C) Y3 k}
) o& {- N4 D% I! N) ]; nprintf("%d",a);7 y: `1 ^; b7 D7 R
}
7 D/ u- t6 A' D% |' e( {(2)main()
# H  @( y' A% o6 I/ ?7 L{int a=0,I;
% I9 y8 [% W$ P0 cscanf("%d",&amp;I);0 q: \( s0 R3 `! L0 Y
do
  k0 N! D- ~  R  b0 [- d+ a{a=a+I;  W8 D3 d/ M( F# p# B/ H
I++;& l0 d) Z+ e/ M  j3 T  K2 D
}while(I&lt;=10);
" A: [7 [; p5 m, i" v6 Z: f. oprintf("%d",a);2 Z8 k3 W( x  @; v) f3 C
}9 \, }/ W) r- K7 I- M
可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I&gt;10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。
0 P/ D5 }7 e/ D$ c14.定义数组时误用变量。+ [. y! _4 t! N; l% s$ ]
int n;
0 k- S& o) F! J/ T7 \1 i2 Iscanf("%d",&amp;n);
6 Y! O( W. W) L( d! E' z  Z* zint a[n];$ @3 j. q2 G  C/ W" d- t
数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。. I* L: M9 Z" @2 ?2 @
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。( q' w. l/ R0 @2 O# P
main()8 d% t6 ~! Z# V. J. G; D
{static int a[10]={1,2,3,4,5,6,7,8,9,10};9 v9 U& J' N% V  p5 F( n- ^  E
printf("%d",a[10]);
9 r' e' c+ Z/ F- r1 o& P}5 v& e4 o3 V5 Z' Q2 V; T
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。% ?  d, @4 d4 H
16.初始化数组时,未使用静态存储。
6 D/ y- ^3 g7 m, u8 Uint a[3]={0,1,2};
, ?& |. c* |2 B这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应改为:) p/ j# ?! h$ k+ t0 {5 b
static int a[3]={0,1,2};
) }9 v" j& \& d# n17.在不应加地址运算符&amp;的位置加了地址运算符。
0 Q3 t4 s4 _2 P3 g5 D0 z( V3 F4 ~& sscanf("%s",&amp;str);
! p" ]8 X4 |( v& H7 o1 J: {C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&amp;。应改为:: |2 ^$ [( H) j/ h2 l
scanf("%s",str);$ c: o6 g' C3 `8 q) A4 k8 |
18.同时定义了形参和函数中的局部变量。1 v" o6 f5 B0 I$ U. m% V
int max(x,y)' j( n+ s% Q8 Q1 Z" x( X. W! A
int x,y,z;1 p/ Y3 O) _, k' c$ z  J' Q* W; N# r
{z=x&gt;y?x:y;
  Q/ }  p- y& A0 E! J! \$ t- _& Jreturn(z);
% ]" ~: x1 o8 o/ Z  m: T* \! i& R' Z}
! t7 w7 u8 g9 `/ ~# Y+ I形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
8 v: h+ k  Z& tint max(x,y)' n3 G7 J. F& l: T8 U! j% T6 ?
int x,y;- m3 O0 |" c# r- T3 U7 ^
{int z;- Y/ L) L& {0 l. v. f- B7 N
z=x&gt;y?x:y;7 B& q! _1 }4 l$ e- z
return(z);
  a1 H# Q8 E% |}</P>
9 {5 L2 f4 r  ]2 e8 o<>以上错误中可能有些不符合新版的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-9-3 02:20 , Processed in 0.600395 second(s), 57 queries .

回顶部