C语言编程中常见问题.docx
《C语言编程中常见问题.docx》由会员分享,可在线阅读,更多相关《C语言编程中常见问题.docx(20页珍藏版)》请在冰点文库上搜索。
C语言编程中常见问题
为什么vc6打开的文件却不能编译1
为什么一个vc6工程中有两个main函数不能编译成功?
我想写两个程序怎么办?
2
为什么v6不能编译程序,生成信息说compile和link都正确,到了link生成exe时,却报错无法生成该exe文件2
为什么Vc6在编译时,下方消息窗体显现了compiling…或linking…后就死了,没有反应了,怎么办2
如何用任务窗体关闭进程3
如何生成一个vc6工程3
如何查看工程中的文件7
如何添加一个已有文件到工程8
如何添加一个新文件到vc6中9
为什么Scanf执行后程序报错死了10
如何通过编译器的编译消息框发现语法错误10
如何发现代码中混入了中文信息11
如何打/取消断点12
如何让程序可以调试方式运行12
为何不能在断点停下来12
为何我不能看到输出的结果,程序闪了一下就结束了12
为何在scanf打断点后,程序停下来,再单步执行,没有动静了12
如何单步执行13
如何查看变量或某个表达式的值?
13
在watch中如何用16进制显示某一项变量或表达式14
内存查看窗体14
不用ascii表,用内存查看字符的ascii码值15
用内存窗体证明”A”和’A’的区别16
用内存窗体定位一个scanf错误17
内存窗体可修改内存的值17
利用内存窗体发现a,b,c,d的规律18
用调试分析错误18
用二分法查看编译错误19
字符串0结尾的bug19
为什么vc6打开的文件却不能编译
因为你是打开的该文件,而不是将其加入到ide中。
如果添加一个新文件,请参见
如果添加一个已有文件,请参见
为什么一个vc6工程中有两个main函数不能编译成功?
我想写两个程序怎么办?
因为一个工程代表一个程序,一个程序只有一个入口点。
Main是入口函数,如果有两个main,到底哪个才是入口能?
如果想编两个程序,那么生成两个工程即可。
见工程生成。
为什么v6不能编译程序,生成信息说compile和link都正确,到了link生成exe时,却报错无法生成该exe文件
因为,你可能没有关闭该exe程序。
关闭重编译即可。
如果找不到该exe是否还在执行就用任务管理器查看该进程并关闭。
为什么Vc6在编译时,下方消息窗体显现了compiling…或linking…后就死了,没有反应了,怎么办
编译环境出问题了,用任务管理器关闭vc6进程,其名字是msdev,如下图,鼠标左键单击选中它,结束该进程。
如何用任务窗体关闭进程
同时按照ctr,alt和delete键,win7上点击界面中“启动任务管理器”选项。
将弹出如下窗体
选中要结束的某个进程。
然后点击右下角结束进程按钮结束之。
如何生成一个vc6工程
目录选择,点击上图的包含…的按钮后,如下图选择工程所在目录
如何查看工程中的文件
在左边面板,鼠标左击选择右下方的fileview,并点击左边的加号展开工程节点,并点击展开sourcefiles节点,即可见相关文件。
点击文件即可在右边面板编辑文件了。
如何添加一个已有文件到工程
选择files菜单
在弹出的文件对话框中选择相关文件(在顶部下拉框中选择目录,在中间用鼠标左键点击选择要添加的文件),然后按ok即可。
如何添加一个新文件到vc6中
在红色箭头所指处输入新文件名字,并按ok
为什么Scanf执行后程序报错死了
intI;
scanf(“%d”,I);
因为要修改I的内容,必须传递给I的地址,即&I.而此时却是将I的值传递给scanf了。
此时I是随机数,比如7777,那么,scanf获取到键盘值后,就会将它写入地址为7777的内存。
如果该内存不存在,就要出错。
正确做法
intI;
scanf(“%d”,&I);
如何通过编译器的编译消息框发现语法错误
编译出错后,我们会看见下方如下信息
拨动滚动条查看上面信息,加下图
说明test1.cpp的第9行出错了,错误如行中信息所示。
双击上图中error所在行将跳到出错的行,如下图
我们发现sum后的等号多了一个“:
“
如何发现代码中混入了中文信息
比如我们在代码非注释部分敲入了中午的分号,逗号等,很不容易发现,但这是不允许的。
编译器会报错。
因为中文字比因为选择多,一个字节(256种选择)无法代表几万个字,所以中文字由两个字节组成。
如上面小节的错误,将sum后的冒号变成中文的冒号,编译错误是:
test1.cpp
F:
\hhan\test\test1.cpp(9):
errorC2018:
unknowncharacter'0xa3'
F:
\hhan\test\test1.cpp(9):
errorC2018:
unknowncharacter'0xba'
Errorexecutingcl.exe.
这时还是指示sum所在行出错了。
而提示有两个不识别的字符0xa3,0xba其实这两个字符就代表中文冒号。
出现这种“unknowncharacter'0x..'信息,一般就说明可能混入了中文字符。
如何打/取消断点
断点,即是调试方式运行时,执行到断点所在行,程序将暂停,我们可以分析其状态。
将光标放到要打断点的行,按f9即可。
取消也按f9
如何让程序可以调试方式运行
按f5运行即可。
为何不能在断点停下来
可能你是ctrl+f5运行的,或你点击了工具条上的惊叹号按钮运行。
这不是调试运行,所以不会停止。
用f5运行即可。
为何我不能看到输出的结果,程序闪了一下就结束了
因为在f5方式下运行,程序执行完毕自动就结束了。
如果你只是打印了信息就退出,那么,非常快,程序打印完毕就退出了,所以只看到了黑色的dos界面闪了一下。
解决办法:
1,用ctrl+f5运行。
这时,程序会在最后退出前停下来等待你的键盘回车。
2在dos界面中执行该程序
3在程序最后打个断点,f5运行,停在断点后,切换到dos界面查看结果
4在程序最后加一个getchar,这样就会停下来,等待你回车输入
为何在scanf打断点后,程序停下来,再单步执行,没有动静了
因为这时已经执行了scanf,而scanf需要从黑色的dos窗体中接收键盘输入。
这时我们应该切换到dos窗体,输入数据,回车,自然又在v6中可调试了。
如何切换到dos窗体?
鼠标点击dos窗体的图标即可
如何单步执行
单步分为stepinto和stepover。
前者遇到函数会跟踪进函数,按f11即可
后者遇到函数不会跟踪进函数,而是执行下一句语句,按f10即可。
很多时候,你认为被调用函数不会有问题,就按f10,不跟踪进去,这样速度快
遇到诸如scanf这样的语句调用,不要按f11,否则就跟踪进scanf了。
如何查看变量或某个表达式的值?
当程序在调试方式下运行,停在某个断点时,我们可用watch查看所有合法的表达式和变量。
程序没执行,没停在某个断点,是不可能watch的。
上图中,我们在左下角的watch1中点击第一列name,在第一行输入要观察的变量c,即可看到value列给出了其值为字符A,且ascii值为65.
我们也可以输入任何合法的表达式,比如c+1
输入不合法的表达式就会报错,比如c1,因为没有这个变量就会报错。
watch可有多个观察的page,比如上图的watch1,watch2...
在watch中如何用16进制显示某一项变量或表达式
将该项强制为void*,因为调试器会用16进制显示指针类型。
比如显示charc;的值,可以(void*)c。
即可
内存查看窗体
如果没有内存窗体的工具条,选如下选出该工具条,点击customize菜单
在如下窗体的toolbars列表中勾选,debug复选框
勾选后,出现调试工具条
当调试运行在断点处停止后,
点击从右边数过来第3个按钮
,得到如下界面
上部Address栏中输入要查看的内存地址,回车即可查看。
图中每个字节由16进制表示。
左边0012FF40这些数字是地址
然后在内存窗体地址栏输入该地址0x0012FF40,回车
不用ascii表,用内存查看字符的ascii码值
voidmain()
{
charc='A';
charp[3];
scanf("%c",&p);
}
在scanf打断点,运行停止后,现在watch中查看c的地址,即&c。
获得地址为0x0012ff44.
注意地址为0x0012f44的内存值为41.这是16进制,0x41就是65.如果在watch中输入c的值,可证明这点。
用内存窗体证明”A”和’A’的区别
程序如下,调试,从watch获得c和p的地址,分别为0x12ff44和0x0012ff40
先看C中的值,在内存窗体地址栏输入0x12ff44
可见只有12ff44是0x41,后面并没有0作为结尾字符
再看p的内容,在内存窗体地址栏输入0x12ff40
可见41后面是00,字符串形式的A实际占用了2个字节,最后一个为0.
用内存窗体定位一个scanf错误
这个错在哪里呢?
调试执行scanf前,查看内存c的内容。
执行后,输入9,再看内容
地址0x12ff44就是c的地址,其中的值变成了09,不仅如此,后面3个字节的值也变成了00.为什么会这样?
因为d代表整数,是4字节,那么输入的9被翻译成整数表示,就会写4个字节,这时,c本来只占一个字节,scanf就导致越界写了,越了3字节。
如果输入的是66,请问在scanf后加入printf(“%c”,c);将打印什么值。
内存窗体可修改内存的值
在内存窗体中,将光标点在要修改字节上,直接按键盘输入即可。
利用内存窗体发现a,b,c,d的规律
然后打开内存窗体,查看c中的内容,即输入c的地址0x0012ff44.
将内存中的值0x41改成0x42.
请看有下watch中的c值,变成了B。
本来C的值是A。
用调试分析错误
只靠看,下面错误很难发现原因:
#include
voidmain()
{
inta,b,c;
scanf("%d&d",&a,&b);
if(a>b)
{c=a;
a=b;
b=c;
printf("%d%d",a,b);
}
}
而在main开始打断点,执行当执行了scanf后(输入数据并回车),我们发现程序报错。
很明显是scanf执行出错,而scanf不会有问题,因此,仔细查看参数,第二个d前应该是%但错误写为了&
用二分法查看编译错误
即使从编译错误提示,如果一时看不出哪行代码出了问题(极有可能是上下的其它地方的错)。
我们可以删除或注释掉一些语句编译。
如果依然错误可以继续扩大删除或注销的语句,直到正确。
然后再慢慢恢复删掉的语句,直到出错。
这样就能定位了。
字符串0结尾的bug
structPerson{
charname[4];
intage;
};
voidmain(){
Personp;
scanf("%s",&p.name);
scanf("%d",&p.age);
printf("%s\n",p.name);
}
如果第一个输入"hell",第2个输入18。
分析输出结果的原因
答案:
因为第一个输入实际要占5字节,最后一个是0字节,它录入到age的第一个字节,再输入age后,内存中的内容实际是‘h’‘e’‘l’‘l’0x12000000这时printf打印时会认为name字串的结尾在0x12后面那个0,这时会将0x12的ascii符号打印出来。