| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 999 人关注过本帖, 1 人收藏
标题:[讨论]FAQ新增条目建议 C语言常见错误汇编
只看楼主 加入收藏
sunyuantz
Rank: 1
等 级:新手上路
威 望:1
帖 子:407
专家分:0
注 册:2006-3-20
收藏(1)
 问题点数:0 回复次数:4 
[讨论]FAQ新增条目建议 C语言常见错误汇编

我以前的帖子,觉得有点用就想加进FAQ了
c语言的最大特点是:功能强、使用方便灵活。c编译的程序对语法检查并不象其他高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序调试带来了许多不便,尤其对初学c语言的人来说,经常会出一些连自己都不知道错在哪的错误。这个FAQ就是帮你自检的

1、书写标识符时,忽略了大小写字母的区别。
int main()
{
int a=5;
printf("%d",A);
return 0;
}
编译程序把a和A认为是两个不同的变量,(这是c与VB不一样的地方)而显示出错信息。c认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。


2、忽略了变量的类型,进行了不合法的运算。
main()
{
float a,b;
printf("%d",a%b);
}
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量则不可以进行“求余”运算。


3、忽略了“=”和“==”的区别
许多高级语言中,用“=”符号作为关系运算符“等于”。如BASIC程序中可以写if(a=3) then …… 但c语言中“=”是赋值运算符,“==”是关系运算符,如:
if(a=5) a=b;
if(5==a) a=b;(5写在前面是为了防止出现上面的错误,这样写错编译器会报错)
前者是进行赋值,将3赋给变量a,在判断a的值是真还是假,显然,a的值是5始终为真;而后者表示比较,即如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。(经常在论坛上碰到这类问题,所以请新手在发帖前先检查一下自己是不是因为这个问题导致程序出错,以节约大家的时间。谢谢!)


4、忘记加分号。
分号是c语句的结束符,他不可缺少,当你写了“;”就告诉电脑你这一句结束了,所以语句末尾必须有分号。
a=1 /*缺少了;编译器会报错的*/
b=2 /*缺少了;编译器会报错的*/
编译时,编译程序在“a=1”后面没有发现分号,就把下一行“b=2”也作为上一行语句的一部分,这就会出现语法错误,就需要看上一行(或上一个语句)是否漏掉了分号。
{ k=m+n;
t=k/10;
printf("%f",t);
}
对于复合语句来说,最后一个语句的分号不能忽略(这是和PASCAL不同的)。 (在论坛上也碰到这类问题,所以还是请新手在发帖前先检查一下自己是不是因为这个问题导致程序出错,以节约大家的时间。谢谢!)


5、对于一个复合语句。
如:
{ k=m+n;
t=k/10;
printf("%f",t);
};
复合语句的花括号后不应再加分号,否则将会画蛇添足。
又如:
if(a%3==0);
i++;
本意是如果3整除a,则i加1,但由于if(a%3==0)后多加分号,则if语句到此结束。程序将执行i++语句,不论3是否整除a,i都会自动加1。(以前这是我常犯的错误)
再如:
for(i=0;i<5;i++);
{sacnf("%d",&x);
printf("%d",x);}
本意是先后输入5个数,每输入一个数再将它输出。由于for()后多加了一个分号,使循环体变为空语句,此时只能输入一个数并输出它(这种错误不仔细看是很难发现的,特别是很长的程序中就更难发现了,所以大家在写程序时要小心哦!)


6、输入变量时忘记加地址运算符“&”
int a,b;
scanf("%d%d",a,b);
这是不合法的。scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存的地址。(这个问题本人现在还有时犯,哎好繁啊!)


7、输入数据的方式与要求不符。
(1) scanf("%d%d",&a,&b);输入时,不能用逗号作两个数据之间的分隔符,如下面输入不合法:
3,4
输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
(2)scanf("%d,%d",&a,&b);
C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
3,4
此时不用逗号而用空格或其它字符是不对的。
3 4 3:4
又如:
scanf("a=%d,b=%d",&a,&b);
输入应如以下形式:
a=3,b=4


8、将字符常量与字符串常量混淆。
char c;
c="a"
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。c规定以“\0”作字符串常量的结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:'a'和‘\0’,而把它赋给一个字符变量是不行的。


9、输入字符的格式与要求不一致。
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
scanf("%c%c%c",&c1,&c2,&c3);
如输入a b c
字符' a'送给c1,字符' '送给c2,字符' b'送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。


10、输入输出的数据类型与所用格式说明符不一致。
例如:a已定义为整型,b定义为实型
int a=3;
float b=4.5;
printf("%f%d\n"a,b);
编译时不会给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。


11、输入数据时企图规定精度。
(个人认为这不能不说这是一个高级错误,为什么呢?因为犯这种错误的人字符输出这一节应该学的很好,但他看书一定没仔细看就上机操作了。)
scanf("%7.2f",&a);
这样做是不合法的,输入数据时不能规定精度。

12、switch语句中漏写break语句。
例如:根据考试成绩的登记打印出百分制数段。
switch(grade)
{case 'A':printf("85~100\n");
case 'B':printf("70~84\n");
case 'C':printf("60~69\n");
case 'D':printf("<60\n");
default:printf("error\n");
}
由于漏写了break语句,case只起标号的作用,而不起判断的作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。
例如
case 'A':printf("85~100\n");break;


