C语言上机软件VC++6.0中文版安装,学习Visual


Microsoft Visual C++6.0 介绍
从 2008 年 4 月开始,全国计算机等级考试将全面停止 Turbo C2.0(简称 TC)软件的使用,所有参加 二级 C 语言、三级信息技术、网络技术和数据库技术上机考试的考生,都要在 Visual C++6.0(简称 VC)环 境下调试运行 C 程序。众所周知,VC 软件主要是用来开发 C++程序的,如何在 VC 下调试运行 C 程序,对 于众多程序设计者来说,确实是一个新的话题。 VC 与 TC 的差异,主要是体现在程序设计语言 C++与 C 的关系上。其实,了解计算机程序设计的人都 知道,C++是 C 语言的升级板,VC 是在 Windows 进行 C++程序设计的主要软件,VC 完全兼容了 C 的功能, 也就是说,在 VC 下是完全能够进行 C 语言程序开发。 我以前下载安装过很多次_VC++6.0 中文版,但是每次都无法正常安装使用,下面就让我告诉 你下载 地址吧,保证可以正常使用,我也是偶然碰到的

按住 ctr 点击 “全国计算机等级考试 C 语言上机软件_VC++6.0 中文版.rar”安装
安装后你可能会出现下面的对话框,在左下角“不再显示此信息”勾上,然后点击“运行程序就”可 以了

Visual C++ 6.0 编程环境的使用

1



编制并运行一个简单程序 .................................................................................................................................. 3 1.1 编制并运行程序的“四步曲” ..................................................................................................................... 3 1.2 工程(PROJECT)以及工程工作区(PROJECT WORKSPACE) ............................................................................... 4 1.3 启动并进入VC6的集成开发环境 .................................................................................................................. 6 1.4 创建工程并输入源程序代码 ......................................................................................................................... 7 1.5 不创建工程,直接输入源程序代码 ........................................................................................................... 13 1.6 编译、链接而后运行程序 ........................................................................................................................... 13 1.7 及时备份自己的创作 ................................................................................................................................... 15 1.8 将自己设计的产品提供给他人使用 ........................................................................................................... 15

2

VC6集成开发环境使用参考............................................................................................................................. 17 2.1 VC6的常用菜单命令项 ................................................................................................................................ 17 2.2 VC6的主要工作窗口 .................................................................................................................................... 21

3

严谨思维,调试程序 ........................................................................................................................................ 24 3.1 什么时候需要对程序进行调试 ................................................................................................................... 24 3.2 对程序进行调试的基本手段和方法 ........................................................................................................... 25 3.3 对一个简单程序的调试过程 ....................................................................................................................... 28 3.4 设计合适的程序调试方案 ........................................................................................................................... 30 3.5 优秀程序员的基本素质——丰富的想象、严谨的思维............................................................................ 33

4

编译与链接过程中常见的出错提示 ................................................................................................................ 36 4.1 常见编译错误 ............................................................................................................................................... 37 4.2 常见链接错误 ............................................................................................................................................... 43

2

1

编制并运行一个简单程序
1.1 编制并运行程序的“四步曲”

让我们用 VC6 先来编制一个最简单的程序, 并让它运行(执行)而得出 结果,以此来作为了解 VC6 的开端。这个程序的功能仅仅是向屏幕 上输出一个字符串“Hello World” 。程序虽小,但与编制运行大程序 的整个过程是相同的,都包含着如下所谓的“四步曲” : (1)编辑(把程序代码输入,交给计算机)。 (2)编译(成目标程序文件.obj)。编译就是把高级语言变成计算机可以 识别的 2 进制语言,计算机只认识 1 和 0,编译程序把人们熟悉的语 言换成 2 进制的。 编译程序把一个源程序翻译成目标程序的工作过程 分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代 码优化;目标代码生成。主要是进行词法分析和语法分析,又称为源 程序分析,分析过程中发现有语法错误,给出提示信息。 (3)链接(成可执行程序文件.exe)。链接是将编译产生的.obj 文件和系 统库连接装配成一个可以执行的程序。 由于在实际操作中可以直接点 击 Build 从源程序产生可执行程序,可能有人就会置疑:为何要将源 程序翻译成可执行文件的过程分为编译和链接两个独立的步骤, 不是 多此一举吗?之所以这样做, 主要是因为: 在一个较大的复杂项目中, 有很多人共同完成一个项目(每个人可能承担其中一部分模块),其中 有的模块可能是用汇编语言写的,有的模块可能是用 VC 写的,有的 模块可能是用 VB 写的,有的模块可能是购买(不是源程序模块而是 目标代码)或已有的标准库模块,因此,各类源程序都需要先各自编
3

译成目标程序文件(2 进行机器指令代码),再通过链接程序将这些目 标程序文件连接装配成可执行文件。 (4)运行(可执行程序文件)。 上述四个步骤中, 其中第一步的编辑工作是最繁杂而又必须细致地由 人工在计算机上来完成,其余几个步骤则相对简单,基本上由计算机 来自动完成。

1.2 工 程 (Project) 以 及 工 程 工 作 区 (Project Workspace)
在开始编程之前,必须先了解工程 Project(也称“项目” ,或称“工程 项目”)的概念。工程又称为项目,它具有两种含义,一种是指最终 生成的应用程序, 另一种则是为了创建这个应用程序所需的全部文件 的集合,包括各种源程序、资源文件和文档等等。绝大多数较新的开 发工具都利用工程来对软件开发过程进行管理。 用 VC6 编写并处理的任何程序都与工程有关(都要创建一个与其相关 的工程),而每一个工程又总与一个工程工作区相关联。工作区是对 工程概念的扩展。一个工程的目标是生成一个应用程序,但很多大型 软件往往需要同时开发数个应用程序,VC 开发环境允许用户在一个 工作区内添加数个工程,其中有一个是活动的(缺省的),每个工程都 可以独立进行编译、连接和调试。 实际上, VC6 是通过工程工作区来组织工程及其各相关元素的, 就好 像是一个工作间(对应于一个独立的文件夹,或称子目录),以后程序 所牵扯到的所有的文件、资源等元素都将放入到这一工作间中,从而 使得各个工程之间互不干扰,使编程工作更有条理,更具模块化。最
4

简单情况下,一个工作区中用来存放一个工程,代表着某一个要进行 处理的程序(我们先学习这种用法)。但如果需要,一个工作区中也可 以用来存放多个工程, 其中可以包含该工程的子工程或者与其有依赖 关系的其他工程。 可看出,工程工作区就像是一个“容器” ,由它来“盛放”相关工程 的所有有关信息, 当创建新工程时, 同时要创建这样一个工程工作区, 而后则通过该工作区窗口来观察与存取此工程的各种元素及其有关 信息。创建工程工作区之后,系统将创建出一个相应的工作区文件 (.dsw),用来存放与该工作区相关的信息;另外还将创建出的其他几 个相关文件是:工程文件(.dsp)以及选择信息文件(.opt)等。 编制并处理 C++程序时要创建工程,VC6 已经预先为用户准备好了 近20种不同的工程类型以供选择,选定不同的类型意味着让 VC6 系统帮着提前做某些不同的准备以及初始化工作(例如,事先为用户 自动生成一个所谓的底层程序框架或称框架程序, 并进行某些隐含设 置,如隐含位置、预定义常量、输出结果类型等)。工程类型中,其 中有一个为“Win32 Console Application” ,它是我们首先要掌握的、 用来编制运行 C++程序方法中最简单的一种。此种类型的程序运行 时,将出现并使用一个类似于 DOS 的窗口,并提供对字符模式的各 种处理与支持。 实际上, 提供的只是具有严格的采用光标而不是鼠标 移动的界面。此种类型的工程小巧而简单,但已足以解决并支持本课 程中涉及到的所有编程内容与技术, 使我们把重点放在程序的编制而 并非界面处理等方面,至于 VC6 支持的其他工程类型(其中有许多还
5

将涉及到 Windows 或其他的编程技术与知识),有待在今后的不断学 习中来逐渐了解、掌握与使用。

1.3 启动并进入VC6的集成开发环境

图1-1 VC6的集成开发环境窗口 了解了工程及其上述一般概念后,现在就让我们开始 Visual C++ 6.0 之旅吧!首先按如下两种方法之一启动并运行 VC6,进入到它的集 成开发环境窗口(假设在 Windows 系统下已经安装了 VC6), 其具体窗 口式样如图 1-1 所示。 方法一:若桌面上有 VC6 图标(“横躺着”即“倒下”的“8”字型 图标,且标有“Microsoft Visual Studio 6.0”字样,如图 1-2 所示), 则用鼠标双击该图标。

6

图1-2 VC6在桌面上的快捷方式 方法二(假设按照通常方式对 VC6 进行了安装的话):通过“开始”→ “程序” “Microsoft Visual Studio 6.0” “Microsoft Visual C++ 6.0” → → , 单击一下该菜单项。 图 1-1 式样的窗口从大体上可分为四部分。上部:菜单和工具条;中 左:工作区(workspace)视图显示窗口,这里将显示处理过程中与项 目相关的各种文件种类等信息;中右:文档内容区,是显示和编辑程 序文件的操作区;下部:输出(Output)窗口区,程序调试过程中,进 行编译、链接、运行时输出的相关信息将在此处显示。 注意,由于系统的初始设置或者环境的某些不同,可能你所启动的 VC6 初始窗口式样与图 1-1 有所不同, 也许会没出现 Workspace 窗口 或 Output 窗口,这时可通过“View→Workspace”菜单选项的执行, 总可使中左处的工作区窗口显现出来;而通过“View→Output”菜 单选项的执行,又总可使下部的输出区窗口得以显现。当然,如果不 想看到这两个窗口,可以点击相应窗口的“x”按键来关闭窗口。

1.4 创建工程并输入源程序代码
为了把程序代码输入而交给计算机, 需要使用 VC6 的编辑器来完成。 如前所述, 首先要创建工程以及工程工作区, 而后才能输入具体程序 完成所谓的“编辑”工作(注意,该步工作在四步骤中最繁杂、而又 必须细致地由人工来完成!)。

7

图1-3 新建一个名为Sample的工程(同时自动创建一工作区)

(1)新建一Win32 Console Application工程
选择菜单 File 下的 New 项,会出现一个选择界面,在属性页中选择 Projects 标签后,会看到近 20 种的工程类型,我们只需选择其中最 简 单 的 一 种 : Win32Console Application ” 而 后 往 右 上 处 的 “ , “Location”文本框和“Project name”文本框中填入工程相关信息所 存放的磁盘位置(目录或文件夹位置)以及工程的名字,设置到此时的 界面信息如图 1-3 所示。 在图 1-3 中, “Location”文本框中填入如“D:\myData\VC6” ,这是假 设你准备在 D 磁盘的\myData\VC6 文件夹即子目录下存放与工程工 作区相关的所有文件及其相关信息, 当然也可通过点击其右部的 “?” 按钮去选择并指定这一文件夹即子目录位置。 “Project name”文本框 中填入如“Sample”的工程名(注意,名字由你根据工程性质确定, 此时 VC6 会自动在其下的 Location 文本框中用该工程名“Sample”
8

为你建立一个同名子目录, 随后的工程文件以及其他相关文件都将存 放在这个目录下)。 选择 OK 按钮进入下一个选择界面。 这个界面主要是询问用户想要构 成一个什么类型的工程,其界面如图 1-4 所示。

图1-4 选择创建一个什么样的工程 若选择“An empty project”项将生成一个空的工程,工程内不包括 任何东西。若选择“A simple application”项将生成包含一个空的 main 函 数 和 一 个 空 的 头 文 件 的 工 程 。 选 “ A"Hello World!"application”项与选“A simple application”项没有什么本质 的区别,只是需要包含有显示出“Hello World!”字符串的输出语句。 选择“An application that supports MFC”项的话,可以利用 VC6 所提供的类库来进行编程。 为了更清楚的看到编程的各个环节,我们选择“An empty project” 项,从一个空的工程来开始我们的工作。单击 Finish 按钮,这时 VC6
9

会为你生成一个小型报告,报告的内容是刚才所有选择项的总结,并 且询问你是否接受这些设置。 如果接受选择 OK 按钮, 否则选择 Cancel 按钮。我们选 OK 从而可进入到真正的编程环境下了。界面情况如图 1-5 所示。

图1-5 刚完成创建工程Sample的VC6集成开发环境窗口

(2)在工作区窗口中查看工程的逻辑架构
注意屏幕中的 Workspace 窗口,该窗口中有两个标签,一个是 ClassView, 一个是 FileView。 ClassView 中列出的是这个工程中所包 含的所有类的有关信息,当然我们的程序将不涉及到类,这个标签中 现在是空空如也。点击 FileView 标签后,将看到这个工程所包含的 所有文件信息。点击“+”图标打开所有的层次会发现有三个逻辑文

件夹:Source Files 文件夹中包含了工程中所有的源文件;Header
Files 文件夹中包含了工程中所有的头文件;Resource Files 文件夹中
10

包含了工程中所有的资源文件。所谓资源就是工程中所用到的位图, 加速键等信息,在我们的编程中不会牵扯到这一部分内容。现在 FileView 中也不包含任何东西。 逻辑文件夹是逻辑上的, 他们只是在工程的配置文件中定义的, 在磁 盘上并没有物理地存在这三个文件夹。 我们也可以删除自己不使用的 逻辑文件夹;或者根据我们项目的需要,创建新的逻辑文件夹,来组 织工程文件。这三个逻辑文件夹是 VC 预先定义的,就编写简单的单 一源文件的 C 程序而言, 我们只需要使用 Source Files 一个文件夹就 够了。

(3)在工程中新建C源程序文件并输入源程序代码
下面该轮到生成一个“Hello.cpp”的源程序文件,而后通过编辑界面 来输入所需的源程序代码。 选择菜单 Project 中子菜单 Add To Project 下的 new 项,在出现的对话框的 Files 标签(选项卡)中,选择“C++ Source File”项,在右中处的 File 文本框中为将要生成的文件取一个 名字,我们取名为 Hello(其他遵照系统隐含设置,此时系统将使用 Hello.cpp 的文件来保存所键入的源程序),此时的界面情况如图 1-6 所示。 而后选择 OK 按钮,进入输入源程序的编辑窗口(注意所出现的呈现 “闪烁”状态的输入位置光标),此时只需通过键盘输入你所需要的 源程序代码:
#include <stdio.h> void main() { printf("Hello World!\n"); }

11

图1-6 选择在工程Sample中新建一名为Hello.cpp的C源程序文件 可通过 Workspace 窗口中的 FileView 标签,看到 Source Files 文件夹 下文件 Hello.cpp 已经被加了进去,此时的界面情况如图 1-7 所示。

图1-7 在Hello.cpp输入C源程序代码 实际上,这时在 Workspace 窗口的 ClassView 标签中的 Globals 文件
12

夹下,也可以看到我们刚才所键入的 main 函数。

1.5 不创建工程,直接输入源程序代码
不需要象前面描述的那样显示地创新一个工程,对于新编写一个程 序, 只需要在图 1-3 所示的界面中,“Files” 选 标签, 再选择 “C++ Source File” ,其界面与图 1-6 相似(仅 Add to projec 是暗淡的、无法选择), 后续操作则与前述相同。 最简单的做法是:直接使用工具栏上的新建文件按钮“ ”新建一空 白文件,紧接着单击工具栏上的保存按钮“ ”保存此空文件——注 意,保存时一定要以“.c”或“.cpp”作为扩展名,否则逻辑程序时 自动格式化和特殊显示等很多特性将无法使用,程序无法被运行。 这种方式新建的 C 源程序文件在编译时,会提示用户,要求允许系 统为其创新一个默认的工程(含相应的工作区)。

1.6 编译、链接而后运行程序
程序编制完成(即所谓 “四步曲” 中第一步的编辑工作得以完成)之后, 就可以进行后三步的编译、 链接与运行了。 所有后三步的命令项都处 在菜单 Build 之中。注意,在对程序进行编译、链接和运行前,最好 先保存自己的工程(使用“File→Save All”菜单项)以避免程序运行时 系统发生意外而使自己之前的工作付之东流, 应让这种做法成为自己 的习惯、素质。 首先选择执行菜单第一项 Compile,此时将对程序进行编译。若编译 中发现错误(error)或警告(warning),将在 Output 窗口中显示出它们 所在的行以及具体的出错或警告信息, 可以通过这些信息的提示来纠

13

正程序中的错误或警告(注意,错误是必须纠正的,否则无法进行下 一步的链接;而警告则不然,它并不影响进行下一步,当然最好还是 能把所有的警告也“消灭”掉)。当没有错误与警告出现时,Output 窗口所显示的最后一行应该是: “Hello.obj-0 error(s), 0warning(s)” 。

图1-8 程序Hello.cpp的运行结果界面 编译通过后, 可以选择菜单的第二项 Build 来进行链接生成可执行程 序。在链接中出现的错误也将显示到 Output 窗口中。链接成功后, Output 窗口所显示的最后一行应该是: “Sample.exe-0 error(s), 0 warning(s)” 。最后就可以运行(执行)我们所编制的程序了,选择 Execute 项(该选项前有一个深色的感叹号标志 ” 实际上也可通过 “!, 单击窗口上部工具栏中的深色感叹号标志“! ”来启动执行该选项), VC6 将运行已经编好的程序,执行后将出现一个结果界面(所谓的类 似于 DOS 窗口的界面),如图 1-8 所示,其中的“press any key to continue”是由系统产生的,使得用户可以浏览输出结果,直到按下 了任一个键盘按键时为止(那时又将返回到集成界面的编辑窗口处)。
14

至此我们已经生成并运行(执行)了一个完整的程序,完成了一个“回 合”的编程任务。此时应执行“File→Close Workspace”菜单项,待 系统询问是否关闭所有的相关窗口时,回答“是” ,则结束了一个程 序从输入到执行的全过程, 回到了刚刚启动 VC6 的那一个初始画面。

1.7 及时备份自己的创作
(1) 完 全 备 份 。 对 于 刚 才 工 作 的 工 程 Sample 而 言 , 只 需 将 D:\myData\VC6 下的文件夹 Sample 复制到 U 盘或打包成一个文件后 放到自己的邮箱。 需要在其它计算机上继续完成该工程时, 将该文件 夹 复 制 到 该 计 算 机 的 硬 盘 上 , 进 入 VC6 , 通 过 “ File → Open Workspace”菜单项将该工程打开即可。 (2)只备份 C 源程序文件。对于刚才工作的工程 Sample 而言,工程非 常简单,没有什么专门的设置,因此,仅备份其中的 C 源程序 Hello.cpp 就足矣。需要在其它计算机上继续完成该程序时,只需将 备份的程序复制到该计算机的硬盘上,进入 VC6,根据前面的讲述, 新建一 Win32 Console Application(做到图 1-5 所示的界面),然后通 过“Project→Add to Project→Files”菜单项将 Hello.cpp 添加新建的 工程中。 最简单的做法是:直接使用工具栏上的文件打开按钮“ Hello.cpp。 ”打开

1.8 将自己设计的产品提供给他人使用
需要将自己设计的产品提供给他人使用时, 针对前述的 Sample 工程, 只需将链接产生的可执行文件 Sample.exe 复制/发送给他人即可,不
15

能复制整个工程文件夹或复制.cpp 文件,这是因为: (1)复制可执行文件已足够。 (2)复制整个工程文件夹或复制.cpp 文件,等于提供了自己的详细设 计,在商业上一般是不这样做了,除非事先双方谈妥需要这样做或对 方愿意出高价购买你的详细设计。

图1-9 选择生成什么类型的可执行程序 另外,应当说明的是:前面所说的编译、链接过程都是 Debug 类型 的,也就是说,当 VC6 在进行这些工作时将加入一些调试信息,致 使编译链接后生成的代码很庞大, 效率也降低。如果确信你的程序已 经完美无缺或者是要正式发布,就应该选择菜单 Build 中的 Batch Build 项,产生如图 1-9 所示的对话框,其中的两个选项分别代表编 译的代码形式。如果选择第一项 Release,那么生成的就是最终代码, 其运行效率会增高。 选择 Sample-Win32 Release 项,再进行 Build 或 Rebuild All 就会在工 程所在的目录下产生一个新的目录 release,在 release 目录下生成的 可执行程序代码规模小,执行效率高,是我们最后的产品。

16

2

VC6集成开发环境使用参考 2.1 VC6的常用菜单命令项
(1)File菜单

New:打开“new”对话框,以便创建新的文件、工程或工作区。 Close Workspace:关闭与工作区相关的所有窗口。 Exit:退出 VC6 环境,将提示保存窗口内容等。

(2)Edit菜单
Cut:快捷键 Ctrl+X。将选定内容复制到剪贴板,然后再从当前活动 窗口中删除所选内容。与“Paste”联合使用可以移动选定的内容。 Copy:快捷键 Ctrl+C。将选定内容复制到剪贴板,但不从当前活动 窗口中删除所选内容。与“Paste”联合使用可以复制选定的内容。 Paste:快捷键 Ctrl+V。将剪贴板中的内容插入(粘贴)到当前鼠标指针 所在的位置。注意,必须先使用 Cut 或 Copy 使剪贴板中具有准备粘 贴的内容。 Find:快捷键 Ctrl+F。在当前文件中查找指定的字符串。顺便指出, 可按快捷键 F3 寻找下一个匹配的字符串。 Find in Files:在指定的多个文件中查找指定的字符串。 Replace:快捷键 Ctrl+H。替换指定的字符串(用某一个串替换另一个 串)。 Go To: 快捷键 Ctrl+G。将光标移到指定行上。 Breakpoints:快捷键 Alt+F9。弹出对话框,用于设置、删除或查看 程序中的所有断点。 断点将告诉调试器应该在何时何地暂停程序的执 行,以便查看当时的变量取值等现场情况。
17

(3)View菜单
Workspace:如果工作区窗口没显示出来,选择执行该项后将显示出 工作区窗口。 Output:如果输出窗口没显示出来,选择执行该项后将显示出输出窗 口。输出窗口中将随时显示有关的提示信息或出错警告信息等。 (4)Project菜单 Add To Project:选择该项将弹出子菜单,用于添加文件或数据链接 等到工程之中去。 例如子菜单中的 New 选项可用于添加 “C++ Source File”或“C/C++ Header File” ;而子菜单中的 Files 选项则用于插入 已有的文件到工程中。 Settings:为工程进行各种不同的设置。当选择其中的“Debug”标签 (选项卡),并通过在“Program arguments: ”文本框中填入以空格分 割的各命令行参数后, 则可以为带参数的 main 函数提供相应参数(呼 应于“void main(int argc, char* argv[ ]){?}”形式的 main 函数中所 需各 argv 数组的各字符串参数值)。注意,在执行带参数的 main 函 数之前,必须进行该设置,当“Program arguments: ”文本框中为空 时,意味着无命令行参数。 (5)Build菜单 Compile:快捷键 Ctrl+F7。编译当前处于源代码窗口中的源程序文 件, 以便检查是否有语法错误或警告, 如果有的话, 将显示在 Output 输出窗口中。 Build:快捷键 F7。对当前工程中的有关文件进行连接,若出现错误 的话,也将显示在 Output 输出窗口中。
18

Execute:快捷键 Ctrl+F5。运行(执行)已经编译、连接成功的可执行 程序(文件)。 Start Debug:选择该项将弹出子菜单,其中含有用于启动调试器运 行的几个选项。例如其中的 Go 选项用于从当前语句开始执行程序, 直到遇到断点或遇到程序结束;Step Into 选项开始单步执行程序,并 在遇到函数调用时进入函数内部再从头单步执行; Run to Cursor 选项 使程序运行到当前鼠标光标所在行时暂停其执行(注意,使用该选项 前,要先将鼠标光标设置到某一个你希望暂停的程序行处)。执行该 菜单的选择项后,就启动了调试器,此时菜单栏中将出现 Debug 菜 单(而取代了 Build 菜单)。 (6)Debug菜单 启动调试器后才出现该 Debug 菜单(而不再出现 Build 菜单)。 Go:快捷键 F5。从当前语句启动继续运行程序,直到遇到断点或遇 到程序结束而停止(与 Build→Start Debug→Go 选项的功能相同)。 Restart:快捷键 Ctrl+Shift+F5。重新从头开始对程序进行调试执行 (当对程序做过某些修改后往往需要这样做!)。选择该项后,系统将 重新装载程序到内存,并放弃所有变量的当前值(而重新开始)。 Stop Debugging:快捷键 Shift+F5。中断当前的调试过程并返回正常 的编辑状态(注意, 系统将自动关闭调试器, 并重新使用 Build 菜单来 取代 Debug 菜单)。 Step Into:快捷键 F11。单步执行程序,并在遇到函数调用语句时, 进入那一函数内部, 并从头单步执行(与 Build→Start Debug→Step Into
19

选项的功能相同)。 Step Over: 快捷键 F10。 单步执行程序, 但当执行到函数调用语句时, 不进入那一函数内部,而是一步直接执行完该函数后,接着再执行函 数调用语句后面的语句。 Step Out:快捷键 Shift+F11。与“Step Into”配合使用,当执行进入 到函数内部,单步执行若干步之后,若发现不再需要进行单步调试的 话,通过该选项可以从函数内部返回(到函数调用语句的下一语句处 停止)。 Run to Cursor:快捷键 Ctrl+F10。使程序运行到当前鼠标光标所在 行时暂停其执行(注意,使用该选项前,要先将鼠标光标设置到某一 个你希望暂停的程序行处)。事实上,相当于设置了一个临时断点, 与 Build→Start Debug→Run to Cursor 选项的功能相同。 Insert/Remove Breakpoint:快捷键 F9。本菜单项并未出现在 Debug 菜单上(在工具栏和程序文档的上下文关联菜单上),列在此处是为了 方便大家掌握程序调试的手段, 其功能是设置或取消固定断点——程 序行前有一个圆形的黑点标志, 表示已经该行设置了固定断点。 另外, 与固定断点相关的还有 Alt+F9(管理程序中的所有断点)、Ctrl+F9(禁 用/使能当前断点)。 (7)Help菜单 通过该菜单来查看 VC6 的各种联机帮助信息。 (8)上下文关联菜单 除了主菜单和工具栏外,VC6 开发环境还提供了大量的上下文关联

20

菜单, 用鼠标右键的单击窗口中很多地方都会弹出一个关联菜单, 里 面包含有与被单击项目相关的各种命令, 建议大家在工作时可以试着 多点点鼠标右键, 说不定会发现很多有用的命令, 从而大大加快一些 常规操作的速度。 2.2 VC6的主要工作窗口 (1)Workspace窗口 Workspace 窗口显示了当前工作区中各个工程的类、资源和文件信 息, 当新建或打开一个工作区后, Workspace 窗口通常就会出现三个 树视图: ClassView(类视图)、 ResourceView(资源视图)和 FileView(文 件视图),如果在 VC6 企业版中打开了数据库工程,还会出现第四个 视图 DataView(数据视图)。如同前面所述,在 Workspace 窗口的各个 视图内单击鼠标右键可以得到很多有用的关联菜单。 ClassView 显示当前工作区中所有工程定义的 C++类、全局函数和全 局变量, 展开每一个类后, 可以看到该类的所有成员函数和成员变量, 如果双击类的名字, VC6 会自动打开定义这个类的文件, 并把文档窗 口定位到该类的定义处,如果双击类的成员或者全局函数及变量,文 档窗口则会定位到相应函数或变量的定义处。 ResourceView 显示每个工程中定义的各种资源,包括快捷键、位图、 对话框、图标、菜单、字符串资源、工具栏和版本信息,如果双击一 个资源项目,VC6 就会进入资源编辑状态,打开相应的资源,并根据 资源的类型自动显示出 Graphics、Color、Dialog、Controls 等停靠式 窗口。

21

FileView 显示了隶属于每个工程的所有文件。除了 C/C++源文件、 头文件和资源文件外, 我们还可以向工程中添加其它类型的文件, 例 如 Readme.txt 等, 这些文件对工程的编译连接不是必需的, 但将来制 作安装程序时会被一起打包。 同样, FileView 中双击源程序等文本 在 文件时,VC6 会自动为该文件打开一个文档窗口,双击资源文件时, VC6 也会自动打开其中包含的资源。 在 FileView 中对着一个工程单击鼠标右键后,关联菜单中有一个 “Clean”命令,在此特地要解释一下它的功能:VC6 在建立(Build) 一个工程时,会自动生成很多中间文件,例如预编译头文件、程序数 据库文件等,这些中间文件加起来的大小往往有数兆,很多人在开发 一个软件期间会使用办公室或家里的数台机器, 如果不把这些中间文 件删除,在多台机器之间使用软盘拷贝工程就很麻烦。 “Clean”命令 的功能就是把 VC6 生成的中间文件全部删除,避免了手工删除时可 能会出现误删或漏删的问题。另外,在某些情况下,VC6 编译器可 能无法正确识别哪些文件已被编译过了, 以致于在每次建立工程时都 进行完全重建,很浪费时间,此时使用“Clean”命令删除掉中间文 件就可以解决这一问题。 应当指出,承载一个工程的还是存储在工作文件夹下的多个文件(物 理上),在 Workspace 窗口中的这些视图都是逻辑意义上的,它们只 是从不同的角度去自动统计总结了工程的信息, 以方便和帮助我们查 看工程、更有效地开展工作。如果开始时你不习惯且工程很简单(学 习期间很多时候都只有一个.cpp 文件),则你完全没有必要去搭理这
22

些视图,只需要在.cpp 文件内容窗口中工作。 (2)Output窗口 与 Workspace 窗口一样,Output 窗口也被分成了数栏,其中前面 4 栏 最常用。在建立工程时,Build 栏将显示工程在建立过程中经过的每 一个步骤及相应信息, 如果出现编译连接错误, 那么发生错误的文件 及行号、错误类型编号和描述都会显示在 Build 栏中,用鼠标双击一 条编译错误,VC6 就会打开相应的文件,并自动定位到发生错误的 那一条语句。 工程通过编译连接后,运行其调试版本,Debug 栏中会显示出各种调 试信息,包括 DLL 装载情况、运行时警告及错误信息、MFC 类库或 程序输出的调试信息、进程中止代码等。 两个 Find in Files 栏用于显示从多个文件中查找字符串后的结果,当 你想看看某个函数或变量出现在哪些文件中,可以从“Edit”菜单中 选择“Find in Files?”命令,然后指定要查找的字符串、文件类型及 路径,按“查找”后结果就会输出在 Output 的 Find in Files 栏中。 (3)窗口布局调整 VC6 的智能化界面允许用户灵活配置窗口布局,例如菜单和工具栏 的位置都可以重新定位。 让我们在菜单或工具栏左方类似于把手的两 个竖条纹处或其它空白处点击鼠标左键并按住, 然后试试把它拖动到 窗口的不同地方,就可以发现菜单和工具栏能够停靠在窗口的上方、 左方和下方,双击竖条纹后,它们还能以独立子窗口的形式出现,独 立子窗口能够始终浮动在文档窗口的上方,并且可以被拖到 VC6 主
23

窗口之外,如果有双显示器,甚至可以把这些子窗口拖到另外一个显 示器上,以便进一步加大编辑区域的面积。Workspace 和 Output 等 停靠式窗口(Docking View)也能以相同的方式进行拖动,或者切换成 独立的子窗口, 此外, 这些停靠式窗口还可以切换成普通的文档窗口 模式,不过文档窗口不能被拖出 VC6 的主窗口,切换的方法是选中 某个停靠式窗口后,在“Windows”菜单中把“Docking View”置于 非选中状态。

3

严谨思维,调试程序 3.1 什么时候需要对程序进行调试

当程序编译出错或者链接出错时,系统都将在 Output 输出窗口中随 时显示出有关的提示信息或出错警告信息等(如果是编译出错,只要 双击 Output 窗口中的出错信息就可以自动跳到出错的程序行,以便 仔细查找)。但若编译和链接都正确,而执行结果又总是不正确时, 这时就需要使用调试工具来帮着 “侦察” 出程序中隐藏着的出错位置 (某种逻辑错误)。 强调:初学者常犯的错误是认为“编译和链接”都正确,程序就应该 没有问题,怎么会结果不对呢?“编译和链接”都正确,只能说明程 序没有语法和拼写上的错误,但在算法(逻辑)上有没有错,还得看结 果对不对。反过来讲,无论让你设计一个什么样的程序,你都只写以 下几行,则“编译和链接”肯定都正确,但能实现设计的要求吗? #include <stdio.h> void main() { printf("Hello World!\n"); }
24

事实上, 程序设计的重点完全不是修正编译和链接过程中的错误—— 相对而言,这种工作基本没有技术含量,程序设计的主要工作是设计 正确的算法。

3.2 对程序进行调试的基本手段和方法 (1)设置固定断点或临时断点
所谓断点,是指定程序中的某一行,让程序运行至该行后暂停运行, 使得程序员可以观察分析程序的运行过程中的情况。 这些情况一般包 括: ①在变量窗口(Varibles)中观察程序中变量的当前值。 程序员观察这些 值的目的是与预期值对比,若与预期值不一致,则此断点前运行的程 序肯定在某个地方有问题,以此可缩小故障范围。例如以下程序是计 算 cos(x)并显示, 运行时发现无论 x 输入为多少, 结果都是 0.046414。 #include <stdio.h> #include <math.h> void main() { int x; printf("Please input x:"); scanf("% d", &x); printf("cos(x)=%f\n", cos(x));

}

在该程序中, 若你没有看到问题——程序较长、 较复杂时很难看出问 题所在,则应该使用调试手段定位故障位置。 ②在监控窗口(Watch)中观察指定变量或表达式的值。当变量较多时, 使用 Varibles 窗口可能不太方便,使用 Watch 窗口则可以有目的、有 计划地观察关键变量的变化。 ③在输出窗口中观察程序当前的输出与预期是否一致。同样地,若不
25

一致,则此断点前运行的程序肯定在某个地方有问题。 ④在内存窗口(Memory)中观察内存中数据的变化。 在该窗口中能直接 查询和修改任意地址的数据。对初学者来说,通过它能更深刻地理解 各种变量、数组和结构等是如何占用内存的,以及数组越界的过程。 ⑤在调用堆栈窗口(Call Stack)中观察函数调用的嵌套情况。 此窗口在 函数调用关系比较复杂或递归调用的情况下,对分析故障很有帮助。 (2)单步执行程序 让程序被一步一步(行)地执行,观察分析执行过程是否符合预要求。 例如,以下程序预期的功能是从键盘上读入两个数(x 和 y),判断 x 和 y 是否相等,相等则在屏幕上显示 x=y,不相等则显示 x<>y。这 是要求实现的功能,但程序实际的运行状况却是:无论输入什么,都 会在屏幕上显示 x=y 和 x<>y,程序肯定有问题,但表面上看却可能 找不到问题所在,使用单步执行,则能定位故障点,缩小看的范围。 例如,在单步执行的过程中,若输入“2,3” ,发现 x 和 y 的值的确变 成了 2 和 3,此时按道理不应执行“printf("x=y\n");” ,但单步跟踪却 发现被执行了,因此多半问题出在“if (x = y)” 。 #include <stdio.h> void main() { int x, y; printf("Please input x, y:"); scanf("%d,%d", &x, &y); if (x = y) { printf("x=y\n"); } else; { printf("x<>y\n"); }
26

} 在单步执行的过程中,应灵活应用 Step Over、Step Into、Step Out、 Run to Cursor 等方法,提高调试效率。建议在程序调试过程中,记住 并使用“Step Over、Step Into、Step Out、Run to Cursor”等菜单项 的快捷键, 开始时可能较生疏、 操作较慢, 但坚持一段时间就能生巧、 效率提高。 (3)使用断言 断言是对某种假设条件进行检查(可理解为若条件成立则无动作,否 则应报告),它可以快速发现并定位软件问题,同时对系统错误进行 自动报警。 断言可以对在系统中隐藏很深, 用其它手段极难发现的问 题进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际 应用时,可根据具体情况灵活地设计断言。 使用断言时,必须在程序的开头加上: #include <assert.h> ①可用断言来确认函数的参数。 示例: 假设某函数参数中有一个指针, 那么使用指针前可对它检查, 以防止其他人调用本函数时使用空指针 作参数。代码如下: int exam_fun( unsigned char *str ) { assert(str != NULL); // 断言“指针不为空” ,若“空” (断言不成立)则报错 ... //other program code } ②可用断言来确认是否发生了不该发生的情况。示例: 以下程序段运 行结果有错,检查起来很困难而且搞了很久都不知是什么地方有问 题。因此,建议分析程序的正常运行情况应该是什么,运行过程中是 否出了异常,针对所有(或关键状态)应当正常的情况,使用断言,就
27

很有可能发现异常原因,且调试效率很高。针对该程序段,我们断言 (断定)变量 i 的取值应该为“i>=0 && i<SIZE”且较关键,但在运行 过程中是否有可能被无意修改(例如其它变量越界)而超出范围呢,就 可使用断言检查是否发生了这样的情况。 for (i=0; i<SIZE; i++) { ... //other program code assert(i>=0 && i<SIZE); // 断言“i的正常取值范围” , 若断言不成立则报错 array[i] = i; ... //other program code } 断言不成立时(一出现异常),系统将立即报错,此时可进入程序调试 状态,检查程序的运行情况。 3.3 对一个简单程序的调试过程 假设准备编制进行如下计算任务的一个简单程序:在已知 x=3、y=5 的情况下,先计算出 x 与 y 的和 s,差 d,商 q,模 r,而后计算 res=s+2d+3q+4r 的值(res 应该等于 16)并显示在屏幕上。但编制的如 下程序运行后却得出了一个错误结果“res=26” 。 #include <stdio.h> void main() { int x=3, y=5; int s, d, q, r, res; s = x + y; d = s - y; q = x / y; r = x % y; res = s + 2*d + 3*q + 4*r; printf("res=%d\n", res);

}

28

图3-1 程序dbgTest.cpp的跟踪调试 分析上述所编制的程序行,假设能在要输出 res 结果值的那一程序行 (倒数第二行)处设置一个临时断点, 让程序先执行到此断点处(注意设 为断点的那一行尚未被执行!),看一看那时各变量的动态取值情况, 有可能就会找到出错的原因!基于上述分析,先将鼠标光标移动到 “printf("res=%d\n", res);” 那一行处(左键单击那一行任意位置), 从而 指定了临时性断点的行位置,而后执行“Build→Start Debug→Run to Cursor”选项,使程序运行到所指定行时暂停其执行,并显示出如图 3-1 的界面,其中的左下方窗口中就列出了当时各变量的取值情况: 和 s=8,差 d=3(x=3,y=5,它们的差 d=3 肯定是错误的!),商 q=0, 模 r=3,最终结果 res=26。再仔细查看程序中负责计算差 d 的那一个 语句“d=s-y;”就会恍然大悟,原来将“x-y”误写成了“s-y” !找到 了错误,此时可以通过菜单选项“Debug→Stop Debugging” ,中断当
29

前的调试过程并返回正常的编辑状态,修改所发现的错误后,再一次 执行将能得出正确结果“res=16” 。 顺便指出,图 3-1 中显示的变量是“自动查看”方式的,即 VC6 自 动显示当前运行上下文中的变量的值。如果变量比较多,自动显示的 窗口比较混乱, 则可以在 Watch 列表中添加自己想要监控的变量名。 上述设置临时断点(到鼠标光标那一行处)的调试手段使用起来很方 便,会经常使用(也经常在到达一个断点后,又设置另一个新的临时 断点)。 另外也常配合使用 “单步执行” 的方式, 来仔细检查每一步(一 个程序行)执行后各变量取值的动态变化情况,如,先通过“Run to Cursor”执行到某一个鼠标光标临时断点行处,而后通过使用 Debug 菜单的“Step Over”或“Step Into”来进行所谓的“单步执行” ,当然, 每执行一步后, 都要仔细观察并分析系统自动给出的各变量取值的动 态变化情况,以便及时发现异常而找到出错原因。 3.4 设计合适的程序调试方案 让我们来分析并设计对如下程序进行调试的具体方法与手段(实际 上, 对不同的程序, 都需要在分析其执行结果以及其程序编写结构的 基础上, 来设计相应的对其进行具体调试的方法与手段, 宗旨是想方 设法逐步缩小“侦察”范围,直到最后找到出错位置)。 该程序除 main 外,还有一个自定义函数 f。若已经能确认调用 f 函数 前计算出的 res 值(或 s、d、q 或 r 其中之一的结果值)不正确的话,则 可像上一程序那样, 在计算出 res 变量值的下一行(或在靠前一些的某 一行)处设置断点,看到达那一断点处是否一切正常。若到达断点处
30

的数据结果已经不正常的话,错误已经出现(出现在跟前或出现在前 面,从而找到了错误或者缩小了“侦察”范围);若断点处仍然正常, 可断言错误出现在后面,而后,一:可又一次通过鼠标光标往更靠后 一些的适当位置设置新断点,再一次“Debug→Run to Cursor”(一 下向后“迈”过了许多行,再继续“侦察” !);二:通过“单步执行” (Debug→StepOver),在重点怀疑的那一块地方仔细地逐行进行“侦 察” 。 注意, “Step Over”不会“跟踪”进入 f 函数内部,若怀疑 f 函数可 能有问题的话,要通过使用“Debug→Step Into”进入 f 内部再进行 细致调试(在不遇到函数调用的地方, “Step Over”与“Step Into”的 功能是相同的。若通过“Step Into”进入到函数内部,单步执行若干 步之后,若发现不再需要进行单步调试的话,可通过“Step Out”从 函数内部返回到调用语句的下一语句处)。 作为练习, 请读者利用这一程序对上述的调试方法与手段进行多方面 的灵活使用与体验!可以看出,程序调试是一件很费时费力而又非常 细致的工作,需要耐心,要通过不断的实践来总结与积累调试经验。 至于 VC6 提供的其他调试方法与手段,这儿就不一一介绍了。 #include <stdio.h> int f(int a) { int b, c; b = a + 5; c = 2*b + 100; return c;

}

void main() {
31

int x=3, y=5; int s, d, q, r, res, z; s = x + y; d = x - y; q = x / y; r = x % y; res = s + 2*d + 3*q + 4*r; printf("res=%d\n", res); z = f(36); printf("z=%d\n", z);

}

前面也提到过,通过“Run to Cursor”所设置并到达的断点是一个 临时性的断点。实际上,VC6 还提供设置与清除固定性断点的方法。 设置固定性断点最简单的方法是:在某一程序行处,单击鼠标右键, 在菜单中选择 “Insert/Remove Breakpoint” 项(通过左键单击该选项, 此时该行前将出现一个圆形的黑点标志, 意味着已经将该行设置成了 固定断点)。 清除固定性断点的方法为: 在具有圆形黑点标志的固定断点行处, 单 击鼠标右键,在菜单中选择“Remove Breakpoint”项(通过左键单击 该选项,此时该行前的那一个圆形黑点标志将消失,意味着已经清除 了该固定断点)。 设置了固定性断点后, 通常通过 “Build→Start Debug→Go” “Debug 或 →Go”选项使程序开始执行,直到遇到某断点或遇到程序结束而停 止。 还要说明的是, 可以随时设置任意多个固定性断点, 也可以随时清除 它们。通过使用菜单选项“Edit→Breakpoints” ,会出现一个对话框, 在其中的“Break at”文本框中键入要设置断点的程序行的行数信息 (但通常是先通过鼠标光标选定某一程序行,再利用菜单选项进入上

32

述对话框,而后通过点击“Break at”文本框右边的小三角按钮,并 选定系统自动提供的程序行的行数, 以免自己要真正地去数清楚那一 行的行数),也能够在指定行处设置一个固定性断点(通过 OK 按钮确 定);如果要清除某断点,可在“Breakpoints”列表栏中先选定它, 之后单击 Remove 按钮。实际上,除位置断点外,通过“Edit→ Breakpoints” ,还可以设置数据断点,消息断点,以及条件断点等, 这儿就不再细说了。 VC6 是一个极为庞大的开发工具, 我们所介绍的仅仅是一些基本的应 用,使用这些应用已经可以完成书中所涉及到的例子和作业,有兴趣 的读者可通过参看其他有关介绍 VC6 的资料或书籍来进行进一步的 学习与提高。 3.5 优秀程序员的基本素质——丰富的想象、严谨的思维 (1)程序运行结果看起来对了,但并不意味着程序没有隐藏的问 题 ①以下程序是从键盘输入一个数(x,x 是一个 int 型整数),计算 y(y=1000x+9)并在屏幕上输出,程序基本上是对的,能输出正确的结 果。 #include <stdio.h> void main() { int x, y; printf("Please input x:"); scanf("%d", &x); y = 1000*x + 9; printf("y=%d\n", y);

}

但是,当 x 输入为 5000000,屏幕上却输出 y=705032713,出现了错 误。
33

②以下程序的功能是从键盘上读入一串字符,然后在屏幕上输出。 #include <stdio.h> void main() { char str[10]; printf("Please input str:"); scanf("%s", &str); printf("str=%s\n", str);

}

若用户在输入 str 时不小心多按了(或无意碰触)几下键盘,则程序运 行会出错, 如图 3-2 所示——可能稍严重的是程序运行死机(不报错), 特别严重的是若有人精心设计输入的字符, 完全可能造成系统被入侵 或被严重破坏。

图3-2 程序运行过程中因用户的输入而出错
③以下程序的功能是从计算班中男生(boy)和女生(girl)的比例。 如果女

生数为 0 时,程序会怎样? #include <stdio.h> void main() { int boy, girl; printf("Please input boy,girl:"); scanf("%d,%d", &boy, &girl);
34

}

printf("boy/girl=%.2f\n", boy*1.0/girl);

实际工作中,类似的隐藏的问题往往是破坏力巨大的“地雷” ,往往 造成极大的损失,例如火箭发射、宇宙飞船飞行、高速列车运行中的 事故,我们平常接触最多的恐怕是微软的各种系统需要不断地打补 丁。因此,在程序设计中,必须缜密考虑各种情况,哪怕是机率极小 的意外。 (2)严谨思维的典范——程序员学习的榜样 丰富的想象力、严谨的思维是一个优秀的程序应当具备的素质。 设 计程序时不要拘泥于固定的思维方式, 遇到问题的时候要多想几种解 决问题的方案,并且考虑全面、思维严谨。 以下 2 个小故事, 应当是一个优秀程序员的标准思维, 它形象、 幽默、 充分地展示了一个优秀程序员的严谨、全面的思维。一个优秀的程序 员只有这样思考并设计程序, 才能保证程序始终能可靠、 稳定地工作, 减少和避免发生事故。 ①方程仅仅对于正实数的简单情形成立 物理教授走过校园,遇到数学教授。 物理教授在进行一项实 验,他总结出一个经验方程,似乎与实验数据吻合,他请数学教 授看一看这个方程。 一周后他们碰头,数学教授说这个方程不成 立。可那时物理教授已经用他的方程预言出进一步的实验结果, 而且效果颇佳,所以他请数学教授再审查一下这个方程。 又是一 周过去,他们再次碰头。数学教授告诉物理教授说这个方程的确 成立, "但仅仅对于正实数的简单情形成立。" ②判断开枪后树上还有几只鸟 某日, 老师在课堂上想看看一学生智商有没有问题, 问他 “树 上有十只鸟,开枪打死一只,还剩几只?” 他反问“是无声手枪或别的无声的枪吗?”(例如激光枪) “不是。 ” “枪声有多大?” “80-100分贝。 ”
35

“那就是说会震的耳朵疼?” “是。 ” “在这个城市里打鸟犯不犯法?” “不犯。 ” “您确定那只鸟真的被打死啦?” “确定。 偶已经不耐烦了 ” “拜托, 你告诉我还剩几只就行了, OK” “OK,树上的鸟里有没有聋子?” “没有。 ” “有没有关在笼子里的?” “没有。 ” “边上还有没有其他的树,树上还有没有其他鸟?” “没有。 ” “有没有残疾的或饿的飞不动的鸟?” “没有。 ” “算不算怀孕肚子里的小鸟?” “不算。 ” “打鸟的人眼有没有花?保证是十只?” “没有花,就十只。 偶已经满脑门是汗,且下课铃响,但 ” 他继续问 “有没有傻的不怕死的?” “都怕死。 ” “会不会一枪打死两只?” “不会。 ” “所有的鸟都可以自由活动吗?” “完全可以。 ” “如果您的回答没有骗人, ”学生满怀信心的说, “打死的鸟 要是挂在树上没掉下来,那么就剩一只,如果掉下来,就一只不 剩。 ” 老师当即晕倒。 4 编译与链接过程中常见的出错提示

编译、链接过程中,主要由于初学和录入阶段的击键失误,VC 经常 会提示程序有错(语法和拼写问题,肯定不会指明算法有问题,否则 就不用编程了)。遇到这些英文的提示时,不少同学无从下手。一定 要克服畏难情绪和一看英文就怕的心理, 凭自己能考上大学的英语水 平,只要仔细、一个单词一个单词地看,这些英文、包括在线帮助中 的英文语句应基本上能看懂,个别单词实在不认识就查一查,做 IT
36

的哪能不学英语,这本身也是在日常生活中学习英语的机会。再者, 即便没有完全理解、似懂非懂,也没有很大关系,只要双击 Output 窗口中的出错信息就可以自动跳到出错的程序行, 仔细查看, 加上经 验的逐渐积累和人类举一反三、 触类旁通的自我学习进步能力, 解决 这些简单问题并非难事。 以下是一些常见的编译、 链接期间的程序出错英文提示及相应的中文 意思,供参考。 4.1 常见编译错误 (1)error C2001: newline in constant 编号:C2001 直译:在常量中出现了换行。 错误分析: ①字符串常量、字符常量中是否有换行。 ②在这句语句中,某个字符串常量的尾部是否漏掉了双引号。 ③在这语句中,某个字符创常量中是否出现了双引号字符“"” ,但是 没有使用转义符“\"” 。 ④在这句语句中,某个字符常量的尾部是否漏掉了单引号。 ⑤是否在某句语句的尾部, 或语句的中间误输入了一个单引号或双引 号。 (2)error C2015: too many characters in constant 编号:C2015 直译:字符常量中的字符太多了。 错误分析:
37

单引号表示字符型常量。一般的,单引号中必须有且只能有一个字符 (使用转义符时,转义符所表示的字符当作一个字符看待),如果单引 号中的字符数多于 4 个,就会引发这个错误。 另外,如果语句中某个字符常量缺少右边的单引号,也会引发这个错 误,例如: if (x == 'x || x == 'y') { … } 值得注意的是,如果单引号中的字符数是 2-4 个,编译不报错,输出 结果是这几个字母的 ASC 码作为一个整数(int,4B)整体看待的数字。 (3)error C2137: empty character constant 编号:C2137 直译:空的字符定义。 错误分析: 原因是连用了两个单引号,而中间没有任何字符,这是不允许的。 (4)error C2018: unknown character '0x##' 编号:C2018 直译:未知字符‘0x##’ 。 错误分析: 0x##是字符 ASC 码的 16 进制表示法。这里说的未知字符,通常是指 全角符号、字母、数字,或者直接输入了汉字。如果全角字符和汉字 用双引号包含起来,则成为字符串常量的一部分,是不会引发这个错 误的。

38

(5)error C2041: illegal digit '#' for base '8' 编号:C2141 直译:在八进制中出现了非法的数字‘#’(这个数字#通常是 8 或者 9)。 错误分析: 如果某个数字常量以“0”开头(单纯的数字 0 除外),那么编译器会 认为这是一个 8 进制数字。例如: “089”“078”“093”都是非法的, 、 、 而“071”是合法的,等同于是进制中的“57” 。 (6)error C2065: 'xxxx' : undeclared identifier 编号:C2065 直译:标识符“xxxx”未定义。 错误分析: 首先, 解释一下什么是标识符。 标志符是程序中出现的除关键字之外 的词,通常由字母、数字和下划线组成,不能以数字开头,不能与关 键字重复,并且区分大小写。变量名、函数名、类名、常量名等等, 都是标志符。所有的标志符都必须先定义,后使用。标志符有很多种 用途,所以错误也有很多种原因。 ①如果“xxxx”是一个变量名,那么通常是程序员忘记了定义这个变 量,或者拼写错误、大小写错误所引起的,所以,首先检查变量名是 否正确。(关联:变量,变量定义) ②如果“xxxx”是一个函数名,那就怀疑函数名是否没有定义。可能 是拼写错误或大小写错误,当然,也有可能是你所调用的函数根本不

39

存在。还有一种可能,你写的函数在你调用所在的函数之后,而你有 没有在调用之前对函数原形进行申明。(关联:函数申明与定义,函 数原型) ③如果“xxxx”是一个库函数的函数名,比如“sqrt”“fabs” 、 ,那么 看看你在 cpp 文件已开始是否包含了这些库函数所在的头文件(.h 文 件)。例如,使用“sqrt”函数需要头文件 math.h。如果“xxxx”就是 “cin” “cout” 那么一般是没有包含 或 , “iostream.h” (关联: 。 #include, cin,cout) ④如果“xxxx”是一个类名,那么表示这个类没有定义,可能性依然 是:根本没有定义这个类,或者拼写错误,或者大小写错误,或者缺 少头文件,或者类的使用在申明之前。(关联:类,类定义) ⑤标志符遵循先申明后使用原则。 所以, 无论是变量、 函数名、 类名, 都必须先定义, 后使用。 如使用在前, 申明在后, 就会引发这个错误。 ⑥C++的作用域也会成为引发这个错误的陷阱。在花括号之内变量, 是不能在这个花括号之外使用的。类、函数、if、do(while)、for 所引 起的花括号都遵循这个规则。(关联:作用域) ⑦前面某句语句的错误也可能导致编译器误认为这一句有错。 如果你 前面的变量定义语句有错误, 编译器在后面的编译中会认为该变量从 来没有定义过,以致后面所有使用这个变量的语句都报这个错误。如 果函数申明语句有错误,那么将会引发同样的问题。 (7)error C2086: 'xxxx' : redefinition 编号:C2374
40

直译: “xxxx”重复申明。 错误分析: 变量“xxxx”在同一作用域中定义了多次。检查“xxxx”的每一次定 义,只保留一个,或者更改变量名。 (8)error C2374: initialization 编号:C2374 直译: “xxxx”重复申明,多次初始化。 错误分析: 变量“xxxx”在同一作用域中定义了多次,并且进行了多次初始化。 检查“xxxx”的每一次定义,只保留一个,或者更改变量名。 (9)C2143: syntax error : missing ';' before (identifier) 'xxxx' 编号:C2143 直译:在(标志符)“xxxx”前缺少分号。 错误分析: 这是 VC6 的编译期最常见的误报,当出现这个错误时,往往所指的 语句并没有错误,而是它的上一句语句发生了错误。其实,更合适的 做法是编译器报告在上一句语句的尾部缺少分号。 上一句语句的很多 种错误都会导致编译器报出这个错误: ①上一句语句的末尾真的缺少分号。那么补上就可以了。 ②上一句语句不完整,或者有明显的语法错误,或者根本不能算上一 句语句(有时候是无意中按到键盘所致)。
41

'xxxx'

:

redefinition;

multiple

③如果发现发生错误的语句是 cpp 文件的第一行语句, 在本文件中检 查没有错误, 但其使用双引号包含了某个头文件, 那么检查这个头文 件,在这个头文件的尾部可能有错误。 (10)error C4716: 'xxx' : must return a value 编号:C4716 直译: “xxx”必须返回一个值。 错误分析: 函数声明了有返回值(不为 void),但函数实现中忘记了 return 返回 值。要么函数确实没有返回值,则修改其返回值类型为 void,要么在 函数结束前返回合适的值。 (11) warning C4508: 'main' : function should return a value; 'void' return type assumed 编号:C4508 直译:main 函数应该返回一个值;void 返回值类型被假定。 错误分析: ①函数应该有返回值, 声明函数时应指明返回值的类型, 确实无返回 值的,应将函数返回值声明为 void。若未声明函数返回值的类型,则 系统默认为整型 int。此处的错误估计是在 main 函数中没有 return 返 回值语句,而 main 函数要么没有声明其返回值的类型,要么声明了。 ②warning 类型的错误为警告性质的错误,其意思是并不一定有错, 程序仍可以被成功编译、链接,但可能有问题、有风险。

42

(12)warning C4700: local variable 'xxx' used without having been initialized 编号:C4700 直译:警告局部变量“xxx”在使用前没有被初始化。 错误分析: 这是初学者常见的错误,例如以下程序段就会造成这样的警告,而且 程序的确有问题,应加以修改,尽管编译、链接可以成功——若不修 改,x 的值到底是多少无法确定,是随机的,判断其是否与 3 相同没 有意义,在运气不好的情况下,可能在调试程序的机器上运行时,结 果看起来是对的,但更换计算机后再运行,结果就不对,初学者往往 感到迷惑。 int x; if (x==3) printf("hello"); 4.2 常见链接错误 (1)error LNK2001: unresolved external symbol _main 编号:LNK2001 直译:未解决的外部符号:_main。 错误分析:缺少 main 函数。看看 main 的拼写或大小写是否正确。 (2)error LNK2005: _main already defined in xxxx.obj 编号:LNK2005 直译:_main 已经存在于 xxxx.obj 中了。 错误分析: 直接的原因是该程序中有多个(不止一个)main 函数。这是初学 C++ 的低年级同学在初次编程时经常犯的错误。 这个错误通常不是你在同
43

一个文件中包含有两个 main 函数,而是在一个 project(项目)中包含 了多个 cpp 文件,而每个 cpp 文件中都有一个 main 函数。引发这个 错误的过程一般是这样的:你写完成了一个 C++程序的调试,接着你 准备写第二个 C++文件, 于是你可能通过右上角的关闭按钮关闭了当 前的 cpp 文件字窗口(或者没有关闭,这一操作不影响最后的结果), 然后通过菜单或工具栏创建了一个新的 cpp 文件,在这个新窗口中, 程序编写完成,编译,然后就发生了以上的错误。原因是这样的:你 在创建第二个 cpp 文件时,没有关闭原来的项目,所以你无意中新的 cpp 文件加入你上一个程序所在的项目。切换到“File View”视图, 展开“Source Files”节点,你就会发现有两个文件。 在编写 C++程序时,一定要理解什么是 Workspace、什么是 Project。 每一个程序都是一个 Project(项目), 一个 Project 可以编译为一个应用 程序(*.exe),或者一个动态链接库(*.dll)。通常,每个 Project 下面可 以包含多个.cpp 文件,.h 文件,以及其他资源文件。在这些文件中, 只能有一个 main 函数。初学者在写简单程序时,一个 Project 中往往 只会有一个 cpp 文件。Workspace(工作区)是 Project 的集合。在调试 复杂的程序时,一个 Workspace 可能包含多个 Project,但对于初学者 的简单的程序,一个 Workspace 往往只包含一个 Project。 当完成一个程序以后,写另一个程序之前,一定要在“File”菜单中 选择“Close Workspace”项,已完全关闭前一个项目,才能进行下一 个项目。避免这个错误的另一个方法是每次写完一个 C++程序,都把 VC6 彻底关掉,然后重写打开 VC6,写下一个程序。
44

45


相关文档

更多相关文档

C语言上机软件VC++6.0中文版安装,学习Visual C++ 6.0编程环境的使用
C语言复习和VC++6.0开发环境
C语言上机软件VC++6.0中文版安装,学习Visual_C++_6.0编程环境的使用[1]
vc++6.0入门教程(PDF编辑版)
VC++6.0上机指导——C语言实验讲义
电脑版