C++面向对象程序设计-谭浩强-完整版.doc

上传人:jian****018 文档编号:9505990 上传时间:2020-04-06 格式:DOC 页数:392 大小:4.75MB
返回 下载 相关 举报
C++面向对象程序设计-谭浩强-完整版.doc_第1页
第1页 / 共392页
C++面向对象程序设计-谭浩强-完整版.doc_第2页
第2页 / 共392页
C++面向对象程序设计-谭浩强-完整版.doc_第3页
第3页 / 共392页
点击查看更多>>
资源描述
C+面向对象程序设计 谭浩强 编著目录第1篇 基 本 知 识2第1章 C+的初步知识2第2章 数据类型与表达式8第2篇 面向过程的程序设计22第3章 程序设计初步23第4章 函数与预处理134第5章 数组167第6章 指针187第7章 自定义数据类型225第3篇基于对象的程序设计248第8章 类和对象248第9章 关于类和对象的进一步讨论267第10章 运算符重载297第4篇 面向对象的程序设计317第11章 继承与派生317第12章 多态性与虚函数342第13章 输入输出流354第14章 C+工具376第1篇 基 本 知 识第1章 C+的初步知识*1.1 从C到C+*1.2 最简单的C+程序 1.3 C+程序的构成和书写形式 1.4 C+程序的编写和实现 1.5 关于C+上机实践*1.1 从C到C+计算机诞生初期,人们要使用计算机必须用机器语言或汇编语言编写程序世界上第一种计算机高级语言诞生于1954年,它是FORTRAN语言先后出现了多种计算机高级语言其中使用最广泛影响最大的当推BASIC语言和C语言BASIC语言是1964年在FORTRAN语言的基础上简化而成的,它是为初学者设计的小型高级语言C语言是1972年由美国贝尔实验室的D.M.Ritchie研制成功的它不是为初学者设计的,而是为计算机专业人员设计的大多数系统软件和许多应用软件都是用C语言编写的但是随着软件规模的增大,用C语言编写程序渐渐显得有些吃力了C+是由AT&T Bell(贝尔)实验室的Bjarne Stroustrup博士及其同事于20世纪80年代初在C语言的基础上开发成功的C+保留了C语言原有的所有优点,增加了面向对象的机制C+是由C发展而来的,与C兼容用C语言写的程序基本上可以不加修改地用于C+从C+的名字可以看出它是C的超集C+既可用于面向过程的结构化程序设计,又可用于面向对象的程序设计,是一种功能强大的混合型的程序设计语言C+对C的“增强”,表现在两个方面: (1) 在原来面向过程的机制基础上,对C语言的功能做了不少扩充(2) 增加了面向对象的机制面向对象程序设计,是针对开发较大规模的程序而提出来的,目的是提高软件开发的效率不要把面向对象和面向过程对立起来,面向对象和面向过程不是矛盾的,而是各有用途互为补充的学习C+,既要会利用C+进行面向过程的结构化程序设计,也要会利用C+进行面向对象的程序设计本书既介绍C+在面向过程程序设计中的应用,也介绍C+在面向对象程序设计中的应用*1.2 最简单的C+程序例1.1 输出一行字符: “This is a C+ program.”程序如下: #include /包含头文件iostreamusing namespace std; /使用命名空间stdint main( )coutThis is a C+ program.;return 0;在运行时会在屏幕上输出以下一行信息:This is a C+ program. 用main代表“主函数”的名字每一个C+程序都必须有一个 main 函数main前面的int的作用是声明函数的类型为整型程序第6行的作用是向操作系统返回一个零值如果程序不能正常执行,则会自动向操作系统返回一个非零值,一般为-1函数体是由大括号 括起来的本例中主函数内只有一个以cout开头的语句注意C+所有语句最后都应当有一个分号再看程序的第1行“#include ”,这不是C+的语句,而是C+的一个预处理命令,它以“#”开头以与C+语句相区别,行的末尾没有分号#include 是一个“包含命令”,它的作用是将文件iostream的内容包含到该命令所在的程序文件中,代替该命令行文件iostream的作用是向程序提供输入或输出时所需要的一些信息iostream是i-o-stream 3个词的组合,从它的形式就可以知道它代表“输入输出流”的意思,由于这类文件都放在程序单元的开头,所以称为“头文件”(head file)在程序进行编译时,先对所有的预处理命令进行处理,将头文件的具体内容代替 #include命令行,然后再对该程序单元进行整体编译程序的第2行“using namespace std; ” 的意思是“使用命名空间std”C+标准库中的类和函数是在命名空间std中声明的,因此程序中如果需要用到C+标准库(此时就需要用#include命令行),就需要用“using namespace std; ”作声明,表示要用到命名空间std中的内容在初学C+时,对本程序中的第1,2行可以不必深究,只需知道: 如果程序有输入或输出时,必须使用“#include ”命令以提供必要的信息,同时要用“using namespace std;” ,使程序能够使用这些信息,否则程序编译时将出错例1.2 求a和b两个数之和可以写出以下程序: / 求两数之和 (本行是注释行)#include /预处理命令using namespace std; /使用命名空间stdint main( ) /主函数首部 /函数体开始 int a,b,sum; /定义变量 cinab; /输入语句 sum=a+b;/赋值语句couta+b=sumendl; /输出语句return 0; /如程序正常结束,向操作系统返回一个零值 /函数结束本程序的作用是求两个整数a和b之和sum第1行“/求两数之和”是一个注释行,C+规定在一行中如果出现“/”,则从它开始到本行末尾之间的全部内容都作为注释如果在运行时从键盘输入 123 456则输出为a+b=579例1.3 给两个数x和y,求两数中的大者在本例中包含两个函数#include /预处理命令using namespace std;int max(int x,int y)/定义max函数,函数值为整型,形式参数x,y为整型 /max函数体开始int z;/变量声明,定义本函数中用到的变量z为整型if(xy) z=x;/if语句,如果xy,则将x的值赋给zelse z=y; /否则,将y的值赋给z return(z);/将z的值返回,通过max带回调用处 /max函数结束int main( ) /主函数 /主函数体开始 int a,b,m;/变量声明cinab;/输入变量a和b的值m=max(a,b); /调用max函数,将得到的值赋给mcoutmax=mn;/输出大数m的值return 0; /如程序正常结束,向操作系统返回一个零值 /主函数结束本程序包括两个函数:主函数main和被调用的函数max程序运行情况如下: 18 25 (输入18和25给a和b)max=25 (输出m的值) 注意输入的两个数据间用一个或多个空格间隔,不能以逗号或其他符号间隔在上面的程序中,max函数出现在main函数之前,因此在main函数中调用max函数时,编译系统能识别max是已定义的函数名如果把两个函数的位置对换一下,即先写main函数,后写max函数,这时在编译main函数遇到max时,编译系统无法知道max代表什么含义,因而无法编译,按出错处理为了解决这个问题,在主函数中需要对被调用函数作声明上面的程序可以改写如下:#include using namespace std;int main( ) int max(int x,int y);/对max函数作声明 int a,b,c; cinab; c=max(a,b); /调用max函数 coutmax=cy) z=x; else z=y; return(z);只要在被调用函数的首部的末尾加一个分号,就成为对该函数的函数声明函数声明的位置应当在函数调用之前下面举一个包含类(class)和对象(object)的C+程序,目的是使读者初步了解C+是怎样体现面向对象程序设计方法的例1.4 包含类的C+程序#include / 预处理命令using namespace std;class Student/ 声明一个类,类名为Studentprivate: / 以下为类中的私有部分int num; / 私有变量numint score; / 私有变量scorepublic: / 以下为类中的公用部分void setdata( ) / 定义公用函数setdatacinnum; / 输入num的值cinscore; / 输入score的值 void display( ) / 定义公用函数displaycoutnum=numendl; / 输出num的值 coutscore=scoreendl;/输出score的值 ; / 类的声明结束Student stud1,stud2; /定义stud1和stud2为Student类的变量,称为对象int main( )/ 主函数首部stud1.setdata( ); / 调用对象stud1的setdata函数 stud2.setdata( ); / 调用对象stud2的setdata函数 stud1.display( ); / 调用对象stud1的display函数stud2.display( ); / 调用对象stud2的display函数return 0;在一个类中包含两种成员: 数据和函数,分别称为数据成员和成员函数在C+中把一组数据和有权调用这些数据的函数封装在一起,组成一种称为“类(class)”的数据结构在上面的程序中,数据成员num,score和成员函数setdata,display组成了一个名为Student的“类”类型成员函数是用来对数据成员进行操作的也就是说,一个类是由一批数据以及对其操作的函数组成的类可以体现数据的封装性和信息隐蔽在上面的程序中,在声明Student类时,把类中的数据和函数分为两大类: private(私有的)和public(公用的)把全部数据(num,score)指定为私有的,把全部函数(setdata,display)指定为公用的在大多数情况下,会把所有数据指定为私有,以实现信息隐蔽具有“类”类型特征的变量称为“对象”(object)程序中第1824行是主函数程序运行情况如下: 1001 98.5 (输入学生1的学号和成绩)1002 76.5 (输入学生2的学号和成绩)num=1001 (输出学生1的学号)score=98.5 (输出学生1的成绩)num=1002 (输出学生2的学号)score=76.5 (输出学生2的成绩)1.3 C+程序的构成和书写形式C+程序的结构和书写格式归纳如下: (1) 一个C+程序可以由一个程序单位或多个程序单位构成每一个程序单位作为一个文件在程序编译时,编译系统分别对各个文件进行编译,因此,一个文件是一个编译单元(2) 在一个程序单位中,可以包括以下几个部分: 预处理命令上节4个程序中都包括#include命令 全局声明部分(在函数外的声明部分)在这部分中包括对用户自己定义的数据类型的声明和程序中所用到的变量的定义 函数函数是实现操作的部分,因此函数是程序中必须有的和最基本的组成部分每一个程序必须包括一个或多个函数,其中必须有一个(而且只能有一个)主函数(main函数)但是并不要求每一个程序文件都必须具有以上3个部分,可以缺少某些部分(包括函数)(3) 一个函数由两部分组成: 函数首部,即函数的第一行包括函数名函数类型函数属性函数参数(形参)名参数类型一个函数名后面必须跟一对圆括号, 函数参数可以缺省,如int main( ) 函数体,即函数首部下面的大括号内的部分如果在一个函数中有多个大括号,则最外层的一对 为函数体的范围函数体一般包括:局部声明部分 (在函数内的声明部分)包括对本函数中所用到的类型函数的声明和变量的定义对数据的声明既可以放在函数之外(其作用范围是全局的),也可以放在函数内(其作用范围是局部的,只在本函数内有效)执行部分由若干个执行语句组成,用来进行有关的操作,以实现函数的功能(4) 语句包括两类一类是声明语句,另一类是执行语句 C+对每一种语句赋予一种特定的功能语句是实现操作的基本成分,显然,没有语句的函数是没有意义的C+语句必须以分号结束(5) 一个C+程序总是从main函数开始执行的,而不论main函数在整个程序中的位置如何(6) 类(class)是C+新增加的重要的数据类型,是C+对C的最重要的发展有了类,就可以实现面向对象程序设计方法中的封装信息隐蔽继承派生多态等功能在一个类中可以包括数据成员和成员函数,他们可以被指定为私有的(private)和公用的(public)属性私有的数据成员和成员函数只能被本类的成员函数所调用(7)C+程序书写格式自由,一行内可以写几个语句, 一个语句可以分写在多行上C+程序没有行号,也不像FORTRAN或COBOL那样严格规定书写格式(语句必须从某一列开始书写)(8) 一个好的有使用价值的源程序都应当加上必要的注释,以增加程序的可读性C+还保留了C语言的注释形式,可以用“/*/”对C+程序中的任何部分作注释在“/*”和“*/”之间的全部内容作为注释用“/”作注释时,有效范围只有一行,即本行有效,不能跨行而用“/*/”作注释时有效范围为多行只要在开始处有一个“/*”,在最后一行结束处有一个“*/”即可因此,一般习惯是: 内容较少的简单注释常用“/”,内容较长的常用“/*/ ”1.4 C+程序的编写和实现一个程序从编写到最后得到运行结果要经历以下一些步骤1. 用C+语言编写程序用高级语言编写的程序称为“源程序”(source program)C+的源程序是以.cpp作为后缀的(cpp是c plus plus 的缩写)2. 对源程序进行编译为了使计算机能执行高级语言源程序,必须先用一种称为“编译器(complier)”的软件(也称编译程序或编译系统),把源程序翻译成二进制形式的“目标程序(object program)”编译是以源程序文件为单位分别编译的目标程序一般以.obj或.o作为后缀(object 的缩写)编译的作用是对源程序进行词法检查和语法检查编译时对文件中的全部内容进行检查,编译结束后会显示出所有的编译出错信息一般编译系统给出的出错信息分为两种,一种是错误(error);一种是警告(warning) 3. 将目标文件连接在改正所有的错误并全部通过编译后,得到一个或多个目标文件此时要用系统提供的“连接程序(linker)”将一个程序的所有目标程序和系统的库文件以及系统提供的其他信息连接起来,最终形成一个可执行的二进制文件,它的后缀是.exe,是可以直接执行的4. 运行程序 运行最终形成的可执行的二进制文件(.exe文件),得到运行结果5. 分析运行结果如果运行结果不正确,应检查程序或算法是否有问题图1.11.5 关于C+上机实践在了解了C+语言的初步知识后,读者最好尽快在计算机上编译和运行C+程序,以加深对C+程序的认识,并初步掌握C+的上机操作读者可以使用不同的C+编译系统,在不同的环境下编译和运行一个C+程序但是需要强调的是,我们学习的是C+程序设计,应当掌握的是标准C+,而不应该只了解某一种“方言化”的C+不应当只会使用一种C+编译系统,只能在一种环境下工作,而应当能在不同的C+环境下运行自己的程序,并且了解不同的C+编译系统的特点和使用方法,在需要时能将自己的程序方便地移植到不同的平台上在本书的参考书C+程序设计题解与上机指导一书中简单介绍了在Visual C+ 6.0和GCC两种典型的环境下运行C+程序的方法请读者选择一种(如能做到两种更好) C+编译系统,在该环境下输入和运行习题中的程序,掌握上机的方法和步骤第2章 数据类型与表达式2.1 C+的数据类型2.2 常量2.3 变量2.4 C+的运算符2.5 算术运算符与算术表达式2.6 赋值运算符与赋值表达式2.7 逗号运算符与逗号表达式2.1 C+的数据类型计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数浮点数字符等形式)不同的数据之间往往还存在某些联系(例如由若干个整数组成一个整数数组)数据结构指的是数据的组织形式例如,数组就是一种数据结构不同的计算机语言所允许使用的数据结构是不同的处理同一类问题,如果数据结构不同,算法也会不同例如,对10个整数排序和对包含10个元素的整型数组排序的算法是不同的C+可以使用的数据类型如下:C+的数据包括常量与变量,常量与变量都具有类型由以上这些数据类型还可以构成更复杂的数据结构例如利用指针和结构体类型可以构成表树栈等复杂的数据结构C+并没有统一规定各类数据的精度数值范围和在内存中所占的字节数,各C+编译系统根据自己的情况作出安排书中表2.1列出了Visual C+数值型和字符型数据的情况说明:(1) 整型数据分为长整型(long int)一般整型(int)和短整型(short int)在int前面加long和short分别表示长整型和短整型(2) 整型数据的存储方式为按二进制数形式存储,例如十进制整数85的二进制形式为1010101,则在内存中的存储形式如图2.1所示图2.1(3) 在整型符号int和字符型符号char的前面,可以加修饰符signed(表示“有符号”)或unsigned(表示“无符号”)如果指定为signed,则数值以补码形式存放,存储单元中的最高位(bit)用来表示数值的符号如果指定为unsigned,则数值没有符号,全部二进制位都用来表示数值本身例如短整型数据占两个字节 ,见图2.2图2.2有符号时,能存储的最大值为215-1,即32767,最小值为-32768无符号时,能存储的最大值为216-1,即65535,最小值为0有些数据是没有负值的,可以使用unsigned,它存储正数的范围比用signed时要大一倍(4) 浮点型(又称实型)数据分为单精度(float)双精度(double)和长双精度(long double)3种,在Visual C+ 6.0中,对float提供6位有效数字,对double提供15位有效数字,并且float和double的数值范围不同对float分配4个字节,对double和long double分配8个字节(5) 表中类型标识符一栏中,方括号 包含的部分可以省写,如short和short int等效,unsigned int和unsigned等效常量的值是不能改变的,一般从其字面形式即可判别是否为常量常量包括两大类,即数值型常量(即常数)和字符型常量如12,0,-3为整型常量,4.6,-1.23为实型常量,包含在两个单撇号之间的字符为字符常量,如a,x这种从字面形式即可识别的常量称为“字面常量”或“直接常量”2.2 常量2.2.1 什么是常量2.2.2 数值常量数值常量就是通常所说的常数在C+中,数值常量是区分类型的,从字面形式即可识别其类型1. 整型常量(整数)的类型在上一节中已知道: 整型数据可分为int,short int,long int以及unsigned int,unsigned short,unsigned long等类别整型常量也分为以上类别为什么将数值常量区分为不同的类别呢?因为在进行赋值或函数的参数虚实结合时要求数据类型匹配那么,一个整型常量怎样从字面上区分为以上的类别呢?(1) 一个整数,如果其值在-32768+32767范围内,认为它是short int型,它可以赋值给short int型int型和long int型变量(2) 一个整数,如果其值超过了上述范围,而在-2147483648+2147483647范围内,则认为它是long int型,可以将它赋值给一个int或long int型变量(3) 如果某一计算机系统的C+版本(例如Visual C+)确定int与long int型数据在内存中占据的长度相同,则它们能够表示的数值的范围相同因此,一个int型的常量也同时是一个long int型常量,可以赋给int型或long int型变量(4) 常量无unsigned型但一个非负值的整数可以赋值给unsigned整型变量,只要它的范围不超过变量的取值范围即可一个整型常量可以用3种不同的方式表示: (1) 十进制整数如1357,-432,0等在一个整型常量后面加一个字母l或L,则认为是long int型常量例如123L,421L,0L等,这往往用于函数调用中如果函数的形参为long int,则要求实参也为long int型,此时用123作实参不行,而要用123L作实参(2) 八进制整数在常数的开头加一个数字0,就表示这是以八进制数形式表示的常数如020表示这是八进制数20,即(20)8,它相当于十进制数16(3) 十六进制整数在常数的开头加一个数字0和一个英文字母X(或x),就表示这是以十六进制数形式表示的常数如0X20表示这是十六进制数20,即(20)16,它相当于十进制数322. 浮点数的表示方法一个浮点数可以用两种不同的方式表示: (1) 十进制小数形式如21.456,-7.98等它一般由整数部分和小数部分组成,可以省略其中之一(如78.或.06,.0),但不能二者皆省略C+编译系统把用这种形式表示的浮点数一律按双精度常量处理,在内存中占8个字节如果在实数的数字之后加字母F或f,表示此数为单精度浮点数,如1234F,-43f,占4个字节如果加字母L或l,表示此数为长双精度数(long double),在GCC中占12个字节,在Visual C+ 6.0中占8个字节(2) 指数形式(即浮点形式)一个浮点数可以写成指数形式,如3.14159可以表示为0.314159101,3.14159100,31.415910-1,314.15910-2等形式在程序中应表示为: 0.314159e1,3.14159e0,31.4159e-1 ,314.159e-2,用字母e表示其后的数是以10为底的幂,如e12表示1012其一般形式为数符 数字部分 指数部分上面各数据中的0.314159,3.14159, 31.4159, 314.159 等就是其中的数字部分可以看到: 由于指数部分的存在,使得同一个浮点数可以用不同的指数形式来表示,数字部分中小数点的位置是浮动的例如: a=0.314159e1;a=3.14159e0;a=31.4159e-1;a=314.159e-2;以上4个赋值语句中,用了不同形式的浮点数,但其作用是相同的在程序中不论把浮点数写成小数形式还是指数形式,在内存中都是以指数形式(即浮点形式)存储的例如不论在程序中写成314.159或314.159e0,31.4159e1,3.14159e2, 0.314159e3等形式,在内存中都是以规范化的指数形式存放,如图2.3所示图2.3数字部分必须小于1,同时,小数点后面第一个数字必须是一个非0数字,例如不能是0.0314159因此314.159和314.159e0,31.4159e1,3.14159e2, 0.314159e3在内存中表示成0.314159103存储单元分为两部分,一部分用来存放数字部分,一部分用来存放指数部分为便于理解,在图2.3中是用十进制表示的,实际上在存储单元中是用二进制数来表示小数部分,用2的幂次来表示指数部分的对于以指数形式表示的数值常量,也都作为双精度常量处理 2.2.3 字符常量1. 普通的字符常量用单撇号括起来的一个字符就是字符型常量如a,#,%,D都是合法的字符常量,在内存中占一个字节注意: 字符常量只能包括一个字符,如AB 是不合法的字符常量区分大小写字母,如A和a是两个不同的字符常量撇号()是定界符,而不属于字符常量的一部分如couta;输出的是一个字母“a”,而不是3个字符“a ”2. 转义字符常量除了以上形式的字符常量外,C+还允许用一种特殊形式的字符常量,就是以 “”开头的字符序列例如,n代表一个“换行”符“coutn; ” 将输出一个换行,其作用与“coutendl; ” 相同这种“控制字符”,在屏幕上是不能显示的在程序中也无法用一个一般形式的字符表示,只能采用特殊形式来表示常用的以“”开头的特殊字符见书中表2.23. 字符数据在内存中的存储形式及其使用方法将一个字符常量存放到内存单元时,实际上并不是把该字符本身放到内存单元中去,而是将该字符相应的ASCII代码放到存储单元中如果字符变量c1的值为a,c2的值为b,则在变量中存放的是a的ASCII码97,b 的ASCII码98,如图2.4(a)所示,实际上在内存中是以二进制形式存放的,如图2.4(b)所示图2.4既然字符数据是以ASCII码存储的,它的存储形式就与整数的存储形式类似这样,在C+中字符型数据和整型数据之间就可以通用一个字符数据可以赋给一个整型变量,反之,一个整型数据也可以赋给一个字符变量也可以对字符数据进行算术运算,此时相当于对它们的ASCII码进行算术运算例2.1 将字符赋给整型变量#include using namespace std;int main( ) int i,j; /i和j是整型变量i=A; /将一个字符常量赋给整型变量ij=B; /将一个字符常量赋给整型变量jcouti jn; /输出整型变量i和j的值,n 是换行符return 0;执行时输出 65 66i和j被指定为整型变量但在第5和第6行中,将字符A和B分别赋给i和j,它的作用相当于以下两个赋值语句:i=65;j=66;因为A和B的ASCII码为65和66在程序的第5和第6行是把65和66直接存放到i和j的内存单元中因此输出65和66可以看到:在一定条件下,字符型数据和整型数据是可以通用的但是应注意字符数据只占一个字节,它只能存放0255范围内的整数例2.2 字符数据与整数进行算术运算下面程序的作用是将小写字母转换为大写字母#include using namespace std;int main( )char c1,c2; c1=a; c2=b; c1=c1-32; c2=c2-32; coutc1 c2endl; return 0;运行结果为A Ba的ASCII码为97,而A的ASCII码为65,b为98,B为66从ASCII代码表中可以看到每一个小写字母比它相应的大写字母的ASCII代码大32C+符数据与数值直接进行算术运算,a-32得到整数65,b-32得到整数66将65和66存放在c1,c2中,由于c1,c2是字符变量,因此用cout输出c1,c2时,得到字符A和B(A的ASCII码为65,B的ASCII码为66)4. 字符串常量用双撇号括起来的部分就是字符串常量,如abc,Hello!,a+b,Liping都是字符串常量字符串常量abc在内存中占4个字节(而不是3个字节),见图2.5图2.5编译系统会在字符串最后自动加一个0作为字符串结束标志但0并不是字符串的一部分,它只作为字符串的结束标志如coutabcendl;输出3个字符abc,而不包括0注意: a和a代表不同的含义,a是字符串常量,a 是字符常量前者占两个字节,后者占1个字节请分析下面的程序片段: char c;/定义一个字符变量c=a;/正确c=a; /错误,c只能容纳一个字符字符串常量要用字符数组来存放,见第5章请思考: 字符串常量abcn包含几个字符?不是5个而是4个字符,其中“n”是一个转义字符但它在内存中占5个字节(包括一个“0”字符) 编译系统遇到“”时就会把它认作转义字符的标志,把它和其后的字符一起作为一个转义字符如果“”后面的字符不能与“”组成一个合法的转义字符(如c),则在编译时显示出错信息如果希望将“”字符也作为字符串中的一个字符,则应写为abcn,此时字符包括5个字符,即a,b,c,n如果有以下输出语句:coutabcnendl;则会输出: abc,然后换行同理执行coutI say Thank you!n;的输出是: I say Thank you!如果在一个字符串中最后一个字符为“”,则表示它是续行符,下一行的字符是该字符串的一部分,且在两行字符串间无空格如coutWe must study C/本行最后的“”后面的空格和换行均不起作用+ hard!;/本行的字符紧连在上一行最后的“”前面字符之后则输出: We must study C+ hard!2.2.4 符号常量为了编程和阅读的方便,在C+程序设计中,常用一个符号名代表一个常量,称为符号常量,即以标识符形式出现的常量例2.3 符号常量的使用#define PRICE 30 /注意这不是语句,末尾不要加分号int main ( ) int num,total;num=10;total=num * PRICE;couttotal=totalendl;return 0; 程序中用预处理命令#define指定PRICE在本程序单位中代表常量30,此后凡在本程序单位中出现的PRICE都代表30,可以和常量一样进行运算,程序运行结果为 total=300 请注意符号常量虽然有名字,但它不是变量它的值在其作用域(在本例中为主函数)内是不能改变的,也不能被赋值如用赋值语句“PRICE=40;”给PRICE赋值是错误的 使用符号常量的好处是:(1) 含义清楚(2) 在需要改变一个常量时能做到“一改全改” 如#define PRICE 352.3 变量2.3.1 什么是变量其实在前面的例子中已经多次用到了变量在程序运行期间其值可以改变的量称为变量一个变量应该有一个名字,并在内存中占据一定的存储单元,在该存储单元中存放变量的值请注意区分变量名和变量值这两个不同的概念,见图2.6图2.62.3.2 变量名规则先介绍标识符的概念和其他高级语言一样,用来标识变量符号常量函数数组类型等实体名字的有效字符序列称为标识符(identifier)简单地说,标识符就是一个名字变量名是标识符的一种,变量的名字必须遵循标识符的命名规则C+规定标识符只能由字母数字和下划线3种字符组成,且第一个字符必须为字母或下划线下面列出的是合法的标识符,也是合法的变量名:sum, average, total, day, month, Student_name, tan, BASIC, li_ling下面是不合法的标识符和变量名:M.D.John, $123, #33, 3G64, Ling li, C+, Zhang-ling, U.S.A.注意,在C+中,大写字母和小写字母被认为是两个不同的字符因此,sum和SUM是两个不同的变量名一般地,变量名用小写字母表示,与人们日常习惯一致,以增加可读性应注意变量名不能与C+的关键字系统函数名和类名相同在国外软件开发工作中,常习惯在变量前面加一个字母以表示该变量的类型,如iCount表示这是一个整型变量,cSex表示这是一个字符型变量C+没有规定标识符的长度(字符个数),但各个具体的C编译系统都有自己的规定有的系统取32个字符,超过的字符不被识别2.3.3 定义变量在C+语言中,要求对所有用到的变量作强制定义,也就是必须“先定义,后使用”,如例2.2和例2.3那样定义变量的一般形式是 变量类型 变量名表列;变量名表列指的是一个或多个变量名的序列如float a,b,c,d,e;定义a,b,c,d,e为单精度型变量,注意各变量间以逗号分隔,最后是分号可以在定义变量时指定它的初值如 float a=83.5,b,c=64.5,d=81.2,e; /对变量a,c,d指定了初值,b和d未指定初值C语言要求变量的定义应该放在所有的执行语句之前,而C+则放松了限制,只要求在第一次使用该变量之前进行定义即可也就是说,它可以出现在语句的中间,如int a;/定义变量a(在使用a之前定义)a=3; /执行语句,对a赋值float b; /定义变量b(在使用b之前定义)b=4.67; /执行语句,对b赋值char c; /定义变量c(在使用c之前定义)c=A; /执行语句 ,对c赋值C+要求对变量作强制定义的目的是:(1) 凡未被事先定义的,不作为变量名,这就能保证程序中变量名使用得正确例如,如果在声明部分写了int student;而在执行语句中错写成statent如statent=30;在编译时检查出statent未经定义,作为错误处理输出“变量statent未经声明”的信息,便于用户发现错误,避免变量名使用时出错(2) 每一个变量被指定为一确定类型,在编译时就能为其分配相应的存储单元如指定a和b为int型,一般的编译系统对其各分配4个字节,并按整数方式存储数据(3) 指定每一变量属于一个特定的类型,这就便于在编译时,据此检查该变量所进行的运算是否合法例如,整型变量a和b,可以进行求余运算:a%b%是“求余”(见2.4 节),得到a/b的余数如果将a和b指定为实型变量,则不允许进行“求余”运算,在编译时会给出有关的出错信息2.3.4 为变量赋初值 允许在定义变量时对它赋予一个初值,这称为变量初始化初值可以是常量,也可以是一个有确定值的表达式如float a,b=5.78*3.5,c=2*sin(2.0);表示定义了a,b,c为单精度浮点型变量,对b初始化为5.78*3, 对c初始化为2*sin(2.0),在编译连接后,从标准函数库得到正弦函数sin(2.0)的值,因此变量c有确定的初值变量a未初始化如果对变量未赋初值,则该变量的初值是一个不可预测的值,即该存储单元中当时的内容是不知道的例如,若未对a和b赋值,执行输出语句couta b cendl;输出结果可能为1.48544e-38 15 1.81858(各次运行情况可能不同)初始化不是在编译阶段完成的(只有在第4章中介绍的静态存储变量和外部变量的初始化是在编译阶段完成的),而是在程序运行时执行本函数时赋予初值的,相当于执行一个赋值语句例如,int a=3;相当于以下两个语句 :int a; / 指定a为整型变量a=3;/ 赋值语句,将3赋给a 对多个变量赋予同一初值,必须分别指定,不能写成float a=b=c=4.5;而应写成 float a=4.5,b=4.5,c=4.5;或float a,b,c=4.5;a=b=c;2.3.5 常变量在定义变量时,如果加上关键字const,则变量的值在程序运行期间不能改变,这种变量称为常变量(constant variable)例如,const int a=3; /用const来声明这种变量的值不能改变,指定其值始终为3在定义常变量时必须同时对它初始化(即指定其值),此后它的值不能再改变常变量不能出现在赋值号的左边例如上面一行不能写成const int a;a=3; /常变量不能被赋值可以用表达式对常变量初始化,如const int b=3+6,c=3*cos(1.5);/b的值被指定为9,c的值被指定为3*cos(1.5)但应注意,由于使用了系统标准数学函数cos,必须将包含该函数有关的信息的头文件“cmath”(或math.h)包含到本程序单位中来,可以在本程序单位的开头加上以下#include命令:#include 或 #include 变量的值应该是可以变化的,怎么值是固定的量也称变量呢?其实,从计算机实现的角度看,变量的特征是存在一个以变量名命名的存储单元,在一般情况下,存储单元中的内容是可以变化的对常变量来说,无非在此变量的基础上加上一个限定: 存储单元中的值不允许变化因此常变量又称为只读变量(read-only-variable)请区别用#define命令定义的符号常量和用const定义的常变量符号常量只是用一个符号代替一个字符串,在预编译时把所有符号常量替换为所指定的字符串,它没有类型,在内存中并不存在以符号常量命名的存储单元而常变量具有变量的特征,它具有类型,在内存中存在着以它命名的存储单元,可以用sizeof运算符测出其长度与一般变量惟一的不同是指定变量的值不能改变用#define命令定义符号常量是C语言所采用的方法,C+把它保留下来是为了和C兼容C+的程序员一般喜欢用const定义常变量虽然二者实现的方法不同,但从使用的角度看,都可以认为用了一个标识符代表了一个常量有些书上把用const定义的常变量也称为定义常量,但读者应该了解它和符号常量的区别2.4 C+的运算符C+的运算符十分丰富,使得C+的运算十分灵活方便例如把赋值号(=)也作为运算符处理,这样,a=b=c=4就是合法的表达式,这是与其他语言不同的C+提供了以下运算符:(1) 算术运算符 +(加)-(减) *(乘) /(除) %(整除求余)+(自加) -(自减)(2) 关系运算符(大于)=(大于或等于)=(小于或等于)!=(不等于)(3) 逻辑运算符 &(逻辑与) |(逻辑或) !(逻辑非)(4) 位运算符 (按位右移) &(按位与) |(按位或) (按位异或) (按位取反)(5) 赋值运算符 (=及其扩展赋值运算符)(6) 条件运算符 (?:)(7) 逗号运算符 (,)(8) 指针运算符 (*)(9)引用运算符和地址运算符 (&)(10) 求字节数运算符(sizeof)(11) 强制类型转换运算符( (类型) 或类型( )(12) 成员运算符 (.)(13) 指向成员的运算符 (-)(14) 下标运算符 ( )(15) 其他 (如函数调用运算符()2.5 算术运算符与算术表达式2.5.1 基本的算术运算符在本章中主要介绍算术运算符与算术表达式,赋值运算符与赋值表达式,逗号运算符与逗号表达式,其他运算符将在以后各章中陆续介绍+(加法运算符,或正值运算符如3+5,+3)-(减法运算符,或负值运算符如5-2,-3)* (乘法运算符如3*5)/(除法运算符如5/3)%(模运算符,或称求余运算符,%两侧均应为整型数据,如7%4的值为3)需要说明,两个整数相除的结果为整数,如5/3的结果值为1,舍去小数部分但是,如果除数或被除数中有一个为负值,则舍入的方向是不固定的例如,-5/3在有的C+系统上得到结果-1,有的C+系统则给出结果-2多数编译系统采取“向零取整”的方法,即5/3的值等于1,-5/3的值等于-1,取整后向零靠拢如果参加+, -, *, / 运算的两个数中有一个数为float型数据,则运算的结果是double型,因为C+在运算时对所有float型数据都按double型数据处理2.5.2 算术表达式和运算符的优先级与结合性用算术运算符和括号将运算对象(也称操作数)连接起来的符合C+语法规则的式子,称C+算术表达式运算对象包括常量变量函数等例如,下面是一个合法的C+算术表达式:a*b/c-1.5+aC+语言规定了运算符的优先级和结合性在求解表达式时,先按运算符的优先级别高低次序执行,例如先乘除后加减如有表达式a-b*c,b的左侧为减号,右侧为乘号,而乘号优先于减号,因此,相当于a-(b*c)如果在一个运算对象两侧的运算符的优先级别相同,如a-b+c,则按规定的“结合方向”处理C+规定了各种运算符的结合方向(结合性),算术运算符的结合方向为“自左至右”,即先左后右,因此b先与减号结合,执行a-b的运算,再执行加c的运算“自左至右的结合方向”又称“左结合性”,即运算对象先与左面的运算符结合以后可以看到有些运算符的结合方向为“自右至左”,即右结合性(例如赋值运算符)关于“结合性”的概念在其他一些高级语言中是没有的,是C和C+的特点之一,希望能弄清楚附录B列出了所有运算符以及它们的优先级别和结合性2.5.3 表达式中各类数值型数据间的混合运算在表达式中常遇到不同类型数据之间进行运算,如10+a+1.5-8765.1234*b在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算转换的规则按图2.7所示图2.7假设已指定i为整型变量,f为float变量,d为double型变量,e为long型,有下面表达式:10+a+i*f-d/e运算次序为: 进行10+a的运算,先将a转换成整数97,运算结果为107进行i*f的运算先将i与f都转换成double型,运算结果为double型整数107与i*f的积相加先将整数107转换成双精度数(小数点后加若干个0,即107.00000),结果为double型将变量e转换成double型,d/e结果为double型将10+a+i*f的结果与d/e的商相减,结果为double型上述的类型转换是由系统自动进行的2.5.4 自增和自减运算符在C和C+中,常在表达式中使用自增(+)和自减(-)运算符,他们的作用是使变量的值增1或减1,如+i(在使用i之前,先使i的值加1,如果i的原值为3,则执行j=+i后,j的值为4)-i (在使用i之前,先使i的值减1,如果i的原值为3,则执行j=-i后,j的值为2)i+ (在使用i之后,使i的值加1,如果i的原值为3,则执行j=i+后,j的值为3,然后i变为4)i-(在使用i之后,使i的值减1,如果i的原值为3,则执行j=i-后,j的值为3,然后i变为2)+i是先执行i=i+1后,再使用i的值;而i+是先使用i的值后,再执行i=i+1正确地使用+和-,可以使程序简洁清晰高效请注意:(1) 自增运算符(+)和自减运算符(-)只能用于变量,而不能用于常量或表达式(2) +和-的结合方向是“自右至左”,见附录B(3) 自增运算符(+)和自减运算符(-)使用十分灵活,但在很多情况下可能出现歧义性,产生“意想不到”的副作用(4) 自增(减)运算符在C+程序中是经常见到的,常用于循环语句中,使循环变量自动加1也用于指针变量,使指针指向下一个地址2.5.5 强制类型转换运算符在表达式中不同类型的数据会自动地转换类型,以进行运算有时程序编制者还可以利用强制类型转换运算符将一个表达式转换成所需类型例如:(double)a (将a转换成double类型)(int)(x+y) (将x+y的值转换成整型)(float)(5%3) (将5%3的值转换成float型)强制类型转换的一般形式为(类型名)(表达式)注意: 如果要进行强制类型转换的对象是一个变量,该变量可以不用括号括起来如果要进行强制类型转换的对象是一个包含多项的表达式,则表达式应该用括号括起来如果写成 (int)x+y则只将x转换成整型,然后与y相加以上强制类型转换的形式是原来C语言使用的形式,C+把它保留了下来,以利于兼容C+还增加了以下形式: 类型名(表达式)如int(x) 或 int(x+y)类型名不加括号,而变量或表达式用括号括起来这种形式类似于函数调用但许多人仍习惯于用第一种形式,把类型名包在括号内,这样比较清楚需要说明的是在强制类型转换时,得到一个所需类型的中间变量,但原来变量的类型未发生变化例如:(int)x如果x原指定为float型,值为3.6,进行强制类型运算后得到一个i
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑环境 > 建筑工程


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

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


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