c程序设计注意事项及解决方法

上传人:daj****de2 文档编号:173997594 上传时间:2022-12-13 格式:DOCX 页数:18 大小:31.74KB
收藏 版权申诉 举报 下载
c程序设计注意事项及解决方法_第1页
第1页 / 共18页
c程序设计注意事项及解决方法_第2页
第2页 / 共18页
c程序设计注意事项及解决方法_第3页
第3页 / 共18页
资源描述:

《c程序设计注意事项及解决方法》由会员分享,可在线阅读,更多相关《c程序设计注意事项及解决方法(18页珍藏版)》请在装配图网上搜索。

1、t/!g/*C语言常见问题及解答*/!/!g问题Q:为什么在机房上机LINK时出现以下错误信息:LinkerError:UnabletoopeninputfileCOS.OBJ(连接器出错:不能打开输入文件C0S.OBJ)A:COS.obj那个问题是因为机房装机的老师修改TC配置文件有误,结果TC在编译时找不到需要的文件,所以出错。从缘网下载的TC2.0安装的时候貌似也有这个问题。改正办法: 先在桌面上找到TC,然后右键-属性-程序-命令行,可能显示如下结果:D:TCTC.EXE这个表明机房的TC是安装在D:TC下面。 双击桌面上的TC,运行它。然后按Alt+O键选择Options菜单,再移动

2、光标到Directories菜单项敲回车。可能出现如下所示的信息:Includedirectories:E:TCINCLUDELibrarydirectories:E:TCLIBOutputdirectory:E:TurboCdirectory:E:TCPickfilename:TCPICK.TCPCurrentpickfile:TCPICK.TCP很显然,上述目录(directory)特别是Include及Library被改成E:盘之后,TC无法在E:盘找到它需要的文件,因为事实上这些文件被安装在D:盘中。所以我们要把上述信息修改成:Includedirectories:D:TCINCLUD

3、ELibrarydirectories:D:TCLIBOutputdirectory:D:TC(这个是存放源程序及EXE程序的文件夹,也可改成你自己的文件夹,比如E:ME)TurboCdirectory:D:TCPickfilename:TCPICK.TCPCurrentpickfile:TCPICK.TCP改好之后按Esc回上一级菜单,移动光标到Saveoptions并敲回车,出现如下信息:D:TCTCCONFIG.TC如果不是则改之。再敲一个回车,它会问你:OverwriteTCCONFIG.TC(Y/N)意思是:要不要覆盖TCCONFIG.TC文件你输入Y表示Yes即可。 主页上下载Tu

4、rboC2.0(修正版)并安装,保证不会有这个毛病。问题Q:我不知道有些TC菜单项的意思,如File|Pick,能否得到帮助?A:选中该菜单项,然后按F1,结束帮助按Esc.在编辑状态下,按F1可以得到有关编辑时键盘使用的一些说明,包括如何进行块操作,你现在就可以按F1试试.当一屏显示不下时,可以按PageUP与PageDown.问题Q:如何快速地把光标移到一行的头尾?A:Home与End,不要拼命地按左键与右键,这是愚蠢的表现.问题Q:如何快速地把光标移到整个程序的头尾?A:Ctrl+PgUp与Ctrl+PgDn问题Q:如何把程序的一部分移到另一个位置,或复制到另一个位置?A:先定义一个块:

5、把光标移到块首,按Ctrl+K,再按B,然后把光标移到块尾,按Ctrl+K,再按K,这时你会看到你选中的部分颜色变亮,表示块定义成功;把光标移到目标位置,按Ctrl+K,再按V就可以对块进行移动,如果按Ctrl+K,再按C则对块进行复制.做完块操作后,若要把变亮部分的颜色恢复原样,则按Ctrl+K,再按H.删除块可以按Ctrl+K,再按Y.记忆:B表示block这个词的首字母,K表示这个词的最后一个字母,C表示copy,V表示move;若用VC编程则可以直接复制粘贴;另外,也可以用EditPlus这个软件来写程序,它的编辑功能非常强大,不仅可以复制粘贴n行,也可以复制粘贴n列(按Alt+C键选

6、择列块),同时还可以按Ctrl+Shift+I左缩进,按Ctrl+I右缩进。问题Q:当程序陷入死循环时,除了重新启动外,还有没有其它办法?A:按Ctrl+Pause键,即通常所说的Ctrl+Break,当回到TC后,你很可能会发现程序行中有一条青色的亮条,按下Ctrl+F2可以消除.Ctrl+F2表示程序复位(回到程序的初始状态),相当于选择菜单项Run|Programreset.问题Q:当我不想运行程序的某一部分,但又不愿删除这部分时,该怎么办?A:用/*和*/把这部分注释掉;也可用#if0与#endif把这部分内容包起来,当想要注释掉的程序里面已经有注释时,用此方法非常有效。问题Q:我不知

7、道按了一个什么键后,原先屏幕下面的错误信息窗不见了.A:按F5.F5表示对当前窗口进行缩放(zoom).在编辑时,你所在窗口是Edit下面的窗口是Watch(观察窗),按F6可以在这两个窗口之间切换,按F5把当前所在窗口缩小或放大.问题Q:不知怎么的,当我想在某一行当中插入一些字符时,现在打进去的字符并没有把后面的字符朝后推,而是把它们逐个地擦掉了.A:按Insert键.Insert键用于编辑时插入与改写状态的切换.问题Q:如何得到函数的用法帮助,如有关pow()函数的参数及返回值?A:把光标移到函数名中任意一个字母下面,再按Ctrl+Fl。问题Q:如何查出程序中的逻辑错误(BUG)?A:第一

8、种方法:把程序划分成几个逻辑段,然后从上到下逐段地排除错误.具体来说,你可以在你觉得可疑的某段程序后加上一些printf(),显示一些重要变量的值,以验证前面部分程序执行是否正确,若没有问题,再在下段程序后加上一些printf(),如此反复多次,必然可以把错误限定在一个很小的范围内,查起来就容易了.第二种方法:跟踪.要学好C语言,必须学会跟踪.跟踪程序要用到以下一些键:F8让程序走一步.当前走到的程序行上有一个青色的亮条.F7让程序走一步.F7与F8的不同之处在于F7能跟踪到函数调用里面,F8则不跟踪函数调用.F4让程序运行到光标当前所在的程序行,这里的光标是指不断闪动的小光标,不是指青色的亮

9、条。F4可以让程序快速运行到循环外面。Ctrl+F8在当前光标所在程序行上设置断点(breakpoint).当程序到断点处时会自动地停下来,因此断点相当于一块拦路石.程序中可以设置多个断点.在断点处再按一下Ctrl+F8可以取消该断点.Ctrl+F9让程序从青色亮条处一直向下运行,直到断点或程序结束,相当于菜单项中的Run|Run.Ctrl+F7观察某个变量的值.当按下此键后,TC会弹出一个对话框,这时应输入你想观察的某个变量的名字,如x,然后按回车.接下去你会发现在屏幕下面的Watch窗中出现了x以及x当前的值.当你按F8跟踪时,若程序中x的值有变化,Watch窗中的x也会跟着变化.可以多次

10、按这个键观察多个变量.当你不想观察某个变量时,可以按F6切换到Watch窗,然后把光标移到该变量处,再按Delete键,然后再按F6切换到代码窗。Ctrl+F2程序复位.使程序回到初始状态,即刚开始运行时的状态,可以重新开始跟踪.具体有关跟踪过程的操作请参考视频1和视频2,VC调试请参考视频3Q:对于自己编的函数应在程序开头说明其原型(prototype),或把函数定义放在引用前.但对于库函数也要说明函数原型吗?我在程序中调用如printf(),scanf(),puts()等函数时从来都不说明原型,也从不用包含头文件的方法(即#include)来包含这些函数的原型信息,编译连接运行都很正常.A

11、:原型的好处是让编译程序知道被调用函数的返回值类型,参数个数及参数类型.当程序中没有说明函数原型,也不把定义放在调用前时,编译程序在遇到函数调用时会自动假设该函数的原型为:intfunc_name();即该函数的返回值类型为int,参数个数及类型都不确定.因此某个函数(包括你自己的函数和库函数)碰巧返回int时,你不说明原型也问题不大,如printf(),scanf()等都返回int.但这并不等于说不说明原型就肯定没问题.下面举两个例子:例一.main()printf(123);/*没有原型,编译不会出错,但结果是#$%?乱七八糟一堆显然,参数有问题。printf(第一个参数应该是一个字符串或

12、字符指针,即字符串首元素的地址。如果你说明了原型(在程序前加上#include就不会犯这个错误,因为编译程序会告诉你错了。*/例二.main()doublex=4,y;y=sqrt(x);printf(y=%lfn,y);/*结果显示:y=-32736*/*原因:由于你没有说明开方函数sqrt()的原型,编译器认为qr的返回值为int类型,但实际上该函数的返回值应该doubl类型.当把该函数的值(应该是8个字节)赋值给变量y时,实际上只取此值的前2个字节(即1个int)再类型转化为double,然后赋值给y,结果当然是错的.解决:方法一:在程序开头(即main()之前)写上函数sqrt()的原

13、型:doublesqrt(doublex);方法二:在程序开头用#include包含头文件math.h,该头文件中含有函数sqrt()的原型说明:#include*/Q:在以下程序中,每次getchar()照例只输入一个字符,如果要输入三个字符,应该输入三次才对,但当我第一次就输入ABC#时,整个程序就结束了,后面我没有机会再输第二次,但结果却是对的,为什么?#includemain()charc=0;while(c!=#)c=getchar(c);putchar(c);A:当你第一次就输入超过一个字符时,getchar()只要了你的第一个字符,多余的字符会放到一个称为缓冲区(buffer)的

14、地方保存;当再次getchar()时,getchar()会先到缓冲区中看一看有没有上次余下的字符,若有的话,就不要求你再次输入了,而是直接从缓冲区中取出下一个字符;若getchar()在缓冲区中找不到上次余下的字符,它会要求你再次输入.Q:C语言的语句一般都要求用分号结束,没有分号会产生一个statementmissing;in.的错误,但是用大括号括起来的复合语句后面好象不用加分号,要是加了也没关系,事实是不是这样呢?A:事实不是如此.用大括号括起来的语句即复合语句(compoundstatement)后面确实是不用加分号的,但并非加了也没关系.结束复合语句的右大括号本身就隐含地起了分号的作

15、用,它已经表示本语句到此结束,如果你再在后面加一个分号,则这个分号并不表示复合语句的结束,而表示复合语句后面跟了一个空语句,因为分号前面没有东西的语句就是空语句,例如:main()inti,j;for(i=1;i=9;i+)for(j=1;j=0)y=1;z=1;/这*个分号有问题!为什么?*/elsey=-1;z=-1;Q:怎样把.txt文件重命名为.C文件?A:(1)去掉以下选项中前面的勾:我的电脑-工具-文件夹选项-查看-隐藏已知文件类型的扩展名(2)重命名.txt为.c问题16Q:如果我不小心打错了函数名,比如把printf打成print时,则Compile是成功的,但是Link的时候

16、就会报以下错误:LinkerError:Undefinedsymbol_print而且光标停在屏幕底行不上来了,按回车也没有用,怎么办?A:按F6。F6表示切换(Switch)窗口。问题17Q:如何把TC窗口切换到全屏?A:按Alt+Enter,要切换回来也按此组合键。Q:如何把观察中的变量名删除?A:先按F6切换到下面的窗口,再按Del删除。删完后,再按F6。Q:每次用Ctrl+F7观察变量的时候都要输入变量名,但有些变量名很长,输起来很烦,有没有快一点的办法?A:把光标移到变量名下面,按Ctrl+F7。Q:如何用TC重新打开已保存的.c文件?A:(1) 选菜单File-Load,输入*.c

17、选择你保存的.c文件(2) 用鼠标左键点住.c文件,并把它拖到TC.exe或TC的快捷方式上面。Q:如何快速删除TC中的一行语句?A:按Ctrl+YQ:如何在TC中观察一个数组的内容?A:Ctrl+F7,输入数组名即可,后面不要跟方括号。Q:当用数组作实参传递给形参后,形参实际上是一个指针变量,请问如何在跟踪到被调函数后,观察该形参数组的内容?A:假定该形参数组名为a,元素个数为10个,则Ctrl+F7,输入*a,10,这里的10表示一共要观察10个元素。如果想要以16进制的格式观察这10个元素,则输入*a,10X。Q:假定函数main()和函数f()都分别定义了局部变量a,请问如何同时观察这

18、两个变量?A:Ctrl+F7,输入main.a,再Ctrl+F7,输入f.a。Q:如何证明值传递时的实参变量与形参变量是两个不同的变量?A:只要输出实参与形参的地址即可,程序如下:voidf(inta)printf(addressofainf()=%pn,&a);/*(1)*/a=-a;main()inta=123;printf(addressofainmain()=%pn,&a);/*(2)*/f(a);printf(a=%dn,a);语句(1)、(2)的输出结果肯定不同,所以f()的a与main()的a不是同一个变量。Q:如何证明形参数组实质上是一个指针变量而不是一个数组?A:设实参数组名

19、为a,共3个元素,类型为float,对应的形参数组名为b。若b是数组,则b不可以赋值,因为数组名就是数组的首地址,是常数,不能赋值的;若b是数组,则可以用sizeofO求出该数组全体元素占用的内存字节数;但事实上,b可以赋值,而且sizeof(b)的值不是12,而是2:voidf(floatb,intn)inti;float*q=b+n-1;/*q指向an-1*/printf(sizeof(b)=%dn,sizeof(b);/*在TC中输出2,VC中输出4。因为指针变量的值是一个地址,而地址其实就是一个整数,所以,sizeof(指针)等价于sizeof(int)*/b+;/*这里可以改变b的值

20、。若b是数组,则这里会语法错误*/while(b=q)*b*=-1;b+;/*以上两句可以合并成一句:*b+*=-1;*/main()floata=10,20,30;inti,n;printf(sizeof(a)=%dn,sizeof(a);/*输出12*/n=sizeof(a)/sizeof(a0);/*n=3*/f(a,n);for(i=0;in;i+)printf(%f,ai);输/出*10-20-30*/Q:假定a是一个char类型的数组,则可以用puts(a)、printf(a)、printf(s,a)输出a的内容,那么是不是也可以用同样的方法输出int类型数组的内容呢?A:不可以。

21、puts(a)之所以能够输出a的内容是因为实参a的类型是char*,而puts()函数只能接受这种类型的参数,如果你把一个int类型的数组比如b代入puts(),则实参b的类型是int*,根本不是char*,所以必然导致语法错误。如果要输出int类型数组的全体内容,只能通过循环逐个输出。Q:sizeof()与strlen()有啥区别?A:sizeof()是运算符,strlen()是函数; sizeof()里面可以代入各种类型或表达式,strlen()的参数类型必须是char*;chara10=ABCD,b=sizeof(a),c=strlen(a),d二sizeof(ABCD);则b=10,c

22、=4,d=5。Q:假定a、b是两个同类型的数组,请问能否用if(a=b)比较两者是否A:不可以。#include#includemain()chara10=ABCD,b10;strcpy(b,a);把/a的内容复制到b中*/if(a=b)puts(aisequaltob.);elseputs(aisnotequaltob.);/*结果程序执行到这里*/这里if(a=b)并没有语法错误,那么a、b为什么不相等?因为这里的a、b并非指数组a、b的全体内容,而是指数组a、b的首地址,而a、b是两个不同的数组,它们的首地址显然是不等的。要比较两个char类型的数组内容是否全等,应该调用函数strcmp

23、();要比较两个其它类型的数组内容是否全等,可以通过循环逐个元素比较。Q:定义数组时,数组的元素个数必须为常数。那请问有没有办法先输元素个数,再定义数组呢?A:可以,但是要用指针来实现,而且要调用一个不在考试范围内的函数malloc(),举例如下:#include#includeVstdl让h/*malloc()函数的原型在此头文件中*/main()inti,n,*p;scanf(%d,&n);/*假定输入10*/p=(int*)malloc(sizeof(int)*n);/*malloc()用来分配一块内存,并返回该块内存的首地址;参数是需要分配的字节数;返回值是内存块的首地址,类型是voi

24、d*,即指向类型不确定的对象的指针;返回值通常要经过强制类型转化,变成等号左边变量的类型。p赋值后,指向10个int的首个,以后p可以当成int数组来用。*/for(i=0;in;i+)pi=i;/*当作数组来用*/free(p);/*用完以后,调用函数free()释放这块内存*/Q:排序除了使数看起来整齐外,有没有实际的用途?A:一个非常重要的应用就是二分法。假定有以下10个已按从小到大顺序排好的整数:下标:0123456789值:102230445560778099100现要找77这个数,则查找过程如下:(1) 设定最左边元素的下标left=0,最右边元素的下标right=9。(2) 计算

25、中间那个元素的下标m=(left+right)/2=(0+9)/2=4(2) 比较77和am=a4=55,发现77am,因此,77落在右边一半。(3) 改变最左边元素的下标left=m+1=5,最右边元素的下标不变。(4) 计算中间那个元素的下标m=(left+right)/2=(5+9)/2=7(5) 比较77和am=a7=80,结果77am,因此,朝右边找。(9) 改变最左边元素的下标left=m+1=6,最右边元素的下标不变。(10) 计算中间那个元素的下标m=(left+right)/2=(6+6)/2=6(11) 比较77和am,结果相等,查找结束。上述查找过程可以用循环法写成函数如

26、下:intfind(inta,intn,intx)intleft=0,right=n-1,m;while(left=right)m=(left+right)/2;if(x=am)/*若找到*/returnm;/则*返回下标*/if(xright)return-1;if(x=am)returnm;if(xam)returnfind(a,m+1,right,x);二分法可以用于数据库的查询,比如一部电子字典,它查找某个单词时并非从头找到尾,因为这样找起来太慢了。假定字典里的条目已经按A-Z顺序排序,则查找某个单词的过程也是用二分法来实现的。二分法的速度非常快,假定字典条目达到2的64次方,则最多找

27、65次肯定找着。Q:假定已经定义chara100;请问scanf(%s,a);与gets(a);有没有区别?A:有区别。假定输入ABCXYZ123并回车,则用scanf(s,a);输入得到的a为ABC,而用gets(a);输入得到的a为ABCXYZ123。这就是说,scanf(%s,a);是以空白符作为分隔符的,遇到任意一个空白符就认为输入结束,而gets(a);则是以回车作为分隔符的。 假定分别执行以下两个程序:程序1:main()intx;chara100;scanf(%d,&x);/*输入123回车*/scanf(%s,a);/*输入ABC回车*/printf(%dn,x);/*输出12

28、3回车*/printf(%sn,a);/*输出ABC回车*/程序2:main()intx;chara100;scanf(%d,&x);/*输入123回车*/gets(a);/输*不进去*/printf(%dn,x);/*输出123回车*/printf(%sn,a);/*输出回车*/程序2之所以无法输入a,是因为前面输入x时所敲的回车留在输入缓冲区内,gets(a)时,相当于在gets(a)时敲回车,于是a0=0,所以最后输出a时只输出一个回车。在TC或VC中要解决这个问题,可以在gets(a)前面插入以下函数调用:fflush(stdin);此函数调用的作用是清除输入缓冲区。在Linux系统中,则应该调用函数fpurge(stdin);来取代fflush(stdin);。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!