版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 要真正学好要真正学好C、用好、用好C并不容易,并不容易,“灵活灵活”固然是固然是好事,但也使人难以掌握,尤其是初学者往往出好事,但也使人难以掌握,尤其是初学者往往出了错还不知怎么回事。了错还不知怎么回事。C编译程序对语法的检查编译程序对语法的检查不如其他高级语言那样严格不如其他高级语言那样严格(这是为了给程序人员这是为了给程序人员留下留下“灵活灵活”的余地的余地)。因此,往往要由程序设计。因此,往往要由程序设计者自己设法保证程序的正确性。调试一个者自己设法保证程序的正确性。调试一个C程序程序要比调试一个要比调试一个PASCAL或或FORTRAN程序更困难程序更困难一些。需要不断积累经验,提高
2、程序设计和调试一些。需要不断积累经验,提高程序设计和调试程序的水平。程序的水平。 下面是常见的一些错误:下面是常见的一些错误:(1) 忘记定义变量。如:忘记定义变量。如:main()x=3; y=6; printf(%dn,x+y); C要求对程序中用到的每一个变量都必须定义其要求对程序中用到的每一个变量都必须定义其类型,上面程序中没有对类型,上面程序中没有对x、y进行定义。应在函进行定义。应在函数体的开头加数体的开头加intx,y;这是学过这是学过BASIC和和FORTRAN语言的读者写语言的读者写C程序时常见的一个错误。程序时常见的一个错误。在在BASIC语言中,可以不必先定义变量类型就可
3、语言中,可以不必先定义变量类型就可直接使用。在直接使用。在FORTRAN中,未经定义类型的变中,未经定义类型的变量按隐含的量按隐含的I-N规则决定其类型,而规则决定其类型,而C语言则要求语言则要求对用到的每一个变量都要在本函数中定义对用到的每一个变量都要在本函数中定义(除非已除非已定义为外部变量定义为外部变量)。(2) 输入输出的数据的类型与所用格式说明符不一致。输入输出的数据的类型与所用格式说明符不一致。例如,若例如,若a已定义为整型,已定义为整型,b已定义为实型。已定义为实型。a=3;b=45;printf(%f%dn,a,b);编译时不给出出错信息,但运行结果将与原意不符,编译时不给出出
4、错信息,但运行结果将与原意不符,输出为输出为0.00000016402它们并不是按照赋值的规则进行转换它们并不是按照赋值的规则进行转换(如把如把45转换转换成成4),而是将数据在存储单元中的形式按格式符的,而是将数据在存储单元中的形式按格式符的要求组织输出要求组织输出(如如b占占4个字节,只把最后两个字节中个字节,只把最后两个字节中的数据按的数据按%d,作为整数输出,作为整数输出)。(3) 未注意未注意int型数据的数值范围。型数据的数值范围。在在Turbo C编译系统,对一个编译系统,对一个int整型数据分配两个整型数据分配两个字节。因此一个整数的范围为字节。因此一个整数的范围为-21521
5、5-1,即,即-3276832767。常见这样的程序段:。常见这样的程序段:int num;num=89101;printf(%d,num); 得到的却是得到的却是23565,原因是,原因是89101已超过已超过32767。两。两个字节容纳不下个字节容纳不下89101,则将高位截去。见图,则将高位截去。见图16.1。即将超过低即将超过低16位的数截去。即将位的数截去。即将89101减去减去216(即即16位二进制所形成的模位二进制所形成的模)。89101-65536=23565。有时还会出现负数。例如有时还会出现负数。例如num=196607; 输出得输出得-1。因为。因为196607的二进制
6、形式为的二进制形式为00 00 00 00 00 00 00 1011 11 11 11 11 11 11 11去掉高位去掉高位10,低,低16位的值是位的值是-1(-1的补码是:的补码是:1111111111111111)。对于超过整个范围的数,要用对于超过整个范围的数,要用long型,即改为型,即改为long intnum; num=89101;printf(%ld,num);请注意,如果只定义请注意,如果只定义num为为long型,而在输出时仍用型,而在输出时仍用“%d”说明符,仍会出现以上错误。说明符,仍会出现以上错误。(4) 输入变量时忘记使用地址符。如:输入变量时忘记使用地址符。如
7、:scanf(%d%d,a,b);这是许多初学者刚学习这是许多初学者刚学习C语言时一个常见的疏忽,语言时一个常见的疏忽,或者说是习惯性的错误,因为在其他语言中在输入或者说是习惯性的错误,因为在其他语言中在输入时只需写出变量名即可,而时只需写出变量名即可,而C语言要求指明语言要求指明“向哪向哪个地址标识的单元送值个地址标识的单元送值”。应写成。应写成scanf(%d%d,&a,&b);(5) 输入时数据的输入时数据的形式形式与要求不符。与要求不符。用用scanf函数输入数据,应注意如何组织输入函数输入数据,应注意如何组织输入数据。数据。假如有以下假如有以下scanf函数:函数:s
8、canf(%d%d,&a,&b);有人按下面的方法输入数据:有人按下面的方法输入数据:3,4这是错的。数据间应该用空格来分隔。应该用以下方这是错的。数据间应该用空格来分隔。应该用以下方法输入:法输入:3 4(中间有空格)(中间有空格)如果如果scanf函数为函数为scanf(%d,%d,&a,&b);对对scanf函数中格式字符串中除了格式说明符外,函数中格式字符串中除了格式说明符外,对其他字符必须按原样输入。因此,应按以下方法对其他字符必须按原样输入。因此,应按以下方法输入:输入:3,4此时如果用此时如果用“3 4”反而错了。反而错了。(6) 在用在用scan
9、f函数向字符数组输入数据时,在数组函数向字符数组输入数据时,在数组名前面多加了名前面多加了&,例如:,例如:char a20;scanf(“%s”, &a);在对变量输入数据时应当加在对变量输入数据时应当加&,例如,例如&a,但是数组,但是数组名本身已经表示地址,不需要再加名本身已经表示地址,不需要再加&,应当写成:,应当写成:scanf(“%s”, a);(7) 在用在用scanf函数向数值型数组输入数据时,直接函数向数值型数组输入数据时,直接用数组名,例如:用数组名,例如:int a20;scanf(“%d”, a);这是错误的。数值型的数组不能一次
10、性整体输入,这是错误的。数值型的数组不能一次性整体输入,只能一个个元素单独输入,应当写成:只能一个个元素单独输入,应当写成:int a20;int i;for(i=0;i20;i+) scanf(“%d”, &ai);(8) 语句后面漏分号,例如:语句后面漏分号,例如:a=3b=4;(9) 在预处理指令后面加分号,例如:在预处理指令后面加分号,例如:#include ;注意预处理不是语句,是指令,所以不需要分号。注意预处理不是语句,是指令,所以不需要分号。(10) 在不该加分号的地方加分号,例如:在不该加分号的地方加分号,例如:if (ab); printf(“a is larger
11、than bn”);这个写法相当于这个写法相当于if的条件成立时,执行空语句(就的条件成立时,执行空语句(就是那个分号);而无论条件是否成立,是那个分号);而无论条件是否成立,printf都需要都需要执行。显然这不是程序的本意。再例如:执行。显然这不是程序的本意。再例如:int a20;int i;for(i=0;i20;i+); scanf(“%d”, &ai);for后面的那个分号,直接导致后面的那个分号,直接导致scanf不属于循环体。不属于循环体。(11) 对于应该有花括号的复合语句,忘记加花括号,对于应该有花括号的复合语句,忘记加花括号,例如:例如:sum=0;i=1;whi
12、le (iy?x:y; 改法改法1,在,在main中增加中增加max函数声明:函数声明:int main() float max(float x, float y); float a,b,c; a=3.5; b=-7.6; c=max(a,b); printf(“%f”, c); return 0;改法改法2,将,将max函数定义提到函数定义提到main之前,如:之前,如:float max(float x, float y) return xy?x:y; int main() float a,b,c; a=3.5; b=-7.6; c=max(a,b); printf(“%f”, c); r
13、eturn 0;(25) 对函数声明与函数定义不匹配,如对函数声明与函数定义不匹配,如fun定义为:定义为:int fun(int x, float y, long z) 则正确的声明写法只有三种:则正确的声明写法只有三种:int fun(int x, float y, long z);int fun(int, float, long); /可以不写变量名可以不写变量名int fun(int a, float b, long c); /可以乱写变量名可以乱写变量名其余写法都是错误的。其余写法都是错误的。(26) 在需要头文件的地方没有用在需要头文件的地方没有用#include指令包含头指令包含
14、头文件,例如程序中使用了文件,例如程序中使用了fabs函数,忘记包含函数,忘记包含math.h文件。文件。至于程序中使用的函数在哪一个头文件中,可以通至于程序中使用的函数在哪一个头文件中,可以通过查帮助文档获得,例如微软的过查帮助文档获得,例如微软的MSDN。再不行的。再不行的话,还可以上网去搜。话,还可以上网去搜。 (27) 误认为形参值的改变会影响实参的值。误认为形参值的改变会影响实参的值。int main( ) int a, b; a=3;b=4; swap(a,b); printf(%d,%dn,a,b); return 0;void swap(int x,int y) int t;
15、t=x;x=y;y=t; 原意是通过调用原意是通过调用swap函数使函数使a和和b的值对换,然后的值对换,然后在在main函数中输出已对换了值的函数中输出已对换了值的a和和b。但是这样。但是这样的程序是达不到目的的,因为的程序是达不到目的的,因为x和和y的值的变化是的值的变化是不传送回实参不传送回实参a和和b的,的,main函数中的函数中的a和和b的值并的值并未改变。未改变。 如果想从函数得到一个以上的变化了的值,应该如果想从函数得到一个以上的变化了的值,应该用指针变量。用指针变量作函数参数,使指针变用指针变量。用指针变量作函数参数,使指针变量所指向的变量的值发生变化。此时变量的值改量所指向的
16、变量的值发生变化。此时变量的值改变了,主调函数中可以利用这些已改变的值。如:变了,主调函数中可以利用这些已改变的值。如:int main( )int a,b,*p1,*p2; a=3;b=4; p1=&a;p2=&b; swap(p1,p2); printf(%d,%dn,a,b);/a和和b的值已对换的值已对换 swap(int *pt1, int *pt2)int t; t=*pt1;*pt1=*pt2;*pt2=t; /借助指针间接修改借助指针间接修改a,b 事实上,变量的指针和变量的地址是一样的,所以事实上,变量的指针和变量的地址是一样的,所以swap函数的调用可以不借
17、助指针,直接使用地址:函数的调用可以不借助指针,直接使用地址:swap(&a, &b); /直接将直接将a,b的地址传入的地址传入(28) 函数的实参和形参类型不一致。函数的实参和形参类型不一致。int main() int fun(int x, int y); float a=3.5, b=4.6, c; c=fun(a, b); / 这行有警告,因为数值的精度受损这行有警告,因为数值的精度受损printf(“%f”, c); int fun(int x,int y) return x+y; 实参实参a、b为整型,形参为整型,形参x、y为实型。为实型。a和和b的值传递的值传递
18、给给x和和y时,时,x和和y的值并非的值并非3和和4。C要求实参与形参要求实参与形参的类型一致。如果在的类型一致。如果在main函数中对函数中对fun作原型作原型声明:声明:float fun (float, float);程序可以正常运行。程序可以正常运行。(29) 不同类型的指针混用。不同类型的指针混用。int main( )int i=3,*p1; float a=1.5,*p2; p1=&i;p2=&a;p2=p1; printf(%d,%dn,*p1,*p2); 企图使企图使p2也指向也指向i,但,但p2是指向实型变量的指针,不是指向实型变量的指针,不能指向整型变量。
19、能指向整型变量。指向不同类型的指针间的赋值必须进行强制类型转指向不同类型的指针间的赋值必须进行强制类型转换。如:换。如:p2=(float*)p1;作用是先将作用是先将p1的值转换成指向实型的指针,然后再的值转换成指向实型的指针,然后再赋给赋给p2。这种情况在这种情况在C程序中是常见的。例如,用程序中是常见的。例如,用malloc函函数开辟内存单元,函数返回的是指向被分配内存空数开辟内存单元,函数返回的是指向被分配内存空间的间的void *类型的指针。而人们希望开辟的是存放类型的指针。而人们希望开辟的是存放一个结构体变量值的存储单元,要求得到指向该结一个结构体变量值的存储单元,要求得到指向该结
20、构体变量的指针,可以进行如下的类型转换构体变量的指针,可以进行如下的类型转换:struct studentint num; char name20; float score; ;struct studentstudent1,*p;p=(struct student *)malloc(LEN);p是指向是指向struct student结构体类型数据的指针,将结构体类型数据的指针,将malloc函数返回的函数返回的void *类型指针转换成指向类型指针转换成指向struct student类型变量的指针。类型变量的指针。(30) 没有注意函数参数的求值顺序。例如有以下语没有注意函数参数的求值顺序
21、。例如有以下语句:句:i=3;printf(%d,%d,%dn,i,+i,+i);许多许多人认为输出必然是人认为输出必然是3,4,5实际不尽然。在实际不尽然。在Turbo C和其他一些和其他一些C系统中输出是系统中输出是5,5,4因为这些系统是采取自右至左的顺序求函数参数的因为这些系统是采取自右至左的顺序求函数参数的值。先求出最右面一个参数值。先求出最右面一个参数(+i)的值为的值为4,再求出,再求出第第2个参数个参数(+i)的值为的值为5,最后求出最左面的参数,最后求出最左面的参数(i)的值的值5。C标准没有具体规定函数参数求值的顺序是自左而右标准没有具体规定函数参数求值的顺序是自左而右还是
22、自右而左。但每个还是自右而左。但每个C编译程序都有自己的顺序,编译程序都有自己的顺序,在有些情况下,从左到右求解和从右到左求解的结果在有些情况下,从左到右求解和从右到左求解的结果是相同的。例如是相同的。例如fun1(a+b,b+c,c+a);fun1是一个函数名。是一个函数名。3个实参表达式个实参表达式a+b、b+c、c+a。在一般情况下,自左至右地求这在一般情况下,自左至右地求这3个表达式的值和自个表达式的值和自右至左地求它们的值是一样的,但在前面举的例子右至左地求它们的值是一样的,但在前面举的例子是不相同的。因此,建议最好不用会引起二义性的是不相同的。因此,建议最好不用会引起二义性的用法。
23、如果在上例中,希望输出用法。如果在上例中,希望输出“3,4,5”时,可时,可以改用以改用i=3;j=i+1;k=j+1;printf(%d,%d,%dn,i,j,k);(31) 混淆数组名与指针变量的区别。混淆数组名与指针变量的区别。int main( ) int i,a5; for(i=0;i5;i+) scanf(%d,a+);企图通过企图通过a的改变使指针下移,每次指向欲输入数据的改变使指针下移,每次指向欲输入数据的数组元素。它的错误在于不了解数组名代表数的数组元素。它的错误在于不了解数组名代表数组首地址,它的值是不能改变的,用组首地址,它的值是不能改变的,用a+是错误的,是错误的,应当
24、用指针变量来指向各数组元素。应当用指针变量来指向各数组元素。可以改成下面的写法:可以改成下面的写法:int i,a5,*p;p=a;for(i=0;i5;i+) scanf(%d,p+); 或者:或者:int a5,*p;for(p=a;pa+5;p+) scanf(%d,p);(32) 混淆结构体类型与结构体变量的区别,对一个混淆结构体类型与结构体变量的区别,对一个结构体类型赋值。结构体类型赋值。struct workerlong int num; char name20; char sex; int age; ;worker.num=187045; strcpy(,Z
25、hangFun);worker.sex=M;worker.age=18;这是错误的,只能对变量赋值而不能对类型赋值。这是错误的,只能对变量赋值而不能对类型赋值。上面只定义了上面只定义了struct worker类型而未定义变量。应类型而未定义变量。应改为改为struct worker worker_1;worker_1.num=187045;strcpy(worker_1.name,Zhang Fun);worker_1.sex=M;worker_1.age=18; 今定义了结构体变量今定义了结构体变量worker_1,并对其中的各成,并对其中的各成员赋值。员赋值。 (33) 使用文件时忘记打
26、开,或打开方式与使用情况使用文件时忘记打开,或打开方式与使用情况不匹配。不匹配。例如,对文件的读写,用只读方式打开,却企图向例如,对文件的读写,用只读方式打开,却企图向该文件输出数据,例如:该文件输出数据,例如:if(fp=fopen(test,r)=NULL) printf(cannot open this filen); exit(0); ch=fgetc(fp);while(ch!=#) ch=ch+4; fputc(ch,fp); /此语句有错此语句有错 ch=fget(fp); (34) 在打开文件时,指定的文件名找不到。例如:在打开文件时,指定的文件名找不到。例如:if (fp=fopen(“test”, “r”)=NULL) printf(“cannot open this filen”); exit(0);试图打开一个已存在的文件试图打开一个已存在的文件test,但是这个文件不存,但是这个文件不存在。一般出现这个问题的原因,是在。一般出现这个问题的原因,是test文件不在当前文件不在当前目录下,所以把目录下,所以把test的路径写全了就行了,如:的路径写全了就行了,如:if (fp=fopen(“d:temptest”, “r”)=NULL)注意路径要用注意路径要用分隔,因为单个分隔,因为单个是转义字符的前缀。是转义字符的前缀。(35) 忘记关闭文件。虽然
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年民生银行沈阳分行社会招聘备考题库有答案详解
- 2025年钦州市灵山生态环境局关于向社会公开招聘工作人员的备考题库附答案详解
- 2025年广州越秀区文联招聘合同制辅助人员备考题库完整参考答案详解
- 2026年短期影院影片策划合同
- 2026年绿电交易合同
- 2025年郑州市中原银行农村普惠金融支付服务点招聘备考题库及一套答案详解
- 2026年国际传统医药国际城市关尹子星城市合同
- 中国人民银行清算总中心所属企业城银清算服务有限责任公司2026年校园招聘16人备考题库及参考答案详解1套
- 2026年长沙市中小学素质教育实践基地岳麓营地编外合同制教师、教官招聘备考题库及参考答案详解一套
- 2025年嘉睿招聘(派遣至市第四人民医院)备考题库及1套完整答案详解
- 现代精细化工生产技术 课件 模块1-4 表面活性剂 -涂料
- 合伙开母婴店协议合同
- 2025年事业单位招聘考试综合类专业能力测试试卷(新闻类)新媒体运营与管理实战
- GB/T 23436-2025汽车风窗玻璃清洗液
- 冷库安全培训演练课件
- 2025年高考物理山东卷试卷评析及备考策略(课件)
- 农业产业新质生产力
- 五金厂生产部工时统计制度
- 研磨钻石的专业知识培训课件
- 以青春之名赴时代之约-高中爱国主题班会-2025-2026高中主题班会
- 2025年传达学习医疗机构重大事故隐患判定清单会议记录
评论
0/150
提交评论