2.2C+程序构架及词法符号约定 2.2.1C++程序示例 先通过一个简单的示例来分析用该语言所编写的程序的基本结构及一些特点。 例2.1一个简单的C+程序 //EX2 1. cpp /分别输入一个学生的3门功课成绩,根据其相应的学分,计算其加权平均值 # include< iostream. h>预处理指令 double average( double scorel, double score2, double score3);//函数引用说明 void maino double scorel, score2, score3, average cout<<”第一门功课成绩:”; n>>scorel //接收用户输入 cout<<”第二门功课成绩:” cin>>score2 cout<<”第三门功课成绩: cin>>score3 average= Average( scorel, score2, score3);//调用子函数,用返回值为变量赋值 cout<<”加权平均分为:”<< average<”\n”;//输出计算结果 //程序的子函数 double Average(double scorel, double score2, double score3) double credit, credit2, credit, average credit=3. 0 credit=4. 0 credit=2. 0 average=(credit*scorel+credit2*score2+credit*score3)/(creditI+credit2+cr edit) return average 2.2.2C++程序的一般结构 C艹源程序以文件为单位进行存储。通常,最终被编译、链接成一个可执行文件的程序 都包含一个工作空间( workspace),其中可以包括一个或多个不同性质的文件 从总体上看,C++程序一般可以分成4个部分:预处理指令、全局说明、对象类的定义 程序的主函数和用户自定义的函数,如下图2.1所示
2.2 C++程序构架及词法符号约定 2.2.1 C++程序示例 先通过一个简单的示例来分析用该语言所编写的程序的基本结构及一些特点。 例 2.1 一个简单的 C++程序 //EX2_1.cpp: //分别输入一个学生的 3 门功课成绩,根据其相应的学分,计算其加权平均值 #include <iostream.h> //预处理指令 double Average(double score1,double score2,double score3); //函数引用说明 void main() { double score1,score2,score3,average; cout<<”第一门功课成绩:”; cin>>score1; //接收用户输入 cout<<”第二门功课成绩:”; cin>>score2; cout<<”第三门功课成绩:”; cin>>score3; average=Average(score1,score2,score3); //调用子函数,用返回值为变量赋值 cout<<”加权平均分为:”<<average<<”\n”;//输出计算结果 } //程序的子函数 double Average(double score1,double score2,double score3) { double credit1,credit2,credit3,average; credit1=3.0; credit2=4.0; credit3=2.0; average=(credit1*score1+credit2*score2+credit3*score3)/(credit1+credit2+cr edit3); return average; } 2.2.2 C++程序的一般结构 C++源程序以文件为单位进行存储。通常,最终被编译、链接成一个可执行文件的程序 都包含一个工作空间(workspace),其中可以包括一个或多个不同性质的文件。 从总体上看,C++程序一般可以分成 4 个部分:预处理指令、全局说明、对象类的定义、 程序的主函数和用户自定义的函数,如下图 2.1 所示
预处理指令 全局说明 子函数1 子函数n 图2.1C+程序的一个结构 2.2.2.1预处理指令 在C艹程序中,预处理指令就是源程序中所包括的各种编译命令。所有的预处理指令均 以“#”号开始进行标识,而且“#”号还必须被置于该指令所在程序行的第一列。各种预处 理指令在程序编译前执行,其作用是以中间文件的形式向编译器传递一定的信息,并不影响 源程序 引进预处理指令的目的是对C艹+程序设计环境进行扩展,使得进行程序开发时更加方便 或控制程序编译的某些流程。 下面介绍几个常用的预处理指令 1、预处理指令# include(最为常用的预处理指令) 在程序执行的过程中,经常要使用到各种编译系统提供的标准函数、类库提供的类以 及用户开发的、存放在其它文件中的变量、函数和类等。而这些变量、函数和类等的说明和 其它信息,都保存在相关的头文件(.h文件)中。为了使用头文件中定义的变量、函数和 类,必须将相应的头文件包含到要使用它们的源文件中。为此可以使用预处理指令# include, 该指令的格式为 # include< readfile.h>或# include” readfile.h” 如果头文件名是由尖猡殳括起来,则编译器将在由编译系统设定的相应子目录中去搜 索该头文件。一般用于将编译系统提供的标准头文件或类库提供的头文件包含到程序中。如 果头文件名是由引号括起来,则编译器将在当前目录中去搜索该头文件。一般用于将自己 开发的头文件包含到程序中,以调用保存在其它源文件中的变量、函数和类等。如果编译器 在相应的目录中找不到相应的头文件,将产生致命错误( fatal error) 2、条件预处理指令 由于被预处理包含指令# include所指定的头文件中也可以使用# include指令,因此就 可能岀现头文件嵌套甚至是头文件循环相互调用的情况,导致编译效率低下甚至失败的情 为了避免这种情况的发生,引入了条件预处理指令,用来标识是否已经包含了某头函 数或头函数的部分。若已经包含,则在以后遇到要求包含该头函数或部分头函数的各部分时 跳过相应的部分 条件预处理指令包括: #ifdef #ifndef #define #else #endif 例2.2条件预处理指令用法1
预处理指令 全局说明 主函数 子函数 1 . . . 子函数 n 图 2.1 C++程序的一个结构 2.2.2.1 预处理指令 在 C++程序中,预处理指令就是源程序中所包括的各种编译命令。所有的预处理指令均 以“#”号开始进行标识,而且“#”号还必须被置于该指令所在程序行的第一列。各种预处 理指令在程序编译前执行,其作用是以中间文件的形式向编译器传递一定的信息,并不影响 源程序。 引进预处理指令的目的是对 C++程序设计环境进行扩展,使得进行程序开发时更加方便 或控制程序编译的某些流程。 下面介绍几个常用的预处理指令。 1、预处理指令#include (最为常用的预处理指令) 在程序执行的过程中,经常要使用到各种编译系统提供的标准函数、类库提供的类以 及用户开发的、存放在其它文件中的变量、函数和类等。而这些变量、函数和类等的说明和 其它信息,都保存在相关的头文件(.h 文件)中。为了使用头文件中定义的变量、函数和 类,必须将相应的头文件包含到要使用它们的源文件中。为此可以使用预处理指令#include, 该指令的格式为: #include <headfile.h> 或 #include ”headfile.h” 如果头文件名是由尖括号括起来,则编译器将在由编译系统设定的相应子目录中去搜 索该头文件。一般用于将编译系统提供的标准头文件或类库提供的头文件包含到程序中。如 果头文件名是由双引号括起来,则编译器将在当前目录中去搜索该头文件。一般用于将自己 开发的头文件包含到程序中,以调用保存在其它源文件中的变量、函数和类等。如果编译器 在相应的目录中找不到相应的头文件,将产生致命错误(fatal error)。 2、条件预处理指令 由于被预处理包含指令#include 所指定的头文件中也可以使用#include 指令,因此就 可能出现头文件嵌套甚至是头文件循环相互调用的情况,导致编译效率低下甚至失败的情 况。 为了避免这种情况的发生,引入了条件预处理指令,用来标识是否已经包含了某头函 数或头函数的部分。若已经包含,则在以后遇到要求包含该头函数或部分头函数的各部分时, 跳过相应的部分。 条件预处理指令包括: #ifdef #ifndef #define #else #endif 例 2.2 条件预处理指令用法 1
#ifndef MYHEADFILE H #define myhEAdFIle H /*此处为头文件应加入的代码*/ #endif / MYHEADFILE H # 例2.3条件预处理指令用法2。 #ifdef u362 /*此处专门为AT&T3B计算机指定的代码*/ #endif / u362 * #ifdef sun /*此处专门为SUN计算机指定的代码*/ #endif 此处,我们看到了# ifdef预处理指令的一个重要用法:为程序的不同编译运行机型、不同 编译系统等指定特定的代码,以使程序具有良好的可移植性 例2.4条件预处理指令用法3。 #ifdef cplusplus /*专门为C++语言指定的代码*/ felse /*专门为C语言指定的代码* #endif /*k cplusplus =/ 3、宏替换指令# define
#ifndef MYHEADFILE_H #define MYHEADFILE_H . . /*此处为头文件应加入的代码*/ . . #endif /* MYHEADFILE_H */ 例 2.3 条件预处理指令用法 2。 #ifdef u362 . . /*此处专门为 AT&T 3B 计算机指定的代码 */ . . #endif /* u362 */ #ifdef sun . . /*此处专门为 SUN 计算机指定的代码 */ . . #endif /* sun */ 此处,我们看到了#ifdef 预处理指令的一个重要用法:为程序的不同编译运行机型、不同 编译系统等指定特定的代码,以使程序具有良好的可移植性。 例 2.4 条件预处理指令用法 3。 #ifdef _cplusplus . . /*专门为 C++语言指定的代码 */ . . #else . . /*专门为 C 语言指定的代码 */ . . #endif /* _cplusplus */ 3、宏替换指令#define
使用宏替换指令主要是为了简化代码和增强程序的可读性。C艹+中的宏替换主要有形 式 形式1: # define标识符所代表的字符或常量(如# define pi3.14159265) 在程序进行编译时,编译器会将遇到的PI用3.14159265进行替换。 形式2 # define标识符(参数)表达式(如:# define area(r)P**r) 2.2.2.2全局说明 全局说明一般包括一些程序所要使用的全局变量、类说明、用户定义的子函数的引用 说明等。 在全局说明段进行说明的变量,其存在和使用是全局的,在程序运行的整个过程中 直存在,且占用同一段内存区域 在全局说明段进行说明的子函数,编译器将为该子函数分配一段内存区域,用来保存 该子函数的函数指针,在对该子函数进行说明之后的代码中,都可以调用该子函数,而不必 关心该子函数的定义部分代码放在源代码的什么地方。 2.2.2.3主函数 任何一个C艹程序都有一个且只有一个主函数。在面向DOS操作系统的编程中,主函数 的名称为main(),而在面向 Windows操作系统的编程中,主函数的名称为 winmaIn() 注意:在利用类库进行面向 Windows操作系统的编程中(如利用VC+的MFC),有时在 程序的源代码中看不到主函数 wInmaIn(),此时程序的主函数隐含在类库的链接库文件中, 而该库文件在程序的主框架类的头文件中 程序的主函数可以不带参数,也可以带有一个或一个以上的参数。若带有参数,则执 行该程序时需要向程序提供相应的参数。 主函数的返回值有两种情况:无返回值及返回值为整型。若主函数的返回值类型说明 为void,即无返回值的情况,在主函数中无需返回语句( return)或使用返回语句,而返 回语句无表达式( return:)。若主函数的返回值类型说明为int,则程序返回值为0,表示 程序运行正常结束,返回其他非零整型值表示程序异常返回。 2.2.2.4用户自定义的函数 用户自定义的函数是程序开发人员为了实现某些特定的操作而编写的一组代码。这样做 能简化代码,避免同样的代码多次重复书写,而且使得程序更加清晰易读、各部分代码功能 目的明确 子函数可以不带任何参数,也可以无返回值(void型),但常用的子函数一般都带一定 数目的参数,这些参数可以按值传递,也可以按地址传递,或者同时含有两种参数传递方式, 其用法和区别将在2.2节进行讨论。在函数体内,对这些参数进行一定的计算或判断,返 回一个特定类型的数值,或通过改变按地址传递参数的数值,实现多值返回。即使无须返回 任何数值的子函数,通常也将函数的返回值类型定义为布尔型(bool),利用返回真(true 和假( false)来判断子函数是否调用成功 般来说,程序定义的子函数,只能在该子函数定义之后的代码中被调用。为了在 子函数定义之前的代码中调用某个子函数,可以在调用它之前的全局说明假中对该子函数进 行引用说明。为了在其它源文件中调用在另一源文件中定义的子函数,可以在头文件中对该
使用宏替换指令主要是为了简化代码和增强程序的可读性。C++中的宏替换主要有形 式。 形式 1: #define 标识符 所代表的字符或常量 (如 #define PI 3.14159265) 在程序进行编译时,编译器会将遇到的 PI 用 3.14159265 进行替换。 形式 2: #define 标识符(参数) 表达式 (如:#define Area(r) PI*r*r) 2.2.2.2 全局说明 全局说明一般包括一些程序所要使用的全局变量、类说明、用户定义的子函数的引用 说明等。 在全局说明段进行说明的变量,其存在和使用是全局的,在程序运行的整个过程中一 直存在,且占用同一段内存区域。 在全局说明段进行说明的子函数,编译器将为该子函数分配一段内存区域,用来保存 该子函数的函数指针,在对该子函数进行说明之后的代码中,都可以调用该子函数,而不必 关心该子函数的定义部分代码放在源代码的什么地方。 2.2.2.3 主函数 任何一个 C++程序都有一个且只有一个主函数。在面向 DOS 操作系统的编程中,主函数 的名称为 main(),而在面向 Windows 操作系统的编程中,主函数的名称为 winmain()。 注意:在利用类库进行面向 Windows 操作系统的编程中(如利用 VC++的 MFC),有时在 程序的源代码中看不到主函数 winmain(),此时程序的主函数隐含在类库的链接库文件中, 而该库文件在程序的主框架类的头文件中。 程序的主函数可以不带参数,也可以带有一个或一个以上的参数。若带有参数,则执 行该程序时需要向程序提供相应的参数。 主函数的返回值有两种情况:无返回值及返回值为整型。若主函数的返回值类型说明 为 void,即无返回值的情况,在主函数中无需返回语句(return)或使用返回语句,而返 回语句无表达式(return;)。若主函数的返回值类型说明为 int,则程序返回值为 0,表示 程序运行正常结束,返回其他非零整型值表示程序异常返回。 2.2.2.4 用户自定义的函数 用户自定义的函数是程序开发人员为了实现某些特定的操作而编写的一组代码。这样做 能简化代码,避免同样的代码多次重复书写,而且使得程序更加清晰易读、各部分代码功能 目的明确。 子函数可以不带任何参数,也可以无返回值(void 型),但常用的子函数一般都带一定 数目的参数,这些参数可以按值传递,也可以按地址传递,或者同时含有两种参数传递方式, 其用法和区别将在 2.2 节进行讨论。在函数体内,对这些参数进行一定的计算或判断,返 回一个特定类型的数值,或通过改变按地址传递参数的数值,实现多值返回。即使无须返回 任何数值的子函数,通常也将函数的返回值类型定义为布尔型(bool),利用返回真(true) 和假(false)来判断子函数是否调用成功。 一般来说,程序定义的子函数,只能在该子函数定义之后的代码中被调用。为了在 子函数定义之前的代码中调用某个子函数,可以在调用它之前的全局说明假中对该子函数进 行引用说明。为了在其它源文件中调用在另一源文件中定义的子函数,可以在头文件中对该
子函数进行引用说明,则在包含该头文件的所有源文件中都有可以对该子函数进行调用。 除了用户自己编写的函数外,还可以利用库函数来实现一些常用的操作。库函数是 由编译器开发商或一些第三方的开发商所提供的,用于实现一些通用的一般操作而编写的函 数。一般可以分为三类: 1、若干个以.H为后缀的头文件,其中包含了该组中所有库函数的原型定义。用户可 以用任何文本编辑器打开该文件,并了解这些库函数的的函数名、调用参数、函数返回值类 型等内容。对类库而言,从该头文件中还可以了解到各个类的定义、类的继承关系、类中的 成员数据和成员函数等。 2、一个以.Lib为后缀的动态链接库,其中包含了各个库函数的实现。该.Lib文件也 是由若干个后缀为.cpp的源文件和后缀为.h的头文件组合在一起,编译链接而成。只不 过由于对编译器的设定不同而形成一种后缀为.cp的特殊动态链接文件。在需要使用库函 数的源文件或该源文件(.Cp)所包含的头文件(h)中将该含有该库的头文件(h)包 含进来 函数定义的一般形式如下 type function name( variable list) statement return var 其中,type是函数的返回值类型, function name是该函数的函, variable list是向该函数所 传递的参数表, statement1,是为了完成该函数的功能所需要执行的各个语句,其中最后 一个语句 return var是将变量var作为函数的返回值传回函数调用处,变量var的类型应与函 数的返回值类型type相匹配。而函数原型函数原型说明则只需要包含函数的返回值类型 函数名及参数表,如下所示。 Type function name(variable list): 2.2.3C++的词法符号定 任何计算机语言都是规定了其可以使用的字符集合,同时由该字符集合中的某些元素进 行组合,形成一系列具有特定意义的词法符号。利用这些词法符号,通过规定的规则,形成 对程序需要执行操作的明确描述。以下将分别对C+使用的字符集合及词法符号进行介 绍 2.2.3.1C++中可以使用的字符集合 C+语言所使用的字符集合是ASCI码,包括: 1、基本代码—一控制字符(32个),数字字符(10个),英文字母(52个),其它字符 (34个)。 2、扩展代码一一包括一些制表符和一些特殊的显示符号等 2.2.3.2C++规定的词法符号
子函数进行引用说明,则在包含该头文件的所有源文件中都有可以对该子函数进行调用。 除了用户自己编写的函数外,还可以利用库函数来实现一些常用的操作。库函数是 由编译器开发商或一些第三方的开发商所提供的,用于实现一些通用的一般操作而编写的函 数。一般可以分为三类: 1、若干个以.H 为后缀的头文件,其中包含了该组中所有库函数的原型定义。用户可 以用任何文本编辑器打开该文件,并了解这些库函数的的函数名、调用参数、函数返回值类 型等内容。对类库而言,从该头文件中还可以了解到各个类的定义、类的继承关系、类中的 成员数据和成员函数等。 2、一个以.Lib 为后缀的动态链接库,其中包含了各个库函数的实现。该.Lib 文件也 是由若干个后缀为.cpp 的源文件和后缀为.h 的头文件组合在一起,编译链接而成。只不 过由于对编译器的设定不同而形成一种后缀为.cpp 的特殊动态链接文件。在需要使用库函 数的源文件或该源文件(.Cpp)所包含的头文件(.h)中将该含有该库的头文件(.h)包 含进来。 函数定义的一般形式如下: type function_name(variable_list) { statement1; statement2; . . . return var; } 其中,type 是函数的返回值类型,function_name 是该函数的函,variable_list 是向该函数所 传递的参数表,statement1,…..是为了完成该函数的功能所需要执行的各个语句,其中最后 一个语句 return var 是将变量 var 作为函数的返回值传回函数调用处,变量 var 的类型应与函 数的返回值类型 type 相匹配。而函数原型函数原型说明则只需要包含函数的返回值类型、 函数名及参数表,如下所示。 Type function_name(variable_list); 2.2.3 C++的词法符号定 任何计算机语言都是规定了其可以使用的字符集合,同时由该字符集合中的某些元素进 行组合,形成一系列具有特定意义的词法符号。利用这些词法符号,通过规定的规则,形成 对程序需要执行操作的明确描述。以下将分别对 C++中使用的字符集合及词法符号进行介 绍。 2.2.3.1 C++中可以使用的字符集合 C++语言所使用的字符集合是 ASCII 码,包括: 1、基本代码——控制字符(32 个),数字字符(10 个),英文字母(52 个),其它字符 (34 个)。 2、扩展代码——包括一些制表符和一些特殊的显示符号等。 2.2.3.2 C++规定的词法符号