13、忽视了while和do-while语句在细节上的区别。
(1) main()
{int a=0,i;
scanf("%d",&i);
while(i<=10)
{a=a+i;
i++;
}
printf("%d");
}
(2)main()
{int a=0,i;
scanf("%d",&i);
do
{a=a+i;
i++;
}while(i<=10);
printf("%d");
}
可以看到,当输入i值小于或等于10时,二者得到的结果相同。而当i>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。

14、定义数组时误用变量。
int n;
scanf("%d",&n);
int a[n];
(刚开始学数组也干过这样的傻事,觉得这样方便,哎结果……,这也是数组最大的问题不能动态定义。c++里可以用向量来代替数组,不知道c里有什么高招,哪位大人教教偶!)数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即c不允许对数组进行动态定义。(但下面这种形式是可以的!)
#define N 5
int a[N];/*因为,N是符号常量*/


15、在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
main()
{static int a[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d",a[10]);
}
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的,属于数组越界,系统并不提示。(处理数组时一定要考虑到会不会越界,这种错误一般新手都会犯,偶也犯过。希望大家警觉!)


16、初始化数组时,未使用静态存储。
int a[3]={0,1,2};
这样初始化数组是不对的。C语言规定只有静态存储(static)数组和外部存储(exterm)数组才能初始化。应该为:
static int a[3]={0,1,2};


17、在不应加地址运算符&的位置加了地址运算符。
char str[10];
……
scanf("%s",&str);
C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应该为:
scanf("%s",str);


18、同时定义了形参和函数中的局部变量。
int max(x,y)
int x,y,z;
{z=x>y?x:y;
return(z);
}
形参应该在函数体外定义,而局部变量应该在函数体内定义。应该为:
int max(x,y)
int x,y;
{int z;
z=x>y?x:y;
return(z);
}


19、对应该有花括弧的复合语句,忘记加花括弧。
如:
s=0;
i=1;
while(i<=100)
s+=i;
i++;
本意是实现1+2+……100但上面的语句只是重复了s+i的操作,而且循环永不终止(死循环)。因为作为循环记数的i始终没变。如果改成:
s=0;
i=1;
while(i<=100)
{s+=i;
i++;
}
就能实现本意了。


20、应用数组元素时误用了圆括弧。
如:
main()
{int i,a[5];
for(i=0;i<5;i++)
scanf("%d",&a(i));
}
C语言中对数组的定义或引用数组元素时必须用方括弧。


21、函数的实参和形参类型或数量不一致。
如:
main()
{int a=5,b=8,c;
c=fun(a,b);

}
fun(float x)
{

}
实参a、b定义为整型,形参x为实型。并且实参有两个而形参只有一个。这种类型错误在一些习题集上的改错题中经常出现。

[此贴子已经被作者于2007-9-21 22:27:06编辑过]

搜索更多相关主题的帖子: FAQ C语言 条目 汇编 c语言 
2007-09-21 22:18
白年不亮
Rank: 1
等 级:新手上路
帖 子:48
专家分:0
注 册:2007-9-17
收藏
得分:0 
将main函数改成下面的形式:
int main()
{
// some code

return 0;
}

==========================================================================
3、忽略了“=”和“==”的区别
建议把if(a==5) a=b;写成这样:if(5==a) a=b;防止少写一个=


[glow=255,red,2] 天凉了,穿上马甲暖和多了。[/glow]
2007-09-21 22:21
死了都要C
Rank: 4
来 自:四川成都
等 级:贵宾
威 望:13
帖 子:1582
专家分:116
注 册:2006-12-7
收藏
得分:0 

我加一个: 把循环条件也当作是语句然后就直接在后面加分号了``
例: while(i<100);
++i;
for(i=0;i<99;i++);
a[i]+=a[i+1];





女施主``我给你``送茶来了```师太``你就从了老衲吧``
代码本天成~~~妙头偶得之```
2007-09-21 22:39
sunyuantz
Rank: 1
等 级:新手上路
威 望:1
帖 子:407
专家分:0
注 册:2006-3-20
收藏
得分:0 
知道了,我组织一下,晚上来改!

我不是名人,所以不要签名。等哪天我成名人了......你都认识我了还要签名干嘛!
2007-09-22 18:45
sunyuantz
Rank: 1
等 级:新手上路
威 望:1
帖 子:407
专家分:0
注 册:2006-3-20
收藏
得分:0 
又补了一条,内容如下:
循环语句后面误加分号
先看例子
#include<stdio.h>
int main()
{
int nI=3;
while(nI>=0);
printf("i=%d\n",nI--);
getch();
return 0;
}
结果是什么呢?
很多新手认为应该显示如下结果
i=3
i=2
i=1
i=0
但实际结果是程序陷入死循环,为什么会这样呢?因为在while(nI>=0);中多了一个分号使得下一句的prinf函数由在循环里变成了在循环 外外面。在书写循环语句时分号是不能乱加的。一般DO-while语句会在最后的while处加一个分号,其余的循环除了特殊需要,一般不用在判定条件后 跟分号。

我不是名人,所以不要签名。等哪天我成名人了......你都认识我了还要签名干嘛!
2007-09-23 17:09
快速回复:[讨论]FAQ新增条目建议 C语言常见错误汇编
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020758 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved