第2章VC编程环境简介.pdf
第二章 VC 编程环境简介 第二章 VC 编程环境简介 2.1 Visual C+6.0 的开发环境 UG 的二次开发环境可以直接在 Visual C+6.0 下进行,由此可充分利用 Visual C+6.0提供的编辑功能。本章简单介绍 Visual C+6.0 的编程环境。2.1.1 VC+6.0 简介 Visual C+6.0(以下简称 VC6)包括了如下几个主要的部件:?编辑器(Editor):用来输入、浏览以及修改 C+源代码;?编译器(Compilor):用来将 C+源代码编译成目标代码;?链接程序(Linker):用来链接目标代码和库模块以生成可执行文件;?库:提供一些预先编译好的模块,可以被包含进编写的程序中。Microsoft 基础类库(MFC)是最重要的库,可以用它来编写运行在 Microsoft Windows 下的应用程序。另外,标准 C+库支持输入/输出以及 C+语言的其他一些标准特征。当然,微软开发者库(MSDN)也是使用 VC6 编程时不可缺少的助手。MSDN 是单独安装的,并且微软会定期进行更新以更好的支持程序员。建议本书的读者也安装 MSDN。VC6 的用户界面包括如下几个部分,如图 2-1 所示。菜单区 工具栏 编辑窗口 输出窗口 项目工作区 图 2-1 VC6 界面布局示意图?菜单区(Menu):与一般的应用程序一样,菜单区显示在最上方,所有系统提供的功能都包括在各项菜单中;?工具栏区(ToolBar):工具栏位于菜单区的正下方,常用的操作工具栏都缺省出现,用户可以通过在工具栏区的右键菜单来定制工具栏;?项目工作区(Project WorkSpace):显示在屏幕的左边,用来管理程序员生成的源文件和各种类(Class)及其方法等。其中包含了两个选项卡片:类视图(ClassView)和文件视图(FileView);?编辑窗口(Editor):编辑窗口显示在项目工作区的中间较大区域。可以用来显示和编辑源代码;?输出窗口(Output):输出窗口显示在屏幕的正下方。它显示一些有关发出的命令的进展信息、错误信息和结果的摘要等。输出窗口也被分成了若干选项卡,包括:编译链接(Build)、排错(Debug)、查找结果(Find in Files)、结果(Results)等。2.1.2 VC6 项目的建立 在 VC6 中,以项目(Project)的形式来组织源代码和文件,VC6 可以建立 15 种类型的项目。包括应用程序、动态链接库、各种控件等。与 UG 二次开发相关的项目类型有:?MFC AppWizard(dll):MFC 支持的动态链接库。本质上是一个动态链接库,但是编程时可以使用许多 MFC 支持的各种资源和高级功能。在 UG NX 二次开发中,若要使用 MFC 的一些高级功能,则需要建立此种类型的项目;?Win32 Console Application:Win32 控制台应用程序,以 main 函数作为软件执行的入口点。在编写 UG NX 外部程序时会使用此此类项目;?Win32 Dynamic-link Library:Win32 动态链接库。与静态库不同,动态链接库只有在其中的功能函数被调用时才会被加载到内存中。在编写 UG NX 内部程序时会使用此类项目。在 VC6 编程中,可以将多个项目组织成一个工作空间(WorkSpace)。在编写大型复杂软件时,以工作空间的形式来组织会更加方便。若单独建立一个项目,则 VC6 会缺省创建一个同名的工作空间。项目的扩展名为*.dsp,工作空间的扩展名为*.dsw。启动 VC6 后,新建项目时,选择菜单【File】【New】,选择【Projects】选项卡,在其中选择合适的项目类型,输入项目的基本信息,点击【OK】即可。2.1.3 VC6 项目环境的设置 在建立项目之后,还不能直接开始编写和调试程序,首先要对项目的环境进行一些基本设置。常见的设置功能分布在不同的菜单项中,如下所示。?项目设置(Project Settings)选择菜单【Project】【Settings】,出现“Project Settings”对话框,其中有若干项选项卡。与本书相关的设置包括:(1)Debug 选项卡 其中可以设置调试 DLL 程序的启动应用程序。在用户调试 UG NX 内部程序时,由于程序是动态链接库,不能直接启动,只能在 UG NX 中调用。则用户可以将“Executable for debug session”值 设 置 为 UG NX 的 启 动 程 序,例 如“C:Program FilesUGSNX 3.0UGIIugraf.exe”,从而方便内部程序的调试。(2)Link 选项卡 其中可以设置动态链接库文件的输出位置(“output file name:”);也可以设置在链接时所使用的外部库的名字(“Object/library modules:”),在编写 UG NX 二次开发程序时,必须将几个 UG NX 二次开发相关的库包含进来,具体的库文件名可以参见本书第 3.2.2 节的内容。?编译模式选择 VC6 中有 2 种编译模式:调试(debug)模式和发布(release)模式。调试模式会在编译链接好的应用程序(*.exe)或动态链接库(*.dll)中增加许多调试用的额外信息,以方便用户调试程序,去除语法错误和逻辑错误。当然此时生成的文件占用空间比较多,运行速度也相对较慢。发布模式则对生成的文件进行了各种优化,当然也不包含各种调试用信息,文件占用空间少,运行速度较快。读者在编写和调试程序时,应首先选择调试模式。在程序完成调试后,使用发布模式再进行一遍编译和链接,之后再进行应用程序的发布。选择菜单【Build】【Set Active Configuration】,在出现的对话框中选择合适的编译模式后,点击【OK】即可。?文件目录设置 VC6 在进行编译时,需要找到相应的头文件(*.h)和库文件(*.lib),查找原则是在项目当前工作目录下查找,或是在系统指定的目录中查找。UG NX 二次开发程序中需要用到许多头文件和库文件,这些文件的存放位置需要在项目中进行设置。选择菜单【Tools】【Options】,出现“Options”对话框,其中有若干选项卡,选择“Directories”选项卡。在“Show directories for:”下拉框中,选择“Include files”,为头文件指定查找目录;选择“Library files”,为库文件指定查找目录。与 UG NX 二次开发相关的头文件和库文件的查找目录设置方法参见本书的第 3.2.2 节内容。2.1.4 VC6 程序的编译 程序员编写的程序都以文本的方式存储在*.cpp 文件中或*.h 文件中,这些程序不能直接执行,需要编译和链接后才能生成可执行文件。编译(Compile)检查代码中的语法错误,生成的文件是目标文件(*.obj),存放在项目目录的debug子目录或release子目录下。链接(Link)将各种目标库链接到程序文件中,生成的文件是可执行程序(*.exe)或动态链接库(*.dll),也存放在项目目录的 debug 子目录或 release 子目录下。VC6 中完成编译和链接可以通过【Build】菜单下的如下几个子菜单功能完成:?Compile 编译命令,将源代码文件编译成目标文件。VC6 有一定的智能功能,在编译时会根据依赖关系,比较相应的源代码文件和目标文件的修改时间,若源代码文件的修改时间晚于目标文件,则认为目标文件已过期,会重新编译生成目标文件;若源代码文件的修改时间早于目标文件,则说明目标文件仍然有效,不会编译相应的源代码文件。?Build 链接命令,将目标文件链接后生成可执行程序或动态链接库。链接也具有智能功能,即也会根据可执行程序和目标文件的依赖关系以及修改时间的先后差异,来判断是否进行新的链接操作。当然,若程序没有进行编译,此命令也会首先启动编译命令,然后再进行链接。?Rebuild All 重新链接命令。此命令忽略各文件的依赖关系和修改时间先后差异,重新执行编译和链接命令,以生成最新的可执行程序或动态链接库。?Batch Build 批量链接命令。当某一个工作空间中包含多个项目时,此命令会依据各项目的依赖关系,对工作空间中所包含的各个项目进行编译和链接。在某种特殊的情况下,VC6 编译程序可能会死机,即 VC6 应用程序没有响应。若之前用户没有保存其对代码的更改,则会造成损失。因此建议用户在编译程序之前,首先应保存应用程序(【File】【Save All】)。2.1.5 VC6 程序的运行 程序完成了编译链接后,如果没有语法错误,则会生成可执行文件,并在 VC6 的环境下执行。执行也可以分为 2 种模式,正式执行和调试执行。正式执行可以通过菜单项【Build】【Execute】或快捷键“Ctrl+F5”来激活,在此种模式下,程序从入口一直执行到结束,完成用户在代码中编写的各种功能;而调试执行则可以允许用户执行到某一行、单步执行等,以消除代码中的逻辑错误,调试执行在下一小节详述。2.1.6 VC6 程序的调试 用户编写完成的源代码中有可能存在 2 种错误,即语法错误和逻辑错误。?语法错误 C 语言对程序的语法要求非常严格,编译过程会检查所有的源代码以消除语法错误。当用户执行编译和链接时,VC6 会严格检查所有的源代码,并将源代码中出现的错误罗列在输出窗口的“Build”选项卡中,其中的每一行对应一个错误。用户可以通过双击此窗口中的某一行错误描述,系统会在编辑窗口中自动定位到出错的代码处,然后用户可以根据错误描述进行源代码更改。在编译和链接过程中,会产生两种类型的信息,即错误(error)和警告(warning)。错误是必须被消除的,否则程序无法生成。而警告信息即使没有消除,VC6 也会产生应用程序,程序也可以执行,但其中会包含很多隐患。建议用户在正式发布程序之前,将所有的警告都处理掉。常见的语法错误包括:变量未定义、变量重定义、数据类型错误、参数类型错误、函数名错误、缺少分号(“;”)、缺少大括号(“”、“”)等;常见的警告包括:从未引用的变量定义、不合适的数据类型强制转换等。链接中经常出现的错误是某个函数调用没有合适的库,即此函数存在于另外的库中,而此库又没有被包含进此工程中,所以链接时系统找不到。?逻辑错误 当源程序编写完成,并通过了编译和链接后,并不能说明程序已经正确地完成了。通过了编译和链接只能说明程序中没有了语法错误,仍然有可能存在逻辑错误。逻辑错误是指那些完全符合语法规则,但却会对程序执行的正确性、执行效率、执行稳定性等产生不利影响的语句或函数。为了消除逻辑错误,程序员可以将某一个中间过程变量的值显示出来,从而逐步缩小逻辑错误的定位范围,最终完成错误的定位和修改。在 VC6 中,程序员也可以使用排错模式,跟踪到程序执行的内部,查看程序的执行分支情况、检查各个变量的值,从而定位逻辑错误的位置并修改。程序员可以通过如下 3 种方式进入排错模式。(1)执行到断点 首先设置断点,在编辑窗口将光标放在源程序的某行(即程序运行到此停止的断点)代码处,按快捷键“F9”来设置和取消断点,设置好的断点在编辑窗口的最左边有一个红色的圆点提示。选择菜单【Build】【Start Debug】【Go】或快捷键“F5”,系统会自动开始执行代码,一直到遇到第一个断点或执行到程序结束。(2)单步执行 选择菜单【Build】【Start Debug】【Step Into】或快捷键“F10”、“F11”,系统会自动开始执行代码,停止在程序入口函数的第一行处。(3)执行到某一行 首先在编辑窗口中,将光标放在某一行代码处,选择菜单【Build】【Start Debug】【Run to Cursor】或快捷键“Ctrl+F10”,系统会自动开始执行代码,停止在光标所处的代码行处,若过程中遇到断点,也会停止在断点处。进入排错模式后,VC6 的菜单中会增加一个顶级下拉菜单“【Run to Cursor】”,其中包含了若干子菜单项来支持排错,简介如下:(1)Go 从当前点执行到下一个断点处或直到程序结束。也可用快捷键“F5”激活。(2)Restart 中止当前排错,重新开始执行排错。也可用快捷键“Ctrl+Shift+F5”激活。(3)Stop Debugging 中止当前排错。也可用快捷键“Shift+F5”激活。(4)Step Into 跟踪执行到某一函数内部。也可用快捷键“F11”激活。(5)Step Over 从当前执行点执行一步到下一行程序,与“Step Into”不同,不会执行到函数内部。也可用快捷键“F10”激活。(6)Step Out 从当前执行点执行到本函数结束。也可用快捷键“F10”激活。(7)Run to Cursor 从当前执行点执行到光标所在位置。,若过程中遇到断点,也会停止在断点处。也可用快捷键“Ctrl+F10”激活。程序执行的当前行会在编辑窗口的右边出现一个黄色的箭头来指示。除了上述菜单命令外,在屏幕的正下方,也会出现 2 个窗口。左边的窗口显示当前代码所处的函数中的各个变量的值;在右边的窗口中,用户可以增加自己想要查看的各个变量。当用户将光标放置在编辑窗口中某变量上时,VC6 会以 Tip 的形式显示此变量的值。比较常见的逻辑错误类型有:单等号(“”)和双等号(“”)的错误使用、指针变量未初始化即使用、申请的内存在程序退出之前没有释放等。2.2 VC6 编程举例 本节以一个例子的形式说明使用 VC6 建立一个可执行程序框架、编写代码、调试错误、编译执行的过程。此例子是一个控制台应用程序,要求用户输入 2 个数字,程序比较两个数字的大小后给出判断结果。(1)建立程序框架 打开 VC6,选择菜单【File】【New】,在“New”对话框中切换到“Project”选项卡,选择工程类型为“Win32 Console Application”。选择工程保存位置“D:”,输入工程名“test”。如图 2-2 所示。其它保持不变,点击【OK】。在随后出现的对话框中选择“a simple application”,如图 2-3 所示。点击【Finish】。在后面出现的对话框中点击【OK】。图 2-2 创建工程 此工程建立完毕,保存在“D:test”目录下,其中有一个文件“test.dsw”,是工作空间文件,一个文件“test.dsp”,是项目文件。图 2-3 选择简单应用程序(2)编写代码 在项目工作区的“文件视图”选项卡中,找到源代码文件“test.cpp”,双击后在出现的编辑窗口中输入源代码,如代码示例 2-1 所示。代码示例 2-1 int main(int argc,char*argv)char char1,char2;float number1,number2;/输入第一个数字 printf(input number 1:);char1=getchar();/清空缓冲区 _flushall();/输入第二个数字 printf(input number 2:);char2=getchar();/将字符转换为数字 number1=atof(char1);number2=atof(char2);/比较两个数字的大小 if(number1=number2)printf(number1 is equal to number2n);else if(number1 number2)printf(number1 is larger than number2n);else if(number1 number2)printf(number1 is smaller than number2n);else printf(i dont know that!n);/等待用户结束 printf(nnhit any key to endn);_flushall();getchar();return 0;(3)调试和排错 按照 2.1.4 节的介绍,对程序进行编译和链接。上述程序中存在着不少语法错误和逻辑错误。编译后,系统会提示有 1 个错误和 2 个警告。如图 2-4 所示一般调试和排错的原则是先解决第一个错误后重新编译链接,因为许多后续的错误和警告可能是由前面的错误引起的。图 2-4 编译错误 在第一个错误提示行上双击,在编辑窗口中会自动将出错的代码行显示出来,并且在编辑窗的左边以蓝色箭头指示。第一个错误是提示“atof”是一个未定义的符号。这是因为声明“atof”函数的头文件没有被包含进来,因此,需要在头文件声明处增加一行声明代码,如代码示例 2-2 所示。代码示例 2-2#include stdlib.h 再次编译,此错误消失,又增加了 2 个错误,提示在调用函数“atof”时,无法将参数1 的类型从“char”类型转换为“const char*”类型。即上述代码中,调用“atof”时传入的参数类型错误,将参数从“char”类型转换为其地址,也就是“char*”类型。改动前后的代码如代码示例 2-3 所示。代码示例 2-3 改动前:/将字符转换为数字 number1=atof(char1);number2=atof(char2);改动后:/将字符转换为数字 number1=atof(&char1);number2=atof(&char2);再次编译,则系统提示中错误已经消失,出现了 2 个警告。提示在执行将字符转换成数字时(调用 atof 函数),可能存在着将整型(int)转换成单精度浮点型(float)时的数据丢失,查阅 MSDN 后得知,函数 atof 的返回值是双精度型。解决方法是将两个浮点型的变量声明改为双精度型,如代码示例 2-4。代码示例 2-4 改动前:float number1,number2;改动后:Double number1,number2;再次编译,则错误和警告都消失了,系统完成了可执行程序的创建。执行程序(快捷键“F5”),程序执行后出现命令行窗口,提示用户输入数字 1 和数字 2,读者可以输入 1 和 2。预期的输出结果应该是在屏幕上打印“number1 is smaller than number2”,可实际的运行结果却是程序打印出“number1 is equal to number2”,显然不正确。说明程序中存在着逻辑错误。为了解决此问题,采用单步跟踪(快捷键“F10”)的方法进入程序逐行执行,在执行到第一个 if(“if(number1=number2)”)语句之前都正常,执行完此语句后,发现变量“number2”的值从 1 变成了 2,由此找到了此逻辑错误。因为在 C 语言中,判断相等的逻辑运算符号是双等号(“=”),而不是单等号(“=”),单等号是一个赋值操作,而且 C 语言中的“逻辑真”等同于非零的整数。修改此处代码,如代码示例 2-5 所示。代码示例 2-5 改动前:if(number1=number2);改动后:if(number1=number2);再次编译执行程序,输入 1 和 2,则程序给出了正确的结果。(4)发布 将编译模式改为发布(release)模式,重新编译链接此程序。生成的可执行文件(“test.exe”)存放在 release 子目录下,将其发布即可。