好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

C++程序设计(谭浩强完整版).ppt

930页
  • 卖家[上传人]:cl****1
  • 文档编号:587830784
  • 上传时间:2024-09-06
  • 文档格式:PPT
  • 文档大小:8.66MB
  • / 930 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    •                         C++程序设计程序设计                           谭浩强编著谭浩强编著                                  清华大学出版社清华大学出版社                                       课件制作:南京理工大学课件制作:南京理工大学 陈清华陈清华 朱红朱红1 第一章第一章C++概述概述 C++语言发展历史语言发展历史     自从自从1946年第一台电子数字计算机年第一台电子数字计算机ENIAC问世以来,随着计算机应用领域的不断扩大,问世以来,随着计算机应用领域的不断扩大,促进了计算机技术的高速发展,尤其是近年促进了计算机技术的高速发展,尤其是近年来计算机的硬件和软件都是日新月异作为来计算机的硬件和软件都是日新月异作为应用计算机的一种工具应用计算机的一种工具—程序设计语言,得程序设计语言,得到不断的充实和完善每年都有新的程序设到不断的充实和完善每年都有新的程序设计语言问世,老的程序设计语言不断地更新计语言问世,老的程序设计语言不断地更新换代 2 20世世纪纪60年年代代,,Martin Richards为为计计算算机机软软件件人人员员在在开开发发系系统统软软件件时时,,作作为为记记述述语语言言使使用用而而开开发发了了BCPL语语言言(Basic Combined Programming Language)。

      1970年年,,Ken Thompson在在继继承承BCPL语语言言的的许许多多优优点点的的基基础础上上发发明明了了实实用用的的B语语言言到到了了1972年年,,贝贝尔尔实实验验室室的的Dennis Ritchie和和Brian kernighan在在B语语言言的的基基础础上上,作作了了进进一一步步的的充充实实和和完完善善,,设设计计出出了了C语语言言当当时时,,设设计计C语语言言是是为为了了编编写写UNIX操操作作系系统统的的以以后后,C语语言言经经过过多多次次改改进进,并并开开始始流流行行C++是是在在C语语言言的的基基础础上上发发展展和和完完善善的的,,而而C是是吸收了其它语言的优点逐步成为实用性很强的语言吸收了其它语言的优点逐步成为实用性很强的语言3 C语言的主要特点是:语言的主要特点是:1、、C语语言言是是一一种种结结构构化化的的程程序序设设计计语语言言,,语语言言本本身身简简洁洁、、使使用用灵灵活活方方便便既既适适用用于于设设计计和和编编写写大大的的系系统统程程序序,,又又适适用用于于编编写写小小的的控控制制程程序序,,也也适适用科学计算用科学计算2、、它它既既有有高高级级语语言言的的特特点点,,又又具具有有汇汇编编语语言言的的特特点点。

      运运算算符符丰丰富富,,除除了了提提供供对对数数据据的的算算术术逻逻辑辑运运算算外外,,还还提提供供了了二二进进制制的的位位运运算算并并且且也也提提供供了了灵灵活活的的数数据据结结构构用用C语语言言编编写写的的程程序序表表述述灵灵活活方方便便,,功功能能强强大大用用C语语言言开开发发的的程程序序,,其其结结构构性性好好,,目目标程序质量高,程序执行效率高标程序质量高,程序执行效率高4 3、、程程序序的的可可移移植植性性好好用用C语语言言在在某某一一种种型型号号的的计计算算机机上上开开发发的的程程序序,,基基本本上上可可以以不不作作修修改改,,而而直直接接移植到其它型号和不同档次的计算机上运行移植到其它型号和不同档次的计算机上运行4、、程程序序的的语语法法结结构构不不够够严严密密,,程程序序设设计计的的自自由由度度大大这这对对于于比比较较精精通通C语语言言的的程程序序设设计计者者来来说说,,可可以以设设计计出出高高质质量量的的非非常常通通用用的的程程序序但但对对于于初初学学者者来来说说,,要要能能比比较较熟熟练练运运用用C语语言言来来编编写写程程序序,,并并不不是是一一件件容容易易的的事事情情。

      与与其其它它高高级级语语言言相相比比而而言言,,调调试试程程序序比比较较困困难难往往往往是是编编好好程程序序输输入入计计算算机机后后,,编编译译时时容容易易通通过过,,而而在在执执行行时时还还会会出出错错但但只只要要对对C语语言言的的语语法法规规则则真真正正领领会会,,编编写写程程序序及及调调试试程程序序还是比较容易掌握的还是比较容易掌握的5 随随着着C语语言言应应用用的的推推广广,,C语语言言存存在在的的一一些些缺缺陷陷或或不不足足也也开开始始流流露露出出来来,,并并受受到到大大家家的的关关注注如如::C语语言言对对数数据据类类型型检检查查的的机机制制比比较较弱弱;;缺缺少少支支持持代代码码重重用用的的结结构构;;随随着着软软件件工工程程规规模模的的扩扩大大,,难难以以适适应应开开发发特大型的程度等等特大型的程度等等6 为为了了克克服服C语语言言本本身身存存在在的的缺缺点点,,并并保保持持C语语言言简简洁洁、、高高效效,,与与汇汇编编语语言言接接近近的的特特点点,,1980年年,,贝贝尔尔实实验验室室的的Bjarne Stroustrup博博士士及及其其同同事事对对C语语言言进进行行了了改改进进和和扩扩充充,,并并把把Simula 67中中类类的的概概念念引引入入到到C中中。

      并并在在1983年年由由Rick Maseitti提提议议正正式式命命名名为为C++((C Plus Plus))后后来来,,又又把把运运算算符符的的重重载载、、引引用用、、虚虚函函数数等等功功能能加加入入到到C++中中,,使使C++的的功能日趋完善功能日趋完善当当前前用用得得较较为为广广泛泛的的C++有有::VC++ ((Visual C Plus  Plus))、、  BC++((Borland  C  Plus  Plus))、、AT&T C++等7 简单的简单的C++程序介绍程序介绍高级语言编译过程高级语言编译过程源程序源程序(文本文件)(文本文件)*.CPP目标文件目标文件(二进制文件)(二进制文件)*.OBJ可执行文件可执行文件(二进制文件)(二进制文件)*.EXE库文件库文件(各种函数)(各种函数)在在Vitual C++系统中,可直接从源程序编译连接至可执行系统中,可直接从源程序编译连接至可执行程序,但依然要生成程序,但依然要生成*.OBJ及及*.EXE这两个文件这两个文件F7编译编译连接连接compilelink8 一个简单的一个简单的C++程序程序#includevoid  main(void ){   cout<<“I am a student.\n”;  //输出字符串输出字符串}主函数主函数函数体函数体开始开始函数体函数体结束结束输出流,在屏幕上打输出流,在屏幕上打印引号内的字符串印引号内的字符串分号,一条完整分号,一条完整语句的结束符语句的结束符本程序编译执行后,在本程序编译执行后,在DOS屏幕上打印出屏幕上打印出 I  am  a student.包含文件包含文件注释或说明注释或说明9 编译过程:编译过程:1)启动)启动Visual C++,选择选择“文件文件”菜单中的菜单中的“新建新建”命令,选择命令,选择“文件文件”标签中的标签中的“C++ Source File”选项。

      选项2)选择源程序存放的目录和输入源程序名,单击)选择源程序存放的目录和输入源程序名,单击“确定确定”3))在在编辑器中编写源程序编辑器中编写源程序4)单击)单击F7或或“编译编译”中的中的“重建全部重建全部”编译源程编译源程序,若编译通过,单击序,若编译通过,单击“执行执行”,在,在DOS屏上看屏上看结果结果,,任按一键返回编辑器任按一键返回编辑器10 启动启动VC++编译系统编译系统11 VC++编译编译系统界面系统界面单击单击“File”菜菜单中单中“New”命命令令12 选择选择“Files”选项选项卡卡选择选择C++源源文件命令文件命令输入文件名输入文件名输入文件输入文件存放位置存放位置单击选择单击选择驱动器驱动器选择驱动选择驱动器或目录器或目录13 C++源文件源文件编辑界面编辑界面输入输入C++源代码源代码14 可以将此源可以将此源代码另起文代码另起文件名存盘件名存盘15 选择编译命令,将源文选择编译命令,将源文件件.cpp生成生成.obj文件文件16 如果编译出错,会出现提示信息,如果编译出错,会出现提示信息,指出错误的位置及种类指出错误的位置及种类错误所在行错误所在行错误的原因错误的原因17 双击错误双击错误所在行所在行光标移到该行光标移到该行18 生成可执生成可执行文件行文件通过后单通过后单击该命令击该命令运行程序运行程序19 运行结果显示运行结果显示在在DOS屏上屏上注意:不可以在软盘上注意:不可以在软盘上运行程序!应该把保存运行程序!应该把保存在软盘中的源文件拷贝在软盘中的源文件拷贝到硬盘的目录中再运行到硬盘的目录中再运行!20 源程序所在目录源程序所在目录未编译前,只未编译前,只有一个源程序有一个源程序21 编译运行后,出编译运行后,出现众多附加文件现众多附加文件同时,产生一个同时,产生一个子目录子目录Debug22 Debug目录中,有目录中,有obj和和EXE文件文件23 #include  void  main(void){  cout << ““i=””;   //显示提示符显示提示符  int i;          //说明变量说明变量i  cin  >>i;       //从键盘上输入变量从键盘上输入变量i的值的值  cout << “i的的值值为为::” <

      一般用四个字节表示整一般用四个字节表示整数举例举例)内存内存CPU内存内存data外存外存Program8硬盘硬盘 软盘软盘26 1514 13 12 11 109876543210有符号数有符号数无符号数无符号数0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 132767327670 1 1 1 1 1 1 1 1 1 1 1 1 1 1 03276632766…………0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1110 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0001 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1-1(补码补码)655351 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0-265534…………1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1-32767327691 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0-327683276827 常量与变量常量与变量常量:在程序运行过程中,其值一直保持不变的量常量:在程序运行过程中,其值一直保持不变的量为常量常量也区分不同的类型:常量也区分不同的类型:30,,40 为整型,为整型,30.0,,40.0为实型,为实型,编辑器只是根据其表面形式来判断其编辑器只是根据其表面形式来判断其类型。

      类型变量:在程序运行过程中,其值可以改变的量为变量:在程序运行过程中,其值可以改变的量为变量变量在程序的执行中能够赋值,发生变化变量在程序的执行中能够赋值,发生变化变量有一个名字,有一个名字,并在使用之前要说明其类型并在使用之前要说明其类型,一经,一经说明,说明,就在内存中占据与其类型相应的存储单元就在内存中占据与其类型相应的存储单元28 #include#define  PRICE   30  //常量,在程序中保持不变常量,在程序中保持不变void main(void){    int  num, total;  //定义变量定义变量,在内存中开辟区间在内存中开辟区间      num=10;        //变量赋值变量赋值,10为常量为常量     total=num*PRICE;     cout<<“total=“<

      序的基本前提30 变量名的命名方法:变量名的命名方法:变量名、数组名、函数名变量名、数组名、函数名…称为称为标识符标识符标识符只能由标识符只能由字母、数字、下划线字母、数字、下划线这三种字符组成,且第这三种字符组成,且第一个字符必须为字母或下划线,长度不大于一个字符必须为字母或下划线,长度不大于247个字符,个字符,大小写不通用大小写不通用关键字不能作为标识符)关键字不能作为标识符)关键字即是关键字即是VC++的语法要求中使用的字的语法要求中使用的字如如 int  if   while 等 正确的标识符:正确的标识符:INT,   sum ,  de12,   SUM等变量必须使变量必须使用前定义,以分配空间用前定义,以分配空间举例说明举例说明31 abc   English 2xy x-y if Else b(3) ‘def’ Chine_bb    b3y   AbsFloat   float一般变量都是用匈牙利命名法命名的一般变量都是用匈牙利命名法命名的int nCount; char  chChoice;32 整型数据整型数据整型常量:整型常量:常量是根据其表面形式来判定,整型量即是没有小数点的常量是根据其表面形式来判定,整型量即是没有小数点的整数,范围:整数,范围:-231~((231-1)) ,有三种形式,有三种形式:1)十进制(默认方式))十进制(默认方式)43   1345   876542)八进制)八进制     以以0开头开头               043,, 056,, 0113)十六进制)十六进制  以以0x开头开头      0x12      0xa3     0x34       0xdf(举例说明)(举例说明)33 #includevoid main(void){int int10,int8,int16;  //定义定义3个整型变量个整型变量int10=10;//默认为十进制默认为十进制int8=010;//八进制八进制int16=0x10;//十六进制十六进制cout<<"int10="<

      分为有符号型与无符号型有符号型:有符号型:          short 在内存中占两个字节,范围为在内存中占两个字节,范围为-215~((215-1)) int 在内存中占四个字节,范围为在内存中占四个字节,范围为-231~((231-1))long在内存中占四个字节,范围为在内存中占四个字节,范围为-2-31~231-1无符号型:无符号型:最高位不表示符号位最高位不表示符号位unsigned  short 在内存中占两个字节,范围为在内存中占两个字节,范围为0~216-1unsigned int  在内存中占四个字节,范围为在内存中占四个字节,范围为0~232-1unsigned  long在内存中占四个字节,范围为在内存中占四个字节,范围为0~232-135 1))整型常量整型常量亦有长短之分,常量中无亦有长短之分,常量中无unsigned型,但一型,但一个非负的整型常量可以赋给个非负的整型常量可以赋给unsigned型的变量型的变量 2)若一个常量定义为长整型数,则在其后加)若一个常量定义为长整型数,则在其后加l或或L进行区进行区分如:如:32l    32L    564L等,内存为其分配四个字节存储。

      等,内存为其分配四个字节存储  一个数在内存中为一个数在内存中为1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1当这个数为有符号数时,是当这个数为有符号数时,是-1;为无符号数时,是;为无符号数时,是232-1内存中的数是以内存中的数是以补码补码的形式存放的举例说明)的形式存放的举例说明)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 136 #include void main(){ unsigned short a;  short int b= -1;  a=b;  cout<<"a="<

      面必须是整数实型变量分单精度实型变量分单精度 float 和双精度和双精度 double 两种形式:两种形式:float:占四个字节,提供占四个字节,提供7~8位有效数字位有效数字double: 占八个字节,提供占八个字节,提供15~16位有效数字位有效数字举例说明举例说明38 #includevoid main(void){float   a,  b;double   c,  d;a=0.01;b=3.45678e-2;c=3.45678e-2;d=9.7654e-5;cout<<"a="<

      称为尾数,尾数决定有效数字,即数字的精度J   表示指数(阶码)表示指数(阶码)R  是基数,可取是基数,可取2,,4,,8,,16等,对具体机器而言,基数等,对具体机器而言,基数取好后,就不能再变了取好后,就不能再变了数有正有负数有正有负, 所以设置数符所以设置数符; 阶码亦有正负阶码亦有正负, 所以设置阶所以设置阶符符40 一般用一般用4个字节表示一个浮点数,也有用个字节表示一个浮点数,也有用8个字个字节表示的节表示的字长一定,尾数越多,精度越高;阶码越多,字长一定,尾数越多,精度越高;阶码越多,范围越大范围越大当计算机中出现小于机器所能表示的最小数当计算机中出现小于机器所能表示的最小数时,机器只能当零来处理时,机器只能当零来处理,,当出现超过机器所能当出现超过机器所能表示的最大数时,出现溢出现象表示的最大数时,出现溢出现象,一旦出现溢出,,一旦出现溢出,就会停止运算就会停止运算定点数,浮点数均会出现溢出现定点数,浮点数均会出现溢出现象41 字符型数据(字符型数据(char)字符型数据实际上是作为字符型数据实际上是作为整型数据整型数据在内存中存储的在内存中存储的计算机是以字符编码的形式处理字符的,因此,我们在计算机内部计算机是以字符编码的形式处理字符的,因此,我们在计算机内部是以是以ASCII码码的形式表示所有字符的。

      所以的形式表示所有字符的所以7位二进制数即可表示出位二进制数即可表示出一个字符,一个字符,我们用一个字节的容量(我们用一个字节的容量(8位)存储一个字符位)存储一个字符例如:字符例如:字符A的的ASCII码为码为0x41或或65,在内存中表示为:,在内存中表示为:01000001在程序中表示为:在程序中表示为:char   grade ;//定义一个字符型的变量空间定义一个字符型的变量空间(1个字节个字节)grade=‘A’;  //必须用必须用‘   ’表示,否则易与标识符混同表示,否则易与标识符混同     ‘ ’内括起来的字符表示该字符的内括起来的字符表示该字符的ASCII码42 进一步,由于在内存中的形式与整型数据相同,所以,进一步,由于在内存中的形式与整型数据相同,所以,可以直接用可以直接用其整型值给变量赋值其整型值给变量赋值char   grade;grade=65;以下的赋值形式均是等同的以下的赋值形式均是等同的grade='A';           grade=65 ;         grade=0x41;         grade=0101;#includevoid main(void){   char a,b;   a=‘A’;   //输入输入ASCII码码   b=65;   //输入十进制数输入十进制数   cout<<"a="<

      如回车、退格等,可用两种方式表示这些字符1)用)用ASCII码的形式码的形式          char   re=13;2)用转义字符)用转义字符               char   re=‘\n’;((p15)44 转义字符转义字符含含         义义  ASCII代码代码\a响铃响铃7\n\n换行,将当前位置移到下一行开头换行,将当前位置移到下一行开头10\t\t水平制表(跳到下一个水平制表(跳到下一个tab位置)位置)9\b\b退格,将当前位置移到前一列退格,将当前位置移到前一列8\r\r回车,将当前位置移到本行开头回车,将当前位置移到本行开头13\f\f换页,将当前位置移到下页开头换页,将当前位置移到下页开头12\ v竖向跳格竖向跳格8 \\\\反斜杠字符反斜杠字符“\\”92\\′单引号(撇号)字符单引号(撇号)字符39\\"双引号字符双引号字符34\0空字符空字符0\\ddd1到到3位位8进制数所代表的字符进制数所代表的字符 \\xhh1到到2位位16进制数所代表的字符进制数所代表的字符 45 转义字符虽然包含转义字符虽然包含2个或多个字符,但它只代个或多个字符,但它只代表一个字符。

      表一个字符编译系统在见到字符编译系统在见到字符““\””时,时,会接着找它后面的字符,把它处理成一个字会接着找它后面的字符,把它处理成一个字符,在内存中只占一个字节符,在内存中只占一个字节 46 典型转义字符典型转义字符 ::‘\n’换行换行            ‘\b’ 退格退格              '\t'  下一下一个输出区个输出区若输出中包含这些特定格式,则再加一个若输出中包含这些特定格式,则再加一个\输出输出 c:\tc\tc    表示为表示为cout<<"c:\\tc\\tc";可以用转义字符表示任一一个可以用转义字符表示任一一个ASCII字符字符  ‘\ddd’ (八进制)八进制)        ‘\xhh‘ (十六进制)(十六进制)'\101'    '\x41'        '\x61'    '\141'    47 #includevoid main(void){   char c1,c2,c3,c4;   char n1,n2;   c1='a';//字符常量字符常量   c2=97;//十进制十进制   c3='\x61';//转义字符转义字符   c4=0141;//八进制八进制   cout<<"c1="<

      结束如:如:"CHINA"      0x430x480x490x550x41\0'a'在内存中占一个字节在内存中占一个字节              "a"占两个字节占两个字节aa\0实际上实际上内存是对应字符的内存是对应字符的ASCII码形式码形式010000110100100001001001010101010100000100000000CHINA\001100001011000010000000049 标识符常量标识符常量在在C++中中有有二二种种方方法法定定义义标标识识符符常常量量,,一一种种是是使使用用编编译译预预处理指令;另一种是使用处理指令;另一种是使用C++的常量说明符的常量说明符const例如:例如:     #define    PRICE  30 //在程序中凡是出现在程序中凡是出现PRICE均用均用30替代替代     #define    PI  3.1415926     #define    S   ““China””const float pi=3.1415926;  //将将变量变量pi定义为定义为常量常量(举例说明)(举例说明)50 #include#define PI 3.14156#define S  "China"void main(void){   const float pi=3.14156;//变量作为常量使用变量作为常量使用   cout<<"PI="<

      若合法,则指出常量的数据类型32767      35u     1.25e3.43L        0.0086e-32‘\87’ “Computer System”   “a”    ‘a’     ‘\96\45’-0+0.5-.56752 变量变量1) 在在程程序序的的执执行行过过程程中中,,其其值值可可以以改改变变的的量量称为变量称为变量2) 变量名必须用标识符来标识变量名必须用标识符来标识3) 变变量量根根据据其其取取值值的的不不同同值值域域,,分分为为不不同同类类型型的的变变量量::整整型型变变量量、、实实型型变变量量、、字字符符型型变变量、构造型变量、指针型变量等等量、构造型变量、指针型变量等等53 4) 对对于于任任一一变变量量,,编编译译程程序序要要为为其其分分配配若若干干个个字字节节((连连续续的的))的的内内存存单单元元,,以以便便保保存存变变量的取值量的取值5) 当当要要改改变变一一个个变变量量的的值值时时,,就就是是把把变变量量的的新新的的取取值值存存放放到到为为该该变变量量所所分分配配的的内内存存单单元元中中;;用用到到一一个个变变量量的的值值时时,,就就是是从从该该内内存存单单元中取出数据。

      元中取出数据6) 不不管管什什么么类类型型的的变变量量,,通通常常均均是是变变量量的的说说明在前,使用变量在后明在前,使用变量在后54 int i, j, k;//定义了三个整型变量定义了三个整型变量i,j,kfloat  x,y,z;//定义了三个实型变量定义了三个实型变量x,y,zchar   c1,c2;  //说明了二个字符型变量说明了二个字符型变量c1,c2double  dv1;;//说明了一个双精度型变量说明了一个双精度型变量dv1k四个字节的四个字节的连续空间连续空间j四个字节的四个字节的连续空间连续空间i四个字节的四个字节的连续空间连续空间z四个字节的四个字节的连续空间连续空间y四个字节的四个字节的连续空间连续空间x四个字节的四个字节的连续空间连续空间dv1八个字节的八个字节的连续空间连续空间c21个字节的个字节的空间空间c11个字节的个字节的空间空间开辟空间后开辟空间后, 空空间中为随机值间中为随机值55 变量赋初值变量赋初值在定义变量的在定义变量的同时同时给变量赋值,即在内存中开辟出一个空给变量赋值,即在内存中开辟出一个空间后马上给此空间赋值间后马上给此空间赋值但这个空间的值并不是固定不变的,但这个空间的值并不是固定不变的,在程序的运行中一样在程序的运行中一样可以改变。

      可以改变        char   a='\x64',  b='d';            int   a1=6,   a2=98;         a=‘A’;  b=‘\n’;                        a1=011;   a2=121;        int   a=4; //定义语句,在开辟空间后马上为空间赋定义语句,在开辟空间后马上为空间赋值值        a=6;        //重新为该空间赋值重新为该空间赋值a4 656 算术运算符和算术表达式算术运算符和算术表达式一、算术运算符和算术表达式一、算术运算符和算术表达式+    --   *    //    %  用算术运算符连接起来的式子是算术表达式用算术运算符连接起来的式子是算术表达式两个整数相除结果为整数两个整数相除结果为整数             1/2=0           5/2=2整数才可求余,余数的符号与左边数的符号相同整数才可求余,余数的符号与左边数的符号相同3%2=1      -3%2=-1         3%-2=1      -3%-2=-1      8%4=0二、优先级与结合性二、优先级与结合性()()      *        /       %           +       —57 三、强制转换类型三、强制转换类型(类型名)(表达式)(类型名)(表达式)((double)  a             (int) (x+y)          (int) 6.2%4=2在强制类型运算后原变量不变,但得到一个所需类在强制类型运算后原变量不变,但得到一个所需类型的中间变量。

      型的中间变量如:如:int  x;        float   y=5.8;        x=(int)y;x=5y=5.8y的值没有改的值没有改变,仍是单精变,仍是单精度浮点型度浮点型58 四、自增、自减运算符四、自增、自减运算符  (难点)难点)          ++      ----i6i37  int   i, j;  i=3;  j = ++i;i=4  j=4  ++在前在前, 先运算先运算,后赋后赋值值  int   i, j;  i=3;  j = i++;i=4 j=3 ++在后在后, 先赋值先赋值,后运后运算算j44i3j34i=6;   i++;   i=i+1     i=7                 ++i;      i=i+1    i=7 i=6;   i----;      i=i--1     i=5          ----i ;    i=i--1     i=5i6 759 1))自增、自减运算符只能用于变量,不可用于常量和表自增、自减运算符只能用于变量,不可用于常量和表达式达式因为表达式在内存内没有具体空间,常量所占的空间不能因为表达式在内存内没有具体空间,常量所占的空间不能重新赋值重新赋值3++      ((x+y)++      (--i)++若若i=3, j=2   (i++) +j  等于等于5i=4,  j=22)结合方式自右至左,优先级最高,向右取最大)结合方式自右至左,优先级最高,向右取最大--i++         --(i++)              i+++j         (i++) +j60 赋值运算符和赋值表达式赋值运算符和赋值表达式bmw=2002"="左边左边必须是变量名。

      必须是变量名若若“ = ” 两边变量类型不同,在赋值时要进两边变量类型不同,在赋值时要进行行类型转换类型转换转换原则:根据左边变量的类型转换转换原则:根据左边变量的类型转换61 少字节少字节多字节多字节1)若多字节变量为)若多字节变量为unsigned ,则转换后多余字节补则转换后多余字节补零0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1unsignedshort int  a=-1;unsigned  long   b;b=a;a ab b62 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1有符号型,符号扩展有符号型,符号扩展short int  a=-1;long   b;b=a;2)若多字节变量为有符号型,则转换后扩展少字)若多字节变量为有符号型,则转换后扩展少字节的最高位节的最高位转换后,数据的符号不变转换后,数据的符号不变a ab b63 多字节多字节少字节少字节低位照搬低位照搬1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1int a=-1;short int  b;b=a;b=-1int   a=65535;short int  b;b=a;b=-1b ba a1 1 1 1 1 1 1 164 赋值表达式赋值表达式a=b=5 ;;             b=5       a=5"="的结合性为的结合性为自右至左自右至左复合的赋值运算符复合的赋值运算符a+=3         a=a+3 x*=y+3           x=x*(y+3)x/=x-4             x=x/(x-4)  x+=y      x=x+yi+=j--     i=i+(j--)65 a=12;      a+=a-=a*a;12a  a=a-(a * a) =12-(12*12)=-132  a=a+(-132)=-132-132=-264-132-26466 关系运算符和关系表达式关系运算符和关系表达式关系运算符(比较运算)关系运算符(比较运算)     <   >  <=   >=     = =      !=1.  = = 与与 =2.     a=5;    赋值运算赋值运算           a= =5;;判断是否相等判断是否相等2.<  >  <=   >= 的优先级大于的优先级大于= =   !=3. 算术运算符的优先级大于关系运算符的优先级算术运算符的优先级大于关系运算符的优先级67 关系表达式:用关系运算符将表达式连接起来称为关系表达式:用关系运算符将表达式连接起来称为关系表达式。

      其值非真即假在关系表达式其值非真即假在C++语言中,用非语言中,用非0代表真,用代表真,用0表示假关系表达式的结果只有两个,关系表达式的结果只有两个,真为真为1,假为,假为0  a=2    b=3   c=4a>2        a>b+c    a= =2     a= ='a'a>'a'   b=a= =2'a'>'A'     b= ='a'+1c-a= =a00100110168  逻辑运算符逻辑运算符  1.运算符运算符             与与&&       或或 ||               非非!! A B      结果结果000010100111有有0出出0,全,全1出出1A,B同时成立同时成立&&A B      结果结果000011101111有有1出出1,全,全0出出0A或或B有一个成立有一个成立| |A    结果结果0    11       0有有0出出1,,有有1出出0!!69 江苏籍的男生江苏籍的男生江苏籍的学生和所有男生江苏籍的学生和所有男生非江苏籍的学生非江苏籍的学生江苏籍江苏籍&&男生男生例如:两个条件:例如:两个条件:江苏籍江苏籍    男生男生江苏籍江苏籍||男生男生!江苏籍!江苏籍注意:注意:1.优先级:优先级:!&&| |           !!算术算术关系关系逻辑逻辑赋值赋值逗号逗号70 3.不可写为不可写为  1

      两种            5>3 && 2 || 8<4-!04.当前面的表达式可以得出整个表达式的结果时,当前面的表达式可以得出整个表达式的结果时,不必再求后面的表达式不必再求后面的表达式a&&b&&c  当当a为为0时,表达式为时,表达式为0,不必求,不必求b与与ca||b||c      当当a为为1时,表达式为时,表达式为1,不必求,不必求b与与c71 x=4    y=5i= ++x= =5 || ++y= =6x=5    y=5   i=1i= x++= =5&& y++= =6x=5    y=5   i=0判断某年是否为闰年判断某年是否为闰年1)能被)能被400整除整除2)能被)能被4整除,不能被整除,不能被100整除整除  (2200年不是年不是)year%400= =0year%4= =0&& year%100!=0(year%400= =0) || (year%4= =0&&year%100!=0)72 当当c==4时,以下的值各多少?时,以下的值各多少?(c=1)&&(c=3)&&(c=5)(c= =1)||(c= =2) || (c= =5)(c!=2) && (c!=4) &&(c>=1)&&(c<=5)10073 sizeof()()运算符运算符  sizeof()运运算算符符是是一一个个单单目目运运算算符符,,用用于于计计算算某某一一个个操作数类型的字节数操作数类型的字节数。

      其格式为:其格式为:sizeof((<类型类型>))sizeof((int))   //其值为其值为4sizeof((float)) //其值为其值为4sizeof((double)  //其值为其值为8sizeof((char)  //其值为其值为174 逗号运算符和逗号表达式逗号运算符和逗号表达式表达式表达式1,表达式,表达式2,表达式,表达式3,,…,表达式,表达式n顺序求解,结果为最后一个表达式的值,并且优先顺序求解,结果为最后一个表达式的值,并且优先级最低a=(3+4, 5*6,  2+1);       a=3a=3*3,  a+6,  a+7;16(a=3*5,  a*4),  a+520a=9a=1575 下列语句中表达式中下列语句中表达式中i, j的值各为多少的值各为多少1、、int   i=0, j=0;                        2、、 int i=0,  j=1;      i=3, (j++)+i ;                               i+=j*=3;3、、int  i=1, j=0;                         4、、int  i=1, j=1;       j=i=((i=3)*2);                            i+=j+=2;i=3,j=1i=3,j=3i=6,j=6i=4,j=376 各类数值型数据间的混合运算各类数值型数据间的混合运算整型、实型、字符型数据间可以混合运算。

      整型、实型、字符型数据间可以混合运算floatdoublelongunsignedintchar10+'a'+1.5-87.65*'b'在进行运算时,在进行运算时,不同类型的数据要先转换成同一类不同类型的数据要先转换成同一类型的数据再进行运算型的数据再进行运算转换规则如下:转换规则如下:77 第三章第三章 简单的输入输出简单的输入输出78  输入语句:输入语句:cin程序在执行期间,程序在执行期间,接收外部信息的操作称为接收外部信息的操作称为程序的输入程序的输入;而把;而把程序向外部发送信息的操程序向外部发送信息的操作称为程序的输出作称为程序的输出在C++中没有专门的输中没有专门的输入输出语句,所有输入输出是通过入输出语句,所有输入输出是通过输入输出输入输出流流来实现的来实现的 79 要要使使用用C++提提供供的的输输入入输输出出时时,,必必须须在在程程序序的开头增加一行:的开头增加一行:#include 即即包包含含输输入入输输出出流流的的头头文文件件“iostream.h”有有关关包包含含文文件件的的作作用用,,在在编编译译预预处处理理部部分分(第五章)作详细介绍。

      第五章)作详细介绍80 输入十进制整数和实数cin >> <变量名变量名1>《《 >> <变量名变量名2> ...... 》》(举例说明)(举例说明)int   a,b;cin>>a>>b;//程序运行至此停下,等待从键盘输入变量值程序运行至此停下,等待从键盘输入变量值键盘输入:键盘输入:3   5或:或:3    5    均可输入语句自动过滤空白字符输入语句自动过滤空白字符a3键盘键盘b5键盘键盘81 浮点型数据同整型数据一样浮点型数据同整型数据一样float   c,d;cin>>c>>d;char   ch1,ch2;cin>>ch1>>ch2;若输入:若输入:ab则则ch1为为a, ch2为为b若输入:若输入:a  b则则ch1为为a, ch2为为b字符型变量过滤空白字符字符型变量过滤空白字符cin格式过滤空白字符格式过滤空白字符82 float  a;int  i1,i2;char  ch1,ch2;cin>>i1>>a>>i2>>ch1>>ch2;输入:输入:34   5.678    1a  bi2:1在缺省的情况下,在缺省的情况下,cin自动跳过输入的空格自动跳过输入的空格,换言,换言之,之,cin不能将输入的空格赋给字符型变量,同样不能将输入的空格赋给字符型变量,同样地,回车键也是作为输入字符之间的分隔符,地,回车键也是作为输入字符之间的分隔符,也不也不能将输入的回车键字符赋给字符型变量能将输入的回车键字符赋给字符型变量。

       a:5.578i1:34ch1:ach2:b83 若若要要把把从从键键盘盘上上输输入入的的每每一一个个字字符符,,包包括括空空格格和和回回车车键键都都作作为为一一个个输输入入字字符符赋赋给给字字符符型型变变量量时时,,必必须须使用函数使用函数cin.get()其格式为:其格式为:cin.get(<字符型变量字符型变量>);;cin.get()从从输输入入行行中中取取出出一一个个字字符符,,并并将将它它赋赋给给字字符符型型变变量量这这个个语语句句一一次次只只能能从从输输入入行行中中提提取取一一个个字符char  c1;cin.get(c1);84 char  ch1,ch2,ch3;cin.get(ch1);cin.get(ch2);cin.get(ch3);输入:输入:A  B则:则:ch1:A并且在输入缓冲区中保留回车键并且在输入缓冲区中保留回车键 ch2:空格空格ch3:B空格的空格的ASCII码为码为3200100000ch2ch285 输入十六进制或八进制数据输入十六进制或八进制数据 在缺省的情况下,系统约定输入的整型数是十进在缺省的情况下,系统约定输入的整型数是十进制数据。

      当要求按八进制或十六进制输入数据时,制数据当要求按八进制或十六进制输入数据时,在在cin中必须指明相应的数据类型:中必须指明相应的数据类型:hex为十六进为十六进制;制;oct为八进制;为八进制;dec为十进制为十进制 86 int  i,j,k,l;cin>>hex>>i;//指明输入为十六进制数指明输入为十六进制数cin>>oct>>j;//指明输入为八进制数指明输入为八进制数cin>>k;//输入仍为八进制数输入仍为八进制数cin>>dec>>l;//指明输入为十进制数指明输入为十进制数当执行到语句当执行到语句cin时,若输入的数据为:时,若输入的数据为:11  11  12  12结果:结果:i:17j:9k:10l:1287 使用非十进制数输入时,要注意以下几点:使用非十进制数输入时,要注意以下几点:1、、八八进进制制或或十十六六进进制制数数的的输输入入,,只只能能适适用用于于整整型型变量变量,不适用于字符型变量,实型变量不适用于字符型变量,实型变量2、、当当在在cin中中指指明明使使用用的的数数制制输输入入后后,,则则所所指指明明的的数数制制一一直直有有效效,,直直到到在在接接着着的的cin中中指指明明输输入入时时所所使使用用的的另另一一数数制制为为止止。

      如如上上例例中中,,输输入入k的的值值时时,,仍为八进制仍为八进制88 3、、输输入入数数据据的的格格式式、、个个数数和和类类型型必必须须与与cin中中所所列列举举的的变变量量类类型型一一一一对对应应一一旦旦输输入入出出错错,,不不仅仅使使当当前前的的输输入入数数据据不不正正确确,,而而且且使使得得后后面面的的提提取取数数据据也也不正确cin>>a,b;  cin>>a b;  cin>>ab;  int  a, b;cin>>a>>b;  89 输出数据输出数据cout与输入与输入cin对应的输出是对应的输出是cout输出流当当要要输输出出一一个个表表达达式式的的值值时时,,可可使使用用cout来来实实现现,,其一般格式为:其一般格式为:cout <<  <表达式表达式>  《《<<  <表达式表达式>......》》;其中运算符其中运算符“<<”称为插入运算符,它将紧跟其后称为插入运算符,它将紧跟其后的表达式的值,输出到显示器的表达式的值,输出到显示器当前光标当前光标的位置 90 int a=6;float  f1=12.4;char  s1[ ]=“abcd”;cout<int  i1=4,i2=5;float  a=3.5;cout<<“a*i1=“<

      如上面的两个输出语句可改写为:如上面的两个输出语句可改写为:cout <2、、括括号号中中必必须须给给出出一一个个表表达达式式((值值为为正正整整数数)),,它它指指明明紧跟其后输出项的宽度紧跟其后输出项的宽度3、、该设置仅对其后的一个输出项有效该设置仅对其后的一个输出项有效。

      一旦按指定的宽一旦按指定的宽度输出其后的输出项后,又回到原来的缺省输出方式度输出其后的输出项后,又回到原来的缺省输出方式 94 输出八、十六进制数和科学表示法的实数输出八、十六进制数和科学表示法的实数对对于于整整型型数数据据可可指指定定以以十十六六进进制制或或八八进进制制输输出出,,而而对对于于实实型型数数据据可可指指定定以以科科学学表表示示法法形形式式输输出出例例如如,,设设有有如如下一个程序:下一个程序:#include void main(void){    float x=3.14,y=100;     cout.setf(ios::scientific,ios::floatfield);     //表明浮点数用科学表示法输出表明浮点数用科学表示法输出      cout << x<<’\t’;     cout <

      对对实实数数的的输输出出,,也也是是这这样样,,一一旦旦指指明明按按科科学学表表示示法法输输出出实实数数,,则则接接着着的的输输出出均均按按科科学学表表示示法法输输出出,,直直到到指指明明以以定定点点数数输输出出为为止止明明确确指指定定按按定定点点数数格格式式输输出出((缺缺省省的的输输出出方方式式))的的语句为:语句为:cout.setf(ios::fixed,ios::floatfield);96 第四章第四章 C++的流程控制语句的流程控制语句97 程序的三种基本结构程序的三种基本结构1、顺序、顺序AB2、选择、选择条件?条件?真真假假ABx>y??真真假假z=xz=y98 3、循环、循环A当当P为真为真当型当型i++i<10PAYN99 直到直到P为真为真A直到型直到型i>=10i++PAYN100 if语句语句判断选择判断选择语句,有三种形式:语句,有三种形式:1)if(表达式)(表达式)    语句语句语句语句条件条件真真假假语句语句2语句语句1条件条件真真假假2)  if(表达式)(表达式)   语句语句1     else      语句语句2  if (a>b)     cout<b)     cout<

      后可跟复合语句            2)  注意注意  ;的位置            3)  注意多重注意多重 if   else  的搭配if  (a>b)    {   a=1;        b=0;    }else    {  a=0;        b=1;     } a=0b=1a=1b=0a>b真真假假104 if (i >j)  i++;if (i>j);   i++;i+ +i>j真真假假if  总是与它上面最近的总是与它上面最近的 else 配对,如要改变,用复合语配对,如要改变,用复合语句{句{ }注意书写格式注意书写格式,相互配对的语句要对齐相互配对的语句要对齐i>j真真假假i+ +105 例:输入两个实数,按代数值由小到大次序输出这两个数例:输入两个实数,按代数值由小到大次序输出这两个数void main( void ){  float a,b,t;   //定义变量定义变量cout<<“ Input  2  Real Number:\n";//在屏幕上的提示信息在屏幕上的提示信息       cin>>a>>b;     //给变量赋值给变量赋值   a:7, b:3    if(a>b)       {    t=a; a=b;   b=t;   }//交换数据,用中间变量交换数据,用中间变量     cout<

      ++中的唯一的三目运算符表达式表达式1?表达式?表达式2 :表达式:表达式3表达式表达式3表达式表达式2表达式表达式1真真假假max=a>b?a:b ;    // 求求a, b中的大者中的大者当当 a=2   b=1   a>b为真,表达式的值等于为真,表达式的值等于a, max值为值为2当当 a=1   b=2   a>b为假,表达式的值等于为假,表达式的值等于b, max值为值为2注意:注意:1.条件运算符的优先级比赋值运算符高条件运算符的优先级比赋值运算符高  2.      x=(x=3) ? x+2 : x-33.2.  结合方向自左至右结合方向自左至右     a>b?a:c>d?c:d4.3.  三个表达式的类型可不同三个表达式的类型可不同     z=a>b?'A':a+bx=5108 x=9, y=6,  z=5;x=((x+y)%z>=x%z+y%z)?1:0;cout<<"x= "<y?x++:y++))<y?x++:y++<=y&&y= =x)?1:0<=y&&y>=x<

      多分支选择语句if语句只有两个分支,而实际问题中常常语句只有两个分支,而实际问题中常常需要用到多分支的选择如,成绩分为需要用到多分支的选择如,成绩分为A(100~85)、、B(84~70)、、C(69~60)、、D(60以下以下)等‘A’100~85Y‘B’Y84~70‘C’Y69~60‘D’Yno passNNNN显示出错显示出错113 cin.get(grade);if(grade= =‘A’)    cout<<“100~85\n”;else   if   (grade= =‘B’)             cout<<“84~70\n”;         else   if   (grade= =‘C’)                      cout<<“69~60\n”;                  else   if   (grade= =‘D’)                                 cout<<“no  pass\n”;                           else                                       cout<<“error\n”;    114 switch(表达式)表达式)    {{ case  常量表达式常量表达式1:语句:语句1          case  常量表达式常量表达式2:语句:语句2          … …         case 常量表达式常量表达式n:语句:语句n         default:语句:语句n+1      }}switch(grade)    {{ case  ‘A’::cout<<“100~85\n”;          case  ‘B’::cout<<“84~70\n”;         case  ‘C’::cout<<“69~60\n”;          case  ‘D’::cout<<“no pass\n”;         default::cout<<“error\n”;      }}如果如果grade为为 ‘A’,则结则结果为果为100~8584~7069~60no passerror115 其流程为:先计算表达式的值,然后顺序地其流程为:先计算表达式的值,然后顺序地与与case子句中所列出的各个常量进行比较,若子句中所列出的各个常量进行比较,若表达式的值与常量中的值相等,就开始进入表达式的值与常量中的值相等,就开始进入相应的相应的case语句执行程序,语句执行程序,遇到遇到case和和default也不再进行判断,直至也不再进行判断,直至switch语句结束。

      语句结束如果如果要使其在执行完相应的语句后中止执行下一要使其在执行完相应的语句后中止执行下一语句,可以在语句后加语句,可以在语句后加break116 switch(grade)    {{ case  ‘A’::cout<<“100~85\n”; break;         case  ‘B’::cout<<“84~70\n”;  break;         case  ‘C’::cout<<“69~60\n”; break;         case  ‘D’::cout<<“no pass\n”; break;         default::cout<<“error\n”;      }}117 注意:注意:1、、switch与与if不同,它仅能判断一种逻辑关系,即不同,它仅能判断一种逻辑关系,即表达式是否表达式是否等于等于指定的常量,而指定的常量,而 if 可以计算并判断可以计算并判断各种表达式各种表达式2、、case子句后必须为常量,常常是整型和字符型子句后必须为常量,常常是整型和字符型3、、default可以省略,这时,不满足条件什么也不可以省略,这时,不满足条件什么也不执行。

      执行118 4、、case和和default只起标号的作用,只起标号的作用,顺序可以颠倒顺序可以颠倒,,颠倒时注意后面的颠倒时注意后面的break语句5、多个、多个case语句可以共用一组程序语句可以共用一组程序   case  ‘A’:   case  ‘B’:   case  ‘C’:  cout<<“pass!\n”;119 void  main(void ){   int  i=10;    switch(i)      {    case  9:  i++;           case   10:  i++;           case  11:  i++;           default:   i++;       }     cout<<“i=”<

      由键盘输入,输出其中最大的数 122 while语句语句while ( 表达式)表达式)     {{  语句组语句组1  }}{语句组{语句组2}}表达式表达式语句组语句组1真真语句组语句组2假假a=3;while(a<100)    a=a+5;cout<<“a=“<

      括起2、循环体内或表达式中必须有使循环结束的条件,、循环体内或表达式中必须有使循环结束的条件,即一定有一个循环变量即一定有一个循环变量3、、while表达式可以成为语句,要特别小心表达式可以成为语句,要特别小心125 k=2;while(k!=0)   cout<1真真22真真33假假无无127 void main(void){   int  y=10;    while (y--);   cout<<“y=”<void main(){char ch;while(cin.get(ch)&&ch!='\n')switch (ch-'2')            { case  0:               case  1:  cout<<(char)(ch+4);               case  2:  cout<<(char)(ch+4); break;               case  3:  cout<<(char)(ch+3) ;                 default : cout<<(char)(ch+2); break;             }     cout<,则程序,则程序的输出结果是:的输出结果是:输出:输出:668977131 直到直到P为真为真A直到型直到型do—while语句语句表达式表达式语句组语句组1真真语句组语句组2假假do    { 语句组语句组1}}while(表达式)(表达式);;{语句组{语句组2}}132 求求 1+2+3+……+100void main(void){   int  i=1,sum=0;   //定义变量,初始化定义变量,初始化     do                 //构造循环构造循环     {     sum=sum+i;   // 循环体,多次执行循环体,多次执行             i=i+1;     }while (i<=100);    cout<<“sum=”<

      表达式,至少执行一次循环体当第一当第一次循环表达式的值为真时,次循环表达式的值为真时,while与与do—while的结果完全一样,否则结果不相同的结果完全一样,否则结果不相同134 x=0,y=0;do  {   y++;  x*=x;  } while ((x>0)&&(y>5));cout<<“y=“<

      也进入不了循环体2、、for语句中的三个表达式可以部分省略或全部省略,语句中的三个表达式可以部分省略或全部省略,但但;;不能省略,不能省略,若省略表达式若省略表达式2,则表示循环条件,则表示循环条件为真为真3、、for语句中三个表达式可以是任何有效的语句中三个表达式可以是任何有效的C语言表达式语言表达式139 void main(void){   char  i, j ;     for (i=‘a’,j=‘z’ ; i>x; 101141 循环的嵌套循环的嵌套一个循环体内又包含另一个完整的循环体,称为循一个循环体内又包含另一个完整的循环体,称为循环的嵌套。

      环的嵌套注意:注意:1、循环体内有多个语句要用{}括起来循环体内有多个语句要用{}括起来2、书写格式要清晰书写格式要清晰for (   ;    ;  ) {  .....        for (  ;   ;  )           { .......              }   } 142 void main(void){   int   i, j, k=0,  m=0;    for ( i=0; i<2; i++)       {     for ( j=0; j<3; j++)                        k++;              k- =j;       }     m=i+j;    cout<<“k=“<n))1、、m被被n除得到余数除得到余数r((0≤r ≤n)       r=m%nm=6   n=4     r=m%n=6%4=2while ( r=m%n )    {     m=n;     n=r ;      }     最小公倍数为两数之积除以最大公约数。

      最小公倍数为两数之积除以最大公约数4*6/2=122、若、若r=0,则算法结束,,则算法结束,n为最大公约数,否则做为最大公约数,否则做33、、mn ,  nr  ,  回到回到1m=4   n=2    r=m%n=4%2=0所以,公约数所以,公约数=2146 最大公约数:能同时被最大公约数:能同时被m和和n整除的最大数整除的最大数r=m>n?n:mfor(i=1; i

      项,得出后一项比前一项大多少倍通项:通项:t=x*x/((2*n)*(2*n-1))第第n项项/第第n-1项:项:表明前一项比后一项大表明前一项比后一项大t倍倍,即后一项乘即后一项乘t等于前一等于前一项项后一项=后一项=(-1)×前一项前一项×t149 S=0;term=1;n=1;//一定要赋初值一定要赋初值while(fabs(term)>=1e-5){S=S+term;term=(-1)*term*x*x/((2*n)*(2*n-1));n++;}term=(-1)*term*t;前一项前一项当前项当前项旧的旧的新的新的后一项=后一项=(-1)×前一项前一项×t设通项为设通项为term,则可以写出迭代公式,则可以写出迭代公式t=x*x/((2*n)*(2*n-1))150 t=x*x/((2*n)*(2*n-1))第第n项项/第第n-1项:项:第一项:第一项:term=1;第一次循环:第一次循环:S=S+term;   term=(-1)*term*t;第二次循环:第二次循环:S=S+term;  term=(-1)*term*t;这时这时左边的左边的term代表第二项,而代表第二项,而右边的右边的term为第一项。

      为第一项这时这时左边的左边的term代表第三项,而代表第三项,而右边的右边的term为第二项为第二项term=(-1)*term*t;前一项前一项当前项当前项同样是同样是term,在循环中不断用旧的数值去推导赋值出新的,在循环中不断用旧的数值去推导赋值出新的数值151 S=0;term=1;n=1;//一定要赋初值一定要赋初值while(fabs(term)>=1e-5){S=S+term;term=(-1)*term*x*x/((2*n)*(2*n-1));n++;}旧的旧的新的新的152 break语句和语句和continue语句语句break在在switch语句中,可以语句中,可以使流程跳过判断体使流程跳过判断体,,执执行下面的程序行下面的程序在循环体中,也可以从循环体内跳在循环体中,也可以从循环体内跳出循环体,提前结束循环出循环体,提前结束循环for ( ;   ;  )  {  cin>>x;      if  (x= =123)  break;   }  当输入当输入123时,结束循环时,结束循环break 只能退出一层循环或只能退出一层循环或switch语句153 a=10 ;  y=0;do   {  a+=2;  y+=a;       cout<<“a=“<50)     break;    }  while  (a=14);第一次:第一次:a=12   y=12输出:输出:a=12 ,  y=12第二次:第二次:a=16   y=28输出:输出:a=16 ,  y=28第三次:第三次:a=16   y=44输出:输出:a=16 ,  y=44第四次:第四次:a=16   y=60输出:输出:a=16 ,  y=60154 continue:其作用为:其作用为结束本次循环结束本次循环,即跳过循环体中下面,即跳过循环体中下面尚未执行的语句,尚未执行的语句,接着进行下一次是否执行循环的判定接着进行下一次是否执行循环的判定。

      void main(void){    int  i;      for (i=1 ; i<=5 ; i++ )        { if (i%2)   cout<<“*”;           else       continue;           cout<<“#”;        }       cout<<“ $\n”;}ii<=5i%2输出输出输出:输出:*#*#*#$1真真1*#2真真0无无3真真1*#4真真0无无5真真1*#6假假$155 void main(void){   int   i, j, x=0 ;     for (i=0 ; i<2; i++)       {    x++;             for (j=0;j<=3; j++)               {    if ( j%2 )    continue;                      x++;               }               x++;          }       cout<<“x=“<< x<

      for(...  ; ... ; ... ){     ........    break;     ........}158 continue:其作用为:其作用为结束本次循环结束本次循环,即跳过循环体,即跳过循环体中下面尚未执行的语句,中下面尚未执行的语句,接着进行下一次是否执行接着进行下一次是否执行循环的判定循环的判定for(...  ;   ... ;    ... ){     ........    continue;     ........}while(    ......   ){     ........    continue;     ........}159 求素数:只可以被求素数:只可以被1与自身整除的数与自身整除的数判断一个数判断一个数 t 是否为素数,用是否为素数,用2到到t-1循环除for( i=2;   i

      可将循环次数降低t/2(i>=t/2)160 求范围内的素数求范围内的素数(50~100)::for(t=50, k=0 ; t<=100; t++){     for( i=2;   i

      请编写程序计算陌生人给百万富翁多少这个契约请编写程序计算陌生人给百万富翁多少钱,百万富翁给陌生人多少钱?钱,百万富翁给陌生人多少钱?163 利用循环语句编程,打印下列图形:利用循环语句编程,打印下列图形:       *   *  *        *  *  *    *  *  *  *    *  *  *      *  *    *找规律:找规律: 上面四行上面四行  行号行号空格空格星号星号131222313404            for(i=0;i<4;i++){for(j=4-i-1;j>0;j--)cout<<"   ";for(k=1;k<=i+1;k++)cout<<" * ";cout<0;j--)cout<<"   ";for(k=1;k<=i+1;k++)cout<<" * ";cout<0;j--)   cout<<" * ";cout<

      同  131     131/11=11   12+32+12=11分析:分析:数字应该从数字应该从100循环到循环到999将每位数字剥出,判断其是否满足条件将每位数字剥出,判断其是否满足条件169 满足以下条件三位数满足以下条件三位数n,它除以,它除以11所得到的商等于所得到的商等于n的各位数字的平方和,且其中至少有两位数字相的各位数字的平方和,且其中至少有两位数字相同  131     131/11=11   12+32+12=11分析:分析:用用a,b,c分别代表三位数,分别代表三位数,a,b,c分别从分别从0循环到循环到9,组,组成所有可能的三位数,然后找出满足条件的数来成所有可能的三位数,然后找出满足条件的数来170 求求n=1000时时π的近似值的近似值分析:分析:通项:通项:s=s×t迭代算法:迭代算法:上次迭代上次迭代的结果的结果本次计算本次计算的结果的结果迭代结束条件:迭代结束条件:迭代迭代 1000次次注意注意s与与t的初始值的初始值n从从1开始迭代开始迭代  s=1171 下面程序的功能是用公式求下面程序的功能是用公式求π的近似值,直到最后一项的值的近似值,直到最后一项的值小于小于10-6为止。

      请填空void main(void ){   int  i=1;     ______     pi=0;    while (i*i<=10e+6)        {   pi=______________  ;                      i++;       }     pi=sqrt (6.0 *pi) ;     cout<<“ pi=”<

      成某一特定的任务C++是由函数构成的,是由函数构成的,函数是函数是C++的基本模块的基本模块有的函数完成某一操作;有的函数计算出一有的函数完成某一操作;有的函数计算出一个值通常,一个函数即能完成某一特定操个值通常,一个函数即能完成某一特定操作,又能计算数值作,又能计算数值175 为什么要使用函数?为什么要使用函数?1、避免重复的编程避免重复的编程2、使程序更加模块化,便于阅读、修改使程序更加模块化,便于阅读、修改参数(多个)参数(多个)函数值函数值(唯一)唯一)函数体函数体所编写的函数应尽量少与主调函数发生所编写的函数应尽量少与主调函数发生联系,这样便于移植联系,这样便于移植176 说明:说明:1、一个源程序文件由一个或多个函数组成,编译程序以文、一个源程序文件由一个或多个函数组成,编译程序以文件而不是以函数为单位进行编译的件而不是以函数为单位进行编译的2、一个程序可以由多个源文件组成,可以分别编译,统一、一个程序可以由多个源文件组成,可以分别编译,统一执行3、一个程序必须有且只有一个、一个程序必须有且只有一个main( )函数,函数,C++从从main( )函数开始执行函数开始执行4、、C++语言中,语言中,所有函数都是平行独立的,无主次、相互所有函数都是平行独立的,无主次、相互包含之分包含之分。

      函数可以嵌套调用,不可嵌套定义函数可以嵌套调用,不可嵌套定义5、从使用角度来说,分标准函数和用户自定义函数;从形、从使用角度来说,分标准函数和用户自定义函数;从形式来说,分无参函数和有参函数式来说,分无参函数和有参函数177 库函数是库函数是C++编译系统已预定义的函数编译系统已预定义的函数,用户根据,用户根据需要可以直接使用这类函数库函数也称为标准函需要可以直接使用这类函数库函数也称为标准函数为了方便用户进行程序设计,为了方便用户进行程序设计,C++把一些常用数学把一些常用数学计算函数(如计算函数(如sqrt()、、exp()等)、字符串处理函数、等)、字符串处理函数、标准输入输出函数等,都作为库函数提供给用户,标准输入输出函数等,都作为库函数提供给用户,用户可以直接使用系统提供的库函数用户可以直接使用系统提供的库函数库函数有很多个,当用户使用任一库函数时,在程库函数有很多个,当用户使用任一库函数时,在程序中必须包含相应的头文件序中必须包含相应的头文件 如如 #include等178 用户在设计程序时,可以将完成某一相对独立功能用户在设计程序时,可以将完成某一相对独立功能的程序定义为一个函数。

      用户在程序中,根据应用的程序定义为一个函数用户在程序中,根据应用的需要,由的需要,由用户自己定义函数用户自己定义函数,这类函数称为用户,这类函数称为用户自定义的函数自定义的函数 根据定义函数或调用时是否要给出参数,又可将函根据定义函数或调用时是否要给出参数,又可将函数分为:无参函数和有参函数数分为:无参函数和有参函数 179 函数定义的一般形式函数定义的一般形式一、无参函数一、无参函数主调函数并不将数据传给被调函数主调函数并不将数据传给被调函数类型说明类型说明      函数名(函数名(void))    {{   函数体函数体   }}  无参函数主要用于完成某一操作无参函数主要用于完成某一操作不传递参数不传递参数参数(多个)参数(多个)函数值函数值(唯一)唯一)函数体函数体180 void main(void ){   printstar ( );     print_message ( );     printstar( );}void     printstar (void ){     cout<<“* * * * * * * * * * *\n”;}     void     print_message (void){     cout<<“  How do you do! \n”;}     调用函数调用函数调用函数调用函数调用函数调用函数函数类型函数类型函数名函数名函数体函数体两个被调函数两个被调函数主要用于完成主要用于完成打印操作。

      打印操作181 输出:输出: * * * * * * * * * * *               How do you do!             * * * * * * * * * * *       182 二、有参函数二、有参函数主调函数和被调函数之间有数据传递主调函数和被调函数之间有数据传递主调函数可以将参数传递给被调函数,被调函数函数可以将参数传递给被调函数,被调函数中的结果也可以带回主调函数中的结果也可以带回主调函数类型说明类型说明      函数名(函数名(形式参数列表说明形式参数列表说明 ))          {{   函数体函数体   }}  183 int  max (int x,int y){   int  z;     z=(x>y)? x : y ;     return  z;}     void main (void ){    int   a,b,c;      cin>>a>>b;      c=max (a , b) ;      cout<<“The max is”<< c<y)? x : y ;     return  z;}     void main (void ){    int   a,b,c;      cin>>a>>b;      c=max (a , b) ;      cout<<“The max is”<< c<

      实参可以是常量、实参可以是常量、变量或复杂的表达式,不管是哪种情况,变量或复杂的表达式,不管是哪种情况,在在调用时实参必须是一个确定的值调用时实参必须是一个确定的值形参与实参类型相同,一一对应形参与实参类型相同,一一对应形参必须要定义类型形参必须要定义类型,因为在定义被调函数,因为在定义被调函数时,不知道具体要操作时,不知道具体要操作什么数什么数,而定义的是,而定义的是要操作要操作什么类型什么类型的数186 int  max (int x,int y){   int  z;     z=(x>y)? x : y ;     return  z;}     void main (void ){    int   a,b,c;      cin>>a>>b;      c=max (a+b , a*b) ;      cout<<“The max is”<

      调用结束调用结束后,形参所占用的内存单元被释放后,形参所占用的内存单元被释放2、实参对形参变量的传递是、实参对形参变量的传递是“值传递值传递”,即单向传递即单向传递在在内存中实参、形参分占不同的单元内存中实参、形参分占不同的单元3、形参只作用于被调函数,可以在别的函数中使用相同的、形参只作用于被调函数,可以在别的函数中使用相同的变量名5a8b实参实参xy形参形参58188 void fun(int a, int b){    a=a*10;     b=b+a;     cout<

      的数形参是被调函数中的变量;形参是被调函数中的变量;实参是主调函数实参是主调函数赋给被调函数的特定值赋给被调函数的特定值在函数调用语句中,在函数调用语句中,实参不必定义数据类型实参不必定义数据类型,,因为实参传递的是因为实参传递的是一个具体的值一个具体的值(常量常量),程序可依据这个数值,程序可依据这个数值的表面形式来判断其类型,并将其赋值到对的表面形式来判断其类型,并将其赋值到对应的形参变量中应的形参变量中191 函数的返回值函数的返回值函数的返回值通过函数的返回值通过return语句获得语句获得函数只函数只能有唯一的返回值能有唯一的返回值函数返回值的类型就是函数的类型函数返回值的类型就是函数的类型return语句可以是一个表达式,函数先计算语句可以是一个表达式,函数先计算表达式后再返回值表达式后再返回值return语句还可以终止函数,并将控制返回语句还可以终止函数,并将控制返回到主调函数到主调函数一个函数中可以有一个以上的一个函数中可以有一个以上的return语句,执行语句,执行到哪一个到哪一个return语句,哪一个语句起作用语句,哪一个语句起作用 192 int add ( int  a, int b){         return (a+b);}    int max ( int a, int b){         if (x>y)         return   x ;     else  return  y;}    若函数体内没有若函数体内没有return语语句,就一直执行到函数体句,就一直执行到函数体的末尾,然后返回到主调的末尾,然后返回到主调函数的调用处。

      函数的调用处先计算,后返回先计算,后返回可以有多个可以有多个return语句语句193 不带返回值的函数可说明为不带返回值的函数可说明为void型函数的类型与函数参数的类型没有关系函数的类型与函数参数的类型没有关系double   blink ( int a,  int b)如果函数的类型和如果函数的类型和return表达式中的类型不一致,表达式中的类型不一致,则以函数的类型为准则以函数的类型为准函数的类型决定返回值的函数的类型决定返回值的类型对数值型数据,可以自动进行类型转换对数值型数据,可以自动进行类型转换 既然函数有返回值,这个值当然应属于某一个确定既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型的类型,应当在定义函数时指定函数值的类型 int   max (float a,  float  b) // 函数值为整型函数值为整型 函数返回值的类型,也是函数的类型函数返回值的类型,也是函数的类型194 参数(多个)参数(多个)函数值函数值(唯一)唯一)函数体函数体int max ( int a, int b){   int z;    z=x>y?x:y;    return   z;    }    如果有函数返回如果有函数返回值值,返回值就是函返回值就是函数值数值,必须惟一。

      必须惟一如果有函数返回如果有函数返回值值, 函数的类型就函数的类型就是返回值的类型是返回值的类型函数体的类型、形式参数的类型必须函数体的类型、形式参数的类型必须在函数的定义中体现出来在函数的定义中体现出来195 函数的调用函数的调用函数调用的一般形式函数调用的一般形式函数名(实参列表);函数名(实参列表);形参与实参类型相同,一一对应形参与实参类型相同,一一对应 i=2;  f (i, ++i);函数调用的方式函数调用的方式作为语句作为语句    printstar( );作为表达式作为表达式    c=max (a,b);作为另一个函数的参数作为另一个函数的参数     cout<在一个函数中调用另一函数(即被调用函数)需要在一个函数中调用另一函数(即被调用函数)需要具备哪些条件呢?具备哪些条件呢?3) 函数调用遵循函数调用遵循先定义、后调用先定义、后调用的原则,即的原则,即被调被调函数应出现在主调函数之前函数应出现在主调函数之前。

      197 float max(float x, float y){   float  z;     z=(x>y)? x : y ;     return  z;}     void main (void){  float   a,b, c;    cin>>a>>b;    c=max (a+b , a*b) ;    cout<<“The max is”<y)? x : y ;     return  z;}     void main (void){    float   a,b, c;      float   max (float,float);      cin>>a>>b;      c=max (a,b) ;      cout<<“The max is”<

      200 void main(void){  int  i=2, x=5, j=7;  void fun(int,int);    fun ( j, 6);  cout<>x;    y=f1(x);    cout<<“x=“<

      时,累加结束205 float fun(float x){  float s=1, t=1;    do    { t=t/x;       s+=t;     }while (t>0.00001);   return s;}void main(void){  float x;     cin>>x;     cout<<“s=“<>x>>y;   cout<>x>>y>>z;   cout<c?r:c;      for(int i=r-1;i>=1;i--)       { if(a%i==0&&b%i==0&&c%i==0)      break;        }       return i;} 209 写一个函数验证哥德巴赫猜想;一个不小于写一个函数验证哥德巴赫猜想;一个不小于6 6的偶的偶数可以表示为两个素数之和,如数可以表示为两个素数之和,如6=3+3, 8=3+5, 6=3+3, 8=3+5, 10=3+710=3+7……。

      在主函数中输入一个不小于在主函数中输入一个不小于6 6的偶数的偶数n n,函数中输出以下形式的结果,函数中输出以下形式的结果∶∶34=3+31 210 函数的嵌套调用函数的嵌套调用C语言中,语言中,所有函数都是平行独立的,无主次、相所有函数都是平行独立的,无主次、相互包含之分互包含之分函数可以嵌套调用,不可嵌套定义函数可以嵌套调用,不可嵌套定义int max ( int a,  int b){    int  c;      int min (  int  a,  int b)       {  return  ( ab? a : b);}   int max ( int a,  int b){    int  c;       c=min(a,b);            return ( a>b? a : b);}   int min (  int  a,  int b){    return  ( a

      函数212 int power(int m,int n)//m^n{int i,product=m;for(i=1;i>k>>m;cout<<"f("<

      问第岁问第4个人多少岁,他说比第个人多少岁,他说比第3个人大个人大2岁问第3个人多少岁,他说比第个人多少岁,他说比第2个人大个人大2岁问第2个人多少岁,他说比第个人多少岁,他说比第1个人大个人大2岁问第1个人多个人多少岁,他说是少岁,他说是10岁请问第岁请问第5个人多大?个人多大?age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10age(n)=10                n=1age(n-1)+2   n>1int  age ( int  n ){  int  c;    c=age(n-1)+2;    return  c;}void main(void){     int age(int);      cout<

      必须有递归终止条件必须有递归终止条件216 用递归方法求用递归方法求n!n!=1                n=0,1n*(n-1)!     n>1float  fac (int n){  float  y;    if ((n= =0)|| (n= =1)   y=1;    else  y=n*fac(n-1);    return  y;}void main (void){  float  y;   int  n;    cout<<“Input  n:\n”;        cin>>n ;    cout<

      不同218 void main (void){   int  i=5;     cin>>i;     f(i);}void f(int  n ){if(n= =0)   return;     else   {cout<=10)       f(n/10); cout<

      在在C++中,作用域共分为五类:中,作用域共分为五类:块作用域、文件作块作用域、文件作用域、函数原型作用域、函数作用域和类的作用域用域、函数原型作用域、函数作用域和类的作用域 222 块作用域块作用域我们把用花括号括起来的一部分程序称为一个块我们把用花括号括起来的一部分程序称为一个块在块内说明的标识符,只能在该块内引用,即其在块内说明的标识符,只能在该块内引用,即其作用域在该块内,开始于标识符的说明处,结束作用域在该块内,开始于标识符的说明处,结束于块的结尾处于块的结尾处 在一个函数内部定义的变量或在一个块中定义的变在一个函数内部定义的变量或在一个块中定义的变量称为局部变量量称为局部变量 223 在函数内或复合语句内部定义的变量,其作用域是在函数内或复合语句内部定义的变量,其作用域是从定义的位置起到函数体或复合语句的结束从定义的位置起到函数体或复合语句的结束形参形参也是局部变量也是局部变量float  f1( int  a){  int  b,c;    .....}float  f2( int  x,  int y){  int  i, j;    .....}void main(void ){  int  m, n;    .....}x,y,i,j 有效有效a,b,c有效有效m,n有效有效224 主函数主函数main中定义的变量,也只在主函数中有效,中定义的变量,也只在主函数中有效,同样属于局部变量同样属于局部变量。

      不同的函数可以使用相同名字的局部变量,它们在不同的函数可以使用相同名字的局部变量,它们在内存中分属不同的存储区间,互不干扰内存中分属不同的存储区间,互不干扰void main(void){   int  x=10;    {  int  x=20;       cout<

      在函数外定义的变量称为全局变量全局变量的作用域称为文件作用域,即在整个文件全局变量的作用域称为文件作用域,即在整个文件中都是可以访问的中都是可以访问的 其缺省的作用范围是其缺省的作用范围是:从定义全局变量的位置开始从定义全局变量的位置开始到该源程序文件结束到该源程序文件结束当在块作用域内的变量与全局变量同名时,当在块作用域内的变量与全局变量同名时,局部变局部变量优先 229 p,q有效有效int  p=1,  q=5;float  f1( int  a){  int  b,c;    .....}char  c1,c2;main( ){  int  m, n;    .....}a,b,c有效有效m,n有效有效c1,c2有效有效全局变量全局变量局部变量局部变量全局变量全局变量增加了函数间数据联系的渠道增加了函数间数据联系的渠道,在函数调,在函数调用时可以得到多于一个的返回值用时可以得到多于一个的返回值230 4int  min;int  max (int x, int  y){   int  z;     min=(xy)? x : y ;     return  z;}     void main (void){    int   a,b,c;      cin>>a>>b;      c=max (a , b) ;      cout<<“The max is”<

      231 在同一个源文件中,外部变量与局部变量同名,则在局部在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用变量的作用范围内,外部变量不起作用int  a=3, b=5;int max(int  a, int  b){  int c;    c=a>b? a:b;    return  c;}void main(void){  int   a=8;    cout<int  i= 100;void main(void){   int i , j=50;   i=18;          //访问访问局部变量局部变量i   ::i= ::i+4;    //访问全部变量访问全部变量i   j= ::i+i;  //访问全部变量访问全部变量i和局部变量和局部变量j  cout<<”::i=”<<::i<<’\n’;  cout<<”i=”<

       float tt(int x , float y);  //函数函数tt的原型说明的原型说明 由于所说明的标识符与该函数的定义及调用无关,由于所说明的标识符与该函数的定义及调用无关,所以,所以,可以在函数原型说明中只作参数的类型说可以在函数原型说明中只作参数的类型说明,而省略参量名明,而省略参量名 float tt (int ,  float); 235 int  i=0;int workover(int i){  i=(i%i)*((i*i)/(2*i)+4);    cout<<“i=“<

      运行结束动态存储:在程序运行期间根据需要分配存储空间,动态存储:在程序运行期间根据需要分配存储空间,函数函数结束后立即释放空间结束后立即释放空间若一个函数在程序中被调用两次,若一个函数在程序中被调用两次,则每次分配的单元有可能不同则每次分配的单元有可能不同程序区程序区静态存储区静态存储区动态存储区动态存储区全局变量全局变量静态局部变量静态局部变量动态局部变量动态局部变量238 局部变量局部变量的分类的分类动态变量(动态变量(auto):默认,存储在动态区):默认,存储在动态区寄存器变量(寄存器变量(register):):在在cpu内部存储内部存储静态局部变量(静态局部变量(static):存储在静态区):存储在静态区动态局部变量未被赋值时,动态局部变量未被赋值时,其值为随机值其值为随机值其作用域的函其作用域的函数或复合语句结束时,数或复合语句结束时,空间被程序收回空间被程序收回程程序序执执行行到到静静态态局局部部变变量量时时,,为为其其在在静静态态区区开开辟辟存存储储空空间间,,该空间一直被保留,该空间一直被保留,直到程序运行结束直到程序运行结束由于存储在静态区,静态局部变量或全局变量未赋初值时,由于存储在静态区,静态局部变量或全局变量未赋初值时,系统自动使之为系统自动使之为0。

      239 int fun(int a){  int c;   static  int b=3;  c=a+ b++;  return c;}void main(void){   int x=2, y;    y=fun(x);    cout<

      2、静态(、静态(static)存储类别)存储类别1、、extern  存储类别存储类别全局变量是在函数的外部定义的,编译时全局变量是在函数的外部定义的,编译时分配在静态存储分配在静态存储区,如果未赋初值,其值为区,如果未赋初值,其值为0它仅能在本文件中引用它仅能在本文件中引用,即使在其它文件中用,即使在其它文件中用extern说明说明也不能使用也不能使用相当于限制了全局变量的作用域范围相当于限制了全局变量的作用域范围244 程序的作用是:给定程序的作用是:给定b的值,输入的值,输入a和和m,,求求a×b和和am的值文件文件file1.c中的内容为:中的内容为:int   a;void main(void){ extern  int  power (int);    int  b=3, c, d, m;    cin>>a>>m;    c=a*b;    cout<

      对应,在别的函数中不能引用全局静态变量全局静态变量::static 在函数外部定义,在函数外部定义,只限在本文件中使只限在本文件中使用用,与,与extern对应对应当变量名相同致使作用域相重时,起作用的是当变量名相同致使作用域相重时,起作用的是最近说明最近说明的的那个变量那个变量全局变量全局变量静态静态 static 外部外部 extern自动自动       auto局部变量局部变量静态静态       static 寄存器寄存器    register 246 主调函数主调函数调用处调用处被调函数被调函数主调函数主调函数调用处调用处被调函数被调函数内联函数内联函数 将被调函数体的代将被调函数体的代码直接插到调用处码直接插到调用处内联函数内联函数247 内联函数的实质是用存储空间(使用更内联函数的实质是用存储空间(使用更多的存储空间)来换取时间(减少执行时间)多的存储空间)来换取时间(减少执行时间).内联函数的定义方法是,在函数定义时,内联函数的定义方法是,在函数定义时,在函数的类型前增加修饰词在函数的类型前增加修饰词inline 248 inline  int  max (int  x, int y){   int  z;     z=(x>y)? x : y ;     return  z;}     void main (void ){    int   a,b,c;      cin>>a>>b;      c=max (a+b , a*b) ;      cout<<“The max is”<

      语句外,所有的函数均可定义为内联函数2、、内内联联函函数数也也要要定定义义在在前前,,调调用用在在后后形形参参与与实实参参之之间间的关系与一般的函数相同的关系与一般的函数相同3、、对对于于用用户户指指定定的的内内联联函函数数,,编编译译器器是是否否作作为为内内联联函函数数来来处处理理由由编编译译器器自自行行决决定定说说明明内内联联函函数数时时,,只只是是请请求求编编译译器器当当出出现现这这种种函函数数调调用用时时,,作作为为内内联联函函数数的的扩扩展展来来实实现现,,而不是命令编译器要这样去做而不是命令编译器要这样去做4、、正正如如前前面面所所述述,,内内联联函函数数的的实实质质是是采采用用空空间间换换取取时时间间,,即即可可加加速速程程序序的的执执行行,,当当出出现现多多次次调调用用同同一一内内联联函函数数时时,,程程序序本本身身占占用用的的空空间间将将有有所所增增加加如如上上例例中中,,内内联联函函数数仅仅调用一次时,并不增加程序占用的存储间调用一次时,并不增加程序占用的存储间250 具有缺省参数值和参数个数可变的函数具有缺省参数值和参数个数可变的函数在在C++中定义函数时,允许给参数指定一个缺中定义函数时,允许给参数指定一个缺省的值。

      省的值在调用函数时,若明确给出了这种实在调用函数时,若明确给出了这种实参的值,则使用相应实参的值;若没有给出相参的值,则使用相应实参的值;若没有给出相应的实参,则使用缺省的值举例说明)应的实参,则使用缺省的值举例说明) 251 int  fac(int n=2){   int t=1;    for(int i=1;i<=n;i++)    t=t*i;   return t;}void main(void){   cout<< fac(6) <

      了缺省值,后面函数的定义不可有缺省值错误!错误!254 参数个数可变的函数到目前为止,在定义函数时,都明确规定了函数的参数个数及类型在调用函数时,实参的个数必须与形参相同在调用具有缺省参数值的函数时,本质上,实参的个数与形参的个数仍是相同的,由于参数具有缺省值,因此,在调用时可省略在某些应用中,在定义在某些应用中,在定义函数时,并不能确定函数的参数个数,参数的个数在调时才能确定函数时,并不能确定函数的参数个数,参数的个数在调时才能确定在C++中允许定义参数个数可变的函数 255 首先,必须包含头文件“stdarg.h”,因为要用到里面的三个库函数  va_start( )、va_arg( )和va_end( )其次,要说明一个va_list类型的变量va_list与int,float类同,它是C++系统预定义的一个数据类型(非float),只有通过这种类型的变量才能从实际参数表中取出可变有参数如:va_list   ap;ab...ap(va_list)变量(可变参数)va_start(ap,b):初始化va_arg(ap,int):依次取参数va_end(ap):正确结束256 va_start():有两个参数,va_start(ap,b); b即为可变参数前的最后一个确定的参数。

      va_arg():有两个参数,va_arg(ap,int)    int即为可变参数的数据类型名int  temp;temp=va_arg(ap,int);va_end():完成收尾工作va_end(ap);在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数如第一个参数值为总的实际参数的个数257 使用参数数目可变的函数时要注意以下几点:1、在定义函数时,固定参数部分必须放在参数表的前面,可变参数在后面,并用省略号“...”表示可变参数在函数调用时,可以没有可变的参数2、必须使用函数va_start()来初始化可变参数,为取第一个可变的参数作好准备工作;使用函数va_arg()依次取各个可变的参数值;最后用函数va_end()做好结束工作,以便能正确地返回3、在调用参数个数可变的函数时,必定有一个参数指明可变参数的个数或总的实参个数258 函数的重载函数的重载所谓函数的重载是指完成不同功能的函数可以具所谓函数的重载是指完成不同功能的函数可以具有有相同的函数名相同的函数名 C++的编译器是根据的编译器是根据函数的实参函数的实参来确定应该调用来确定应该调用哪一个函数的。

      哪一个函数的 int  fun(int a,  int b){   return a+b;  }int  fun (int a){   return a*a;  }void  main(void){  cout<>x;cout<

      与宏名相同,也不进行置换4、在进行宏定义中,可以用已定义的宏名,进行、在进行宏定义中,可以用已定义的宏名,进行层层置换层层置换267 # define  R  3.0# define   PI  3.1415926# define   L   2*PI*R# define   S    PI*R*Rvoid main(void){      cout<<“L=“<>x>>y; area=S(x, y);    /*  area=x*y;  */形式参数形式参数实际参数实际参数宏定义宏定义宏调用宏调用定义的宏定义的宏实参代入后还原实参代入后还原269 按按#define命令行中指定的字符串从左至右进行置命令行中指定的字符串从左至右进行置换宏名,字符串中的换宏名,字符串中的形参以相应的实参代替形参以相应的实参代替,字符,字符串中的非形参字符保持不变。

      串中的非形参字符保持不变define  S(a, b)    a*barea=S(3,2)3*2机械机械地将实参代入地将实参代入宏定义的形参形式宏定义的形参形式S(a,b)等同于等同于  a*bS(3,2)等同于等同于  3*2270 #define  PI  3.1415926#define   S(r)   PI*r*rvoid main(void){  float  a,  area,  b;    a=3.6; b=4.0;    area=S(a);   cout<<“r=“<

      定义宏时在宏名与带参数的括弧间不能有空格define  S_ (r)   P*r*r 带参数的宏与函数调用的区别带参数的宏与函数调用的区别相同:有实参、形参,代入调用相同:有实参、形参,代入调用不同之处:不同之处:1、、函数调用先求表达式的值,然后代入形参函数调用先求表达式的值,然后代入形参,而宏只是,而宏只是机机械替换械替换2、、函数调用时形参、实参进行类型定义函数调用时形参、实参进行类型定义,而宏不需要,只,而宏不需要,只是作为是作为字符串替代字符串替代3、、函数调用是在运行程序时进行的,其目标代码短,但程函数调用是在运行程序时进行的,其目标代码短,但程序执行时间长序执行时间长而宏调用是在编译之前完成的,运行时已而宏调用是在编译之前完成的,运行时已将代码替换进程序中,目标代码长,执行时间稍快将代码替换进程序中,目标代码长,执行时间稍快一般用宏表示实时的、短小的表达式一般用宏表示实时的、短小的表达式273 #define  A  3#define B(a)  ((A+1)*a)执行执行 x=3*(A+B(7)); 后,后, x的值为的值为:93#define  neg(x)   ((-x)+1)int  neg( int x){return  x+1;  }void main(void){  int y;   y=neg(1);  cout<<“y=“<

      即将另外的文件包含到本文件之中  include   “文件名文件名”file1.cppBA#include “file2.cpp”ABfile1.cppfile2.cpp275 注意:注意:1、文件名是、文件名是C的源文件名,是文本文件,后缀名可的源文件名,是文本文件,后缀名可以任选cpp *.h2、一个、一个#include语句只能指定一个被包含文件语句只能指定一个被包含文件3、文件名用双引号或尖括号括起来文件名用双引号或尖括号括起来4、、包含后所有源文件编译为一个可执行文件包含后所有源文件编译为一个可执行文件276 条件编译条件编译C语言允许有选择地对程序的某一部分进行编译语言允许有选择地对程序的某一部分进行编译也就是对一部分源程序指定编译条件也就是对一部分源程序指定编译条件源程序源程序可以将部分源程序可以将部分源程序不不转换为机器码转换为机器码277 条件编译有以下几种形式:条件编译有以下几种形式:1、、  # ifdef      标识符标识符               程序段程序段1        # else               程序段程序段2        # end if当标识符已被定义过(用当标识符已被定义过(用#define定义定义),则对程序段,则对程序段1进行编译,进行编译,否则编译程序段否则编译程序段2.# define  DEBUG......#  ifdef   DEBUG      cout<

       define  DEBUG......#  ifndef   DEBUG      cout<

      当一个完整的程序被存放在多于一个文件中时,称当一个完整的程序被存放在多于一个文件中时,称为程序的多文件组织为程序的多文件组织 282 内部函数和外部函数内部函数和外部函数内部函数:函数只限于在本文件中调用,其它文件不能调内部函数:函数只限于在本文件中调用,其它文件不能调用,用用,用static 定义该函数定义该函数static  float  fac( int  n){   ......      }外部函数:函数的默认形式,可以被其它文件调用,用外部函数:函数的默认形式,可以被其它文件调用,用extern 定义该函数调用时,在文件中用定义该函数调用时,在文件中用extern 说明void main(void){  extern  enter_string( );    char   str[80];    enter_string(str);    ..........}说明外部函数说明外部函数283 补充算法补充算法方程求解方程求解1、牛顿切线法、牛顿切线法只有为数不多的方程有精确解,一般都是用迭代方法近似只有为数不多的方程有精确解,一般都是用迭代方法近似求方程的解方程求方程的解方程f(x)=0的实数解实际上是曲线的实数解实际上是曲线f (x)在在x轴轴上交点的值。

      上交点的值f(x)xyx0284 1、任选一、任选一x值值x1,在在y1=f(x1)处做切线与处做切线与x轴相交于轴相交于x2处f(x)xyx0f(x1)x1x22、若、若|x2-x1|或或|f(x2)|小于指定的精度,则令小于指定的精度,则令x1=x2,继续做,继续做1当其满足所需的精度时,当其满足所需的精度时,x2就是方程的近似解就是方程的近似解x1x2根据已知点求其切线的公式为:根据已知点求其切线的公式为:这就是牛顿切线法这就是牛顿切线法牛顿切线法收敛快,牛顿切线法收敛快,适用性强,缺陷是必适用性强,缺陷是必须求出方程的导数须求出方程的导数285 已知方程为已知方程为f(x)=x*x-a时,用牛顿切线法求方程的解给定时,用牛顿切线法求方程的解给定初值初值x0,精度,精度10-6,算法编程如下算法编程如下cin>>x1; //从键盘输入从键盘输入x0 do{   x0=x1;     x1=x0-(x0*x0-a)/(2*x0) ;  // } while (fabs(x1-x0)>=1e-6) ;cout>>”x=”>>x1>>endl;旧值算本次循环的新值旧值算本次循环的新值上一循环的新值成为本次循环的旧值上一循环的新值成为本次循环的旧值286 2、弦截法、弦截法f(x)xyx1、在、在x轴上取两点轴上取两点x1和和x2, 要确保要确保x1与与x2之间有且只有方程唯一的解之间有且只有方程唯一的解。

      x1x2f(x1)f(x2)2、、x1与与x2分别与分别与f(x)相交于相交于y1=f(x1)、、y2=f(x2)3、做直线通过、做直线通过y1、、y2与与x轴交于轴交于x0点x0x2x04、若、若|f(x0)|满足给定的精度,则满足给定的精度,则x0即是方程的解,否则,若即是方程的解,否则,若f(x0)*f(x1)<0,,则则方程的解应在方程的解应在x1与与x0之间,令之间,令x2=x0,继续做,继续做2同理,若理,若f(x0)*f(x1)>0,,则则方程的解应在方程的解应在x2与与x0之间,令之间,令x1=x0,继续,继续做做2 ,直至满足精度为止直至满足精度为止287 用两分法求方程的根用两分法求方程的根      x3-5x2+16x-80=0#include float f (float x){return  x*x*x-5*x*x+16*x-80;}float  xpoint(float x1,float x2) {  float  x0;     x0=(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1));     return   x0;}void main(void ){ float x1,x2, x0, f0, f1, f2;   do    {  cout<<“Input x1, x2\n”;       cin>>x1>>x2;       f1=f(x1);   f2=f(x2);     } while (f1*f2>0);     do    {  x0=xpoint(x1,x2);      f0=f(x0);   if ((f0*f1) >0) { x1=x0;f1=f0;}   else {  x2=x0;  f2=f0;}      }while (fabs(f0)>=0.0001);    cout<<”x=”<< x0<

      x1x22、求出、求出x1,x2的中点的中点x0x0x2x03、若、若|f(x0)|满足给定的精度,则满足给定的精度,则x0即是方程的解,否则,即是方程的解,否则,若若f(x0)*f(x1)<0,,则则方程的解应在方程的解应在x1与与x0之间,令之间,令x2=x0,,继续做继续做2同理,若同理,若f(x0)*f(x1)>0,,则则方程的解应在方程的解应在x2与与x0之间,令之间,令x1=x0,继续做,继续做2 ,直至满足精度为止直至满足精度为止x0=(x1+x2)/2289 用两分法求方程的根用两分法求方程的根      x3-5x2+16x-80=0#include float f (float x){return  x*x*x-5*x*x+16*x-80;}void main(void ){ float x1,x2, x0, f0, f1, f2;   do    {  cout<<“Input x1, x2\n”;       cin>>x1>>x2;       f1=f(x1);   f2=f(x2);     } while (f1*f2>0);     do    {  x0=(x1+x2)/2;        f0=f(x0);      if ((f0*f1) >0){ x1=x0;f1=f0;}      else { x2=x0;f2=f0;}       }while (fabs(f0)>=0.0001);    cout<<”x=”<< x0<

      的值,请填空include “math.h”double pi(double eps){  double  s, t;  int n;   for ( ___________; t>eps; n++)     {  s+=t;         t=n*t/(2*n+1);      }     return  ___________ ;}main( ){  double x;     cout<<“\nInput a precision:”;     cin>>x;     cout<< “π=“<=10)       f(n/10); cout<545455555657294 第六章第六章     数组数组 295 一维数组的定义和引用一维数组的定义和引用     数组是同一类型的一组值(数组是同一类型的一组值(10个个 char 或或15个个 int)) ,,在内存中顺序存放在内存中顺序存放。

             整个数组共用一个名字,而其中的每一项又称整个数组共用一个名字,而其中的每一项又称为一个元素为一个元素一、定义方式:一、定义方式:类型说明符类型说明符     数组名数组名[常量表达式常量表达式]; int     a[4];    // 表明表明a数组由数组由4个个int型元素组成型元素组成 定义类型定义类型数组名称数组名称元素个数元素个数296       int     a[4];  // 表明表明a数组由数组由4个个int型元素组成型元素组成      其元素分别为:其元素分别为:a[0], a[1], a[2], a[3]      其序号从其序号从0开始开始若存放首地址为若存放首地址为2000H,则在,则在内存中为:内存中为:a[3]a[2]a[1]a[0]2010H200CH2008H2004H2000HC++不允许对数组的大小作动态的定义,不允许对数组的大小作动态的定义,即即数组的数组的大小不能是变量大小不能是变量,必须是常量,必须是常量必须是常数必须是常数297 如果要根据不同的数值改变数组的大小,可如果要根据不同的数值改变数组的大小,可用常量表达式如:用常量表达式。

      如:#define  SIZE   50void main(void){   int   art[SIZE];     ......}298 二、一维数组元素的引用二、一维数组元素的引用数组必须先定义,具体引用时(赋值、运算、输出)其元数组必须先定义,具体引用时(赋值、运算、输出)其元素素等同于变量等同于变量void main(void ){   int  i,  a[10];    for ( i=0; i<10; i++)        a[i]=i;     for ( i=9; i>=0 ; i--)        cout<

      注意:注意:1、对数组中的一部分元素列举初值,未赋值的部、对数组中的一部分元素列举初值,未赋值的部分是分是0int  a[10]= {0,1, 2, 3, 4, 5};2、不能给数组整体赋值,只能一个一个地赋值不能给数组整体赋值,只能一个一个地赋值      int  a[10]= {0,1,2,.....,9}; 非法非法int  a[10]= {0,1, 2, 3, 4, 5,6,7,8,9};int  a[10]= {0,1, 2, 3, 4, 5, 0, 0, 0, 0};300 3、可以用、可以用   int  a[ ]= {0,1, 2, 3, 4, 5, 6, 7, 8, 9};   给数给数组赋值,组赋值,编译器会自动计算出内的元素项数,并将编译器会自动计算出内的元素项数,并将数组定义为该长度数组定义为该长度4、用局部、用局部static 或全局定义的数组不赋初值,或全局定义的数组不赋初值,系统系统均默认其为均默认其为‘\0’static  int  a[10];(即存储在静态数据区中的数组其(即存储在静态数据区中的数组其元素默认为元素默认为0))数组在内存中顺序存放,第一个元素位于地址的最数组在内存中顺序存放,第一个元素位于地址的最低端。

      低端0000000000a301 求求Fibonacci数列:数列:1,1,2,3,5,8,......的前的前20个数,即个数,即              F1=1  (n=1)              F2=1(n=2)              Fn=Fn-1+Fn-2 (n>=3) 2113853211....f[7]f[6]f[5]f[5]f[4]f[3]f[2]f[1]f[0]f [i]=f [i-1]+f [i-2]void main (void){   int  i;     int  f [20]={1,1};     for (i=2 ; i<20 ; i++ )           f [i]=f [i-1]+f [i-2];  for ( i=0; i<20; i++)    {   if (i%5= =0)  cout<<“\n”;         cout<3))%5 ;          cout<

      将相邻的两个数两两比较,将小的调到前头985420895420859420854920854290854209第一趟第一趟循环循环5次次584209548209542809第二趟第二趟循环循环4次次854209543089543089453089435089430589第三趟第三趟循环循环3次次304 430589340589304589304589第四趟第四趟循环循环2次次034589第五趟第五趟循环循环1次次总结:总结:n次数次数趟数趟数j(1~n-1)54321n-j12345共有共有6个数个数for (j=1; j<=n-1; j++)   for (i=1; i<=n-j ; i++)      {   if (a[i]>a[i+1])             {  t=a[i];                 a[i]=a[i+1];                 a[i+1]=t;              }        } 305 一般,元素的序号从一般,元素的序号从0开始,因此,程序可以变动如下:开始,因此,程序可以变动如下:for (j=0; ja[i+1])             {  t=a[i];                 a[i]=a[i+1];                 a[i+1]=t;              }        } 306 二维数组的定义和引用二维数组的定义和引用一、定义方式:一、定义方式:  类型说明符类型说明符    数组名数组名[常量表达式常量表达式][常量表达式常量表达式];int     a[3][4];  其元素分别为:其元素分别为:a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], a[1][1],   a[1][2], a[1][3], a[2][0], a[2][1], a[2][2], a[2][3] 表明表明a数组由数组由3×4个个int型元素组成型元素组成 定义类型定义类型数组名数组名行数行数列数列数307 其行列的序号均其行列的序号均从从0开始开始。

      若存放首地址为若存放首地址为2000H,,则在内存中为:则在内存中为:a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1] a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]2000H2008H2010H 2014H201cH 2020H2028H 202cH即在内存中,多维数组依然是即在内存中,多维数组依然是直线顺序直线顺序排列的,排列的,第第一个元素位于最低地址处一个元素位于最低地址处其元素分别为:其元素分别为:a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], a[1][1],   a[1][2], a[1][3], a[2][0], a[2][1], a[2][2], a[2][3] 308 二、二维数组的引用二、二维数组的引用与一维数组一样,二维数与一维数组一样,二维数组必须先定义,其维数必组必须先定义,其维数必须是常量具体引用时须是常量具体引用时(赋值、运算、输出)其(赋值、运算、输出)其元素等同于变量元素等同于变量void main(void){   int  a[2][3], i, j;     cout<<“Input 2*3 numbers\n”;     for (i=0; i<2; i++) /* 输入输入 */         for(j=0; j<3; j++)             cin>>a[i][j];     for (i=0; i<2; i++)  /* 输出输出 */        { for(j=0; j<3; j++)             cout<输出:输出: _ _ _1_ _ _2_ _ _3             _ _ _4_ _ _5_ _ _6定义定义赋值赋值输出输出309 三、二维数组的初始化三、二维数组的初始化在定义数组的同时给数组元素赋值。

      即在编译阶段在定义数组的同时给数组元素赋值即在编译阶段给数组所在的内存赋值给数组所在的内存赋值1、分行赋值、分行赋值int  a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};2、顺序赋值、顺序赋值int  a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; //依次赋值依次赋值 310 3、部分赋值、部分赋值int  a[3][4]={{1},{5},{9}};     /* a[0][0]=1, a[1][0]=5, a[2][0]=9  其余元素为其余元素为0 */int  a[3][4]={{0,1},{5}}; /* a[0][0]=0, a[0][1]=1, a[1][0]=5  */ 100050009000010050000000311 4、、分行或全部赋值时,分行或全部赋值时,可以省略第一维,第二维可以省略第一维,第二维不可省int  a[ ][4]={{1,2},{5,6,7,8,}{9,10,11,12}}; 5、不能给数组整体赋值,只能一个一个地赋值不能给数组整体赋值,只能一个一个地赋值      6、用、用static 定义的数组不赋初值,系统均默认其为定义的数组不赋初值,系统均默认其为‘\0’。

      static  int  a[2][3];int  a[2][3]={1,2,3,.....,12};312 void main(void){   int  a[3][3], i, j;     for (i=0; i<3; i++)     { for (j=0; j<3; j++)           if (i= =2)               a[i][j]=a[i-1][a[i-1][j]]+1;           else                 a[i][j]=j;         cout<

      那个元素的值,以及其所在的行号和列号 先考虑解此问题的思路从若干个数中求最大者的先考虑解此问题的思路从若干个数中求最大者的方法很多,我们现在采用方法很多,我们现在采用““打擂台打擂台””算法如果有算法如果有若干人比武,先有一人站在台上,再上去一人与其若干人比武,先有一人站在台上,再上去一人与其交手,败者下台,胜者留台上第三个人再上台与交手,败者下台,胜者留台上第三个人再上台与在台上者比,同样是败者下台,胜者留台上如此在台上者比,同样是败者下台,胜者留台上如此比下去直到所有人都上台比过为止最后留在台上比下去直到所有人都上台比过为止最后留在台上的就是胜者的就是胜者314 程序模拟这个方法,开始时把程序模拟这个方法,开始时把a[0][0]a[0][0]的的值赋给变量值赋给变量maxmax,,maxmax就是开始时的擂主,就是开始时的擂主,然后让下一个元素与它比较,将二者中然后让下一个元素与它比较,将二者中值大者保存在值大者保存在maxmax中,然后再让下一个元中,然后再让下一个元素与新的素与新的maxmax比,直到最后一个元素比完比,直到最后一个元素比完为止maxmax最后的值就是数组所有元素中最后的值就是数组所有元素中的最大值。

      的最大值315 max=a[0][0];  //使使max开始时取开始时取a[0][0]的值的值  for (i=0;i<=2;i++)   //从第从第0行到第行到第2行行    for (j=0;j<=3;j++) //从第从第0列到第列到第3列列      if (a[i][j]>max)//如果某元素大于如果某元素大于max     {           max=a[i][j]; //max将取该元素的值将取该元素的值            row=i;    //记下该元素的行号记下该元素的行号i            colum=j;  //记下该元素的列号记下该元素的列号j      }  cout<

      均成绩,并输出低于平均成绩的学生成绩输入负数结束输入负数结束void  main(){  float  x[100],sum=0, ave,a;   int n=0,i;    cout<<“Input score\n”;    _________;   while(__________)   {   x[n]=a;         _______;        _________       cin>>a;    }ave=sum/n;cout<<“ave=“<>aa>=0sum+=an++i

      倒序排列321 void main(void){     int x , i, n ;      int a[100];      cin>>x;     i=0;    while(x)   {          a[i]=x%8;        x=x/8;        i++;    }   n=i;for(i=n-1;i>=0;i--)      cout<>x;    2536913 25 34 56 7836913 34 56 78x25y253434323 36913 34 56 78x25y25343436913 25 56 78x3434y345656324 void main(void){ int a[6]={1,4,7,10,12};  int x;  for(int i=0;i<5;i++)      cout<>x;  for(i=0;i<5;i++) {    if(a[i]>x)  break;  }for(int j=i;j<=5;j++){int y=a[j];a[j]=x;x=y;}for( i=0;i<6;i++)cout<>x;    25369 132534 56 78326 void main(void){ int a[6]={1,4,7,10,12};  int b[6];  int x;  for(int i=0;i<5;i++)cout<>x;  for(i=0;i<5;i++)if(a[i]>x;    2578563425for(i=n-1;i>=0;i--)从后向前循环从后向前循环328 void main(void){ int a[6]={2,5,8,10,12};  int x;  for(int i=0;i<5;i++)cout<>x;  for(i=4;i>0;i--) {    if(a[i]>x)a[i+1]=a[i];       elsebreak;  }   a[i+1]=x;   for(i=0;i<6;i++)cout<

      之间的所有素数 筛法:首先将筛法:首先将1~~n个数为数组置初值个数为数组置初值2的倍数不的倍数不是素数,置是素数,置0;; 3的倍数不是素数,置的倍数不是素数,置0;;5的倍数不的倍数不是素数,置是素数,置0;;....,依次类推,最后将数组中不,依次类推,最后将数组中不是是0的元素输出的元素输出23456789 10 11 12 13 14 15 16 17 18 19 20230507090 11 0 13 0 15 0 17 0 19 0230507000 11 0 13 000 17 0 19 0330 数组作为函数参数数组作为函数参数一、数组元素作函数参数一、数组元素作函数参数数组元素作函数实参,用法与一般变量作实参相同,数组元素作函数实参,用法与一般变量作实参相同,是是“值传递值传递”331 有两个数据系列分别为:有两个数据系列分别为:int a[8]={26,1007,956,705,574,371,416,517};int b[8]={994,631,772,201,262,763,1000,781};求第三个数据系列求第三个数据系列 c ,要求,要求c中的数据是中的数据是a b中对应中对应数的最大公约数。

      数的最大公约数       int a[8]={26,  1007,  956,  705,   574,  371,  416,      517};int b[8]={994, 631,  772,   201,   262,   763,  1000,   781};        c[8]={2,    1,       4,       3 ,     2     ,  7   ,   8,        11}332 int gys(int m,int n){  int r;   if(m

      这时,这时,函数传递的是数组在内存中的地址函数传递的是数组在内存中的地址在在C++中,数组名被认为是中,数组名被认为是数组在内存中存放的数组在内存中存放的首地址首地址实参中的数组地址传到形参中,实参形参实参中的数组地址传到形参中,实参形参共用同共用同一段内存一段内存334 void  fun(int a[2]){  for(int i=0;i<2;i++)       a[i]=a[i]*a[i];  }void main(void){   int b[2]={2,4};     cout<x[j+1])              {  t=x[j]; x[j]=x[j+1]; x[j+1]=t;}  } void main(void){   int a[5]={20,4,16,8,10};     sort(a, 5 );    for(int i=0;i<5;i++)        cout<

      void main(void){  static  float  score[10]={ 100, 90,  ...};    float  aver;    aver=average(score);    cout<<“aver=“<

      递的是数组在内存中的首地址实参和形参共占实参和形参共占一段内存单元一段内存单元,,形参数组中的值发生变化,也相形参数组中的值发生变化,也相当于实参数组中的值发生变化当于实参数组中的值发生变化 score[8]score[6]score[4]score[2]score[0]array[8]array[6]array[4]array[2]array[0]scorearray339 程序中的函数程序中的函数p( )用于计算:用于计算:主函数利用函数完成计算主函数利用函数完成计算int p(int a, int x[], int b, int y[], int n){  int i, s;  for(________; i

      中数据的个数例如:例如:原数组:原数组:2 2 2 3 4 4 5 6 6 6 6 7 7 8 9 9 10 10 10删除后:删除后:2 3 4 5 6 7 8 9 10 342 用多维数组名作函数参数用多维数组名作函数参数同样,实参向形参传递的是数组的首地址同样,实参向形参传递的是数组的首地址如果实参、形参是二维数组,如果实参、形参是二维数组,则形参可以省略第一维则形参可以省略第一维,不,不可省略第二维,且可省略第二维,且第二维必须与实参中的维数相等第二维必须与实参中的维数相等int  array[ ][10]int  score[5][10]int  array[3][10]int  score[5][10]int  array[  ][8]int  score[5][10]错误错误343 有一个有一个3×4的矩阵,求其中的最大元素的矩阵,求其中的最大元素int max_value (int array[ ][4]){   int  i, j, k, max;     max=array[0][0];    for (i=0; i<3; i++)        for (j=0; j<4; j++)             if (array[i][j]>max)                    max=array[i][j];     return (max);} void main (void){ static  int  a[3][4]={{1,3,5,7},         {2,4,6,8},{15,17,34,12}}; cout<<“max  is ”<

      一、字符数组的定义一、字符数组的定义char       数组名数组名[常量表达式常量表达式];char     c[4];    /*每个元素占一个字节每个元素占一个字节 */c[0]=‘I’;  c[1]=‘m’;   c[2]=‘_’;;类型类型数组名数组名数组大小数组大小345 二、字符数组的初始化二、字符数组的初始化与数值数组的初始化相同,取其相应字符的与数值数组的初始化相同,取其相应字符的ASCII值char  c[10]={‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’, ‘a’, ‘ ’ , ‘b’, ‘o’, ‘y’};  随机随机‘y’‘o’‘b’‘ ’‘a’‘ ’‘m’‘a’‘ ’‘I’cc[0]c[9]346 如果字符个数大于数组长度,做错误处理;如果数值个数如果字符个数大于数组长度,做错误处理;如果数值个数小于数组长度,后面的字节全部为小于数组长度,后面的字节全部为‘\0’如果省略数组长度,则字符数即为数组长度如果省略数组长度,则字符数即为数组长度static   char  c[ ]={‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’, ‘a’, ‘ ’ , ‘g’, ‘i’, ‘r’,’l’}; 同理,也可定义和初始化一个二维或多维的字符数组。

      分同理,也可定义和初始化一个二维或多维的字符数组分层或省略最后一维层或省略最后一维char   st1[ ]={65, 66, 68};‘A’‘B’‘D’347 三、字符数组的引用三、字符数组的引用void main(void){ char  c[10]={‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’, ‘a’, ‘ ’ , ‘b’, ‘o’, ‘y’};          int  i;        for (i=0; i<10; i++)              cout<

      349 字符串与字符数组的区别:字符串与字符数组的区别:char  a[ ]={‘C’,’H’,’I’,’N’,’A’};char  c[ ]=“CHINA”;  随机随机随机随机ANIHC长度占长度占5个个字节字节随机随机‘\0’ANIHC长度占长度占6个字节个字节字符数组字符数组字符串字符串350 可以用字符串的形式为字符数组赋初值可以用字符串的形式为字符数组赋初值char  c[ ]={“I am a boy”};  /*长度长度11字节,以字节,以‘\0’结结尾尾  */char  a[ ]={‘I’, ‘ ’, ‘a’, ‘m’, ‘ ’, ‘a’, ‘ ’ , ‘b’, ‘o’, ‘y’};                   /* 长度长度10字节字节  */如果数组定义的长度大于字符串的长度,后面均为如果数组定义的长度大于字符串的长度,后面均为‘\0’char  c[10]=“CHINA”;  ‘\0’‘\0’‘\0’‘\0’‘\0’ANIHCc‘\0’的的ASCII为为0,,而而‘ ’(空格空格)的的ASCII为为32351 char  w[ ]={‘T’, ‘u’, ‘r’, ‘b’, ‘o’, ‘\0’};Turbo ‘\0’char  w[ ]={“Turbo\0”};Turbo ‘\0’char  w[ ]=“Turbo\0”;Turbo ‘\0’char  w[ ]=‘Turbo\0’;非法非法352 char  a[2][5]={“abcd”, “ABCD”};abcd‘\0’ABCD‘\0’在在语句中语句中字符数组不能用赋值语句字符数组不能用赋值语句整体赋值整体赋值。

      char  str[12];str=“The String”;str为字符数组在内存中存储的地址,一经定义,便成为常为字符数组在内存中存储的地址,一经定义,便成为常量,不可再赋值量,不可再赋值char str[12]=“The String”;;非法,在语句中赋值非法,在语句中赋值定义数组,开辟空定义数组,开辟空间时赋初值间时赋初值353 字符数组的输入输出字符数组的输入输出 逐逐个个字字符符的的输输入入输输出出这这种种输输入入输输出出的的方方法法,,通通常常是是使使用循环语句来实现的如:用循环语句来实现的如:char  str[10];cout<<“输入十个字符:输入十个字符:”;for(int i=0;i<10;i++)      cin>>str[i];//A               ......A行将输入的十个字符依次送给数组行将输入的十个字符依次送给数组str中的各个元素中的各个元素定义定义赋值赋值354 把把字字符符数数组组作作为为字字符符串串输输入入输输出出对对于于一一维维字字符符数数组组的的输输入入,,在在cincin中中仅仅给给出出数数组组名名;;输输出出时时,,在在coutcout中也只给出中也只给出数组名数组名。

      void main (void ){char  s1[50],s2[60];cout << “输入二个字符串输入二个字符串:”;cin >>  s1;cin >> s2;cout << “\n s1 = “ <<  s1;cout << “\n s2 = “ << s2 << “\n”; }输入:输入:abcdstringcin只能输入一个单只能输入一个单词,不能输入一行词,不能输入一行单词数组名数组名数组名数组名输出到输出到‘\0’为为止止355 当要把当要把输入的一行输入的一行作为一个字符串送到字符数组中作为一个字符串送到字符数组中时,则要使用函数时,则要使用函数cin.getline( )这个函数的第一这个函数的第一个参数为字符数组名,第二个参数为允许输入的最个参数为字符数组名,第二个参数为允许输入的最大字符个数大字符个数 cin.getline(数组名数组名, 数组空间数数组空间数);char  s1[80];.......cin.getline(s1, 80);首先开辟空间首先开辟空间参数是数组名参数是数组名356 void main (void ){   char s3[81];    cout<<”输入一行字符串输入一行字符串:”;    cin.getline(s3,80);//A   cout<<””s3=””<

      个字符送给字符串 定义定义从键盘接收一行字符从键盘接收一行字符输出到输出到‘\0’为为止止357 从键盘输入一行字符,统计其中分别有从键盘输入一行字符,统计其中分别有多少大小写字母,多少大小写字母,以以$号结束输入号结束输入从键盘输入一行字符,统计其中分别有从键盘输入一行字符,统计其中分别有多少大小写字母多少大小写字母从键盘输入一行字符,其中的大写变小从键盘输入一行字符,其中的大写变小写,小写变大写写,小写变大写358 从键盘接收一行字符,统计有多少个单词数?从键盘接收一行字符,统计有多少个单词数?we    are     students.weares字母字母字母字母空格空格空格空格字母字母字母字母字母字母空格空格字母字母不能用字母数或空格数来判断,只能用字母和空格不能用字母数或空格数来判断,只能用字母和空格状态变状态变化化的次数来判断的次数来判断设状态变量设状态变量word , 判别到字母时判别到字母时word为为1,判别到非字母,判别到非字母时时word为为0word的初始值为的初始值为0,当从,当从0变为变为1时,单词数加时,单词数加10110011101359 void main(void){char s[80];int i=0, word=0,num=0;cin.getline (s,80);while(s[i]!='\0'){ if((s[i]>='a'&&s[i]<='z'||s[i]>='A'&&s[i]<='Z')&&word==0)  {word=1;num++;  }  else if(s[i]==' '||s[i]=='\t')          word=0;  i++; }  cout<<"num="<

      后注意:第一个字符串要有足够的空间注意:第一个字符串要有足够的空间空间足够大空间足够大362 2、复制两个字符串的函数、复制两个字符串的函数  strcpy (str1, str2)static  char  str1[20]={“I am a ”};static  char  str2[ ]={“boy”};strcpy (str1, str2);'\0''\0'amaIstr1'\0'yobstr2'\0''\0'a'\0'yobstr1strcpy ( str1, “CHINA”);'\0'ANIHCstr1strcpy (“CHINA”, str1);str1=str2;     str1=“CHINA”;    字符串正确赋值字符串正确赋值均为非法均为非法363 3、比较两个字符串的函数、比较两个字符串的函数  strcmp (str1, str2)此函数用来比较此函数用来比较str1和和str2中字符串的内容函数对字符串中字符串的内容函数对字符串中的中的ASCII字符字符逐个两两比较逐个两两比较,直到遇到不同字符或,直到遇到不同字符或‘\0’为止函数值由两个对应字符相减而得。

      为止函数值由两个对应字符相减而得该函数具有返回值,返回值是两字符串对应的该函数具有返回值,返回值是两字符串对应的第一个第一个不同不同的的ASCII码的差值码的差值若两个字符串完全相同,函数值为若两个字符串完全相同,函数值为0  if ( strcmp (str1, str2)==0)    {   ........  }用来判断两字符用来判断两字符串是否相等串是否相等364 static  char  str1[20]={“CHINA”};static  char  str2[ ]={“CHINB”};cout<< strcmp (str1, str2)<

      函数参数为数组名,返回值为数组首字母到函数参数为数组名,返回值为数组首字母到‘\0’的长度并非数组在内存中空间的大小并非数组在内存中空间的大小char  s[80];strcpy(s, “abcd”);cout<

      6、、 strupr (str1)将将str1中的小写字母转换成大写字母中的小写字母转换成大写字母368 7、函数、函数strncmp(字符串字符串1,字符串字符串2 , maxlen)函数原型为函数原型为: int  strncmp(char str1[ ], char str2[ ],int m)第三个参数为正整数,它限定了至多比较的字符个数第三个参数为正整数,它限定了至多比较的字符个数若字符串若字符串1或字符串或字符串2的长度小于的长度小于maxlen的值时,函数的的值时,函数的功能与功能与strcmp( )相同当二个字符串的长度均大于当二个字符串的长度均大于maxlen的值时,的值时,maxlen为至为至多要比较的字符个数多要比较的字符个数cout<

      贝的字符个数8、函数、函数strncpy(字符数组名字符数组名1, 字符串字符串2, maxlen)函数原型为函数原型为: void strncmp(char str1[ ], char str2[ ],int m)370 char s[90],s1[90];strncpy(s,"abcdssfsdfk",3); //Astrncpy(s1,"abcdef " , 90);//Bcout<0) changed(s1,s2); if(strcmp(s1,s3)>0) changed(s1,s3); if(strcmp(s2,s3)>0)changed(s2,s3); cout<<"sorted:"<0)changed(ss[j],ss[j+1]); cout<<"sorted:"<

      最上面的数比较交换024589a[6]a[5]a[4]a[3]a[2]a[1]2、、a[min]与与a[2]比较比较1min1、、min=13、、min=22min4、、 a[min]与与a[3]比较比较024589a[6]a[5]a[4]a[3]a[2]a[1]即即9与与8比较比较假定元素假定元素序号序号为为1的数是最的数是最小的数小的数这时,最小数这时,最小数的序号变为的序号变为2即即8与与5比较比较375 024589a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[4]比较比较3min     min=3   min=44mina[min]与与a[5]比较比较024589a[6]a[5]a[4]a[3]a[2]a[1]024589a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[6]比较比较5min     min=5   min=66mina[min]与与a[1]交换交换924580a[6]a[5]a[4]a[3]a[2]a[1]第一趟,循环第一趟,循环5次次这时,最小数这时,最小数的序号变为的序号变为3即即5与与4比较比较这时,最小数这时,最小数的序号变为的序号变为4即即4与与2比较比较这时,最小数这时,最小数的序号变为的序号变为5第一趟比较完毕,第一趟比较完毕,最小数是最小数是a[6],最小,最小数的序号为数的序号为6376 924580a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[3]比较比较2min     min=2   min=33mina[min]与与a[4]比较比较924580a[6]a[5]a[4]a[3]a[2]a[1]924580a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[5]比较比较4min     min=4   min=55mina[min]与与a[6]比较比较924580a[6]a[5]a[4]a[3]a[2]a[1]从第二个数开始从第二个数开始比较,假定最小比较,假定最小数的序号为数的序号为2377 984520a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[2]交换交换5min     min=5第二趟,循环第二趟,循环4次次第二趟比较完毕,第二趟比较完毕,最小数是最小数是a[5],最小,最小数的序号为数的序号为5378 984520a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[4]比较比较3min     min=3   min=44mina[min]与与a[5]比较比较984520a[6]a[5]a[4]a[3]a[2]a[1]984520a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[6]比较比较4min     min=4   min=44mina[min]与与a[3]交换交换985420a[6]a[5]a[4]a[3]a[2]a[1]第三趟,循环第三趟,循环3次次379 985420a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[5]比较比较4min     min=4   min=44mina[min]与与a[6]比较比较985420a[6]a[5]a[4]a[3]a[2]a[1]985420a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[4]交换交换4min     min=4第四趟,循环第四趟,循环2次次380 985420a[6]a[5]a[4]a[3]a[2]a[1]a[min]与与a[6]比较比较5min     min=5   min=55mina[min]与与a[5]交换交换985420a[6]a[5]a[4]a[3]a[2]a[1]第五趟,循环第五趟,循环1次次总结:总结:n次数次数趟数趟数i(1~n-1)54321n-i12345共有共有6个数个数for (i=1; i<=n-1; i++)  {{  min=i ;        for (j=i; j<=n; j++)             if (a[min]>a[j])     min=j ;         t=a[min];                     a[min]=a[i];         a[i]=t;     }              381 一般,元素的序号从一般,元素的序号从0开始,因此,程序可以变动如下:开始,因此,程序可以变动如下:for (i=0; ia[j])                  min=j ;                     t=a[min];         a[min]=a[i];         a[i]=t;    }         小循环,找最小循环,找最小数的序号,小数的序号,从从 i  找起找起大循环,找到大循环,找到后与后与 i 交换交换每一次循环前设每一次循环前设置最小数的序号置最小数的序号382 调试程序的方法:调试程序的方法:1)单步调试:以行为单位,每运行一步,程序就会中断,)单步调试:以行为单位,每运行一步,程序就会中断,可以实时查询目前各变量的状态及程序的走向。

      可以实时查询目前各变量的状态及程序的走向可以选择可以选择是否进入子函数是否进入子函数2))运行到光标处运行到光标处,可以直接使程序运行到,可以直接使程序运行到光标处光标处再进行再进行单步调试,这种方法可以不必运行正确的循环而直接到有单步调试,这种方法可以不必运行正确的循环而直接到有疑问的地方疑问的地方383 在在a数组中查找与数组中查找与x值相同的元素所在的位置,数据从值相同的元素所在的位置,数据从a[1]元素开始存放,请填空:元素开始存放,请填空:#define MAX  10void main(void){  int a[MAX+1], x, i;   for(i=1;i<=MAX;i++)        cin>>__________;    cout<<“Enter x:”;    cin>>x;    a[0]=x;  i=MAX;while(x!=___________)   ____________________;if(___________)      cout<

      顺序排列,被调函数返回删除后数组中数据的个数例如:例如:原数组:原数组:2 2 2 3 4 4 5 6 6 6 6 7 7 8 9 9 10 10 10删除后:删除后:2 3 4 5 6 7 8 9 10 387 第七章第七章       结构体、共同体和枚举类型结构体、共同体和枚举类型 388 定义:定义:将将不同种类型不同种类型的数据有序地的数据有序地组合在一起组合在一起,构,构造出一个造出一个新的数据类型新的数据类型,这种形式称为,这种形式称为结构结构体结构体是多种类型组合的结构体是多种类型组合的数据类型数据类型389 struct       结构体名结构体名{{  成员列表成员列表  };};struct   student   {    int  num;         char  name[20];         char  sex;         char  addr[30];     };结构体名结构体名关键字关键字不同数据不同数据类型组成类型组成的的成员成员分号不能少分号不能少390 定义结构体类型变量的方法定义结构体类型变量的方法一、先定义结构体类型再定义变量名一、先定义结构体类型再定义变量名struct   student   {    int  num;         char  name[20];         char  sex;         int  age;         float  score;         char  addr[30];};struct  student    student1,  student2;结构体类型名结构体类型名变量变量1变量变量2结构体类型只是一种数据结构体类型只是一种数据类型,不占内存空间,只类型,不占内存空间,只有定义结构体类型有定义结构体类型变量变量时时才开辟内存空间。

      才开辟内存空间391 # define  STUDENT  struct   student      STUDENT       {    int  num;             char  name[20];             char  sex;              int  age;             float  score;             char  addr[30];         };      STUDENT    student1,student2;凡是凡是STUDENT的地的地方都用方都用struct student 机械替换机械替换392 二、在定义类型的同时定义变量二、在定义类型的同时定义变量struct   student   {    int  num;         char  name[20];         char  sex;         int  age;         float  score;         char  addr[30];} student1, student2;structstruct 结构体名结构体名 { { 成员列表成员列表 }变量名列表;}变量名列表; 紧接着定紧接着定义变量义变量393 三、直接定义结构体类型变量三、直接定义结构体类型变量struct    {    int  num;         char  name[20];         char  sex;         int  age;         float  score;         char  addr[30];    } student1, student2;struct      {           成员列表成员列表      }变量名列表;}变量名列表;  不出现结构体名。

      不出现结构体名394 2 2、在编译时,仅对、在编译时,仅对变量变量分配空间,不对分配空间,不对类型类型分配分配空间1 1、结构体类型的变量在内存、结构体类型的变量在内存依照其成员的顺序依照其成员的顺序顺顺序排列,所占内存空间的大小是其全体成员所占空序排列,所占内存空间的大小是其全体成员所占空间的间的总和总和3 3、对结构体中各个成员可以单独引用、赋值,其、对结构体中各个成员可以单独引用、赋值,其作用与变量等同作用与变量等同格式:格式:变量名变量名 . . 成员名成员名 student1 . numstudent1 . num395 4 4、结构体的成员可以是另一个结构体类型结构体的成员可以是另一个结构体类型struct  date{  int   month;    int   day;    int  year; };struct  student{  int   num;    char  name[20];       struct  date     birthday; };成员类型成员类型成员名成员名5 5、成员名可以与程序中的变量名相同,二者分占不同的内、成员名可以与程序中的变量名相同,二者分占不同的内存单元,互不干扰。

      例如,在程序中仍可以定义变量存单元,互不干扰例如,在程序中仍可以定义变量 intint num; num;396 结构体类型变量的引用结构体类型变量的引用1 1、不能对结构体变量整体赋值或输出,只能分别对、不能对结构体变量整体赋值或输出,只能分别对各个成各个成员员引用cincin>>student1;>>student1;cincin>>student1.num; student1.num=100;>>student1.num; student1.num=100;可以将一个结构体变量可以将一个结构体变量整体整体赋给另外一个相同类型的结构赋给另外一个相同类型的结构体变量 student2=student1;student2=student1;2 2、嵌套的结构体变量必须逐层引用嵌套的结构体变量必须逐层引用student1.student1.birthday.birthday.dayday=25;=25;3 3、结构体变量中的成员可以同一般变量一样进行运算结构体变量中的成员可以同一般变量一样进行运算student1.birthday.day++; student1.birthday.day++; student1.score+=60;student1.score+=60;错误错误必须用成员名引用必须用成员名引用397 对局部变量类型的结构体变量初始化对局部变量类型的结构体变量初始化void main(void){   struct  student   {    long int  num;         char  name[20];         char  sex;         char  addr[30];    }   student1={901031, “Li Lin”, ‘M’, “123 Beijing Road”};cout<

      这种、同类型的结构体变量之间可以直接赋值这种赋值等同于各个成员的依次赋值赋值等同于各个成员的依次赋值 2 2、、结结构构体体变变量量不不能能直直接接进进行行输输入入输输出出,,它它的的每每一一个个成成员员能能否否直直接接进进行行输输入入输输出出,,取取决决于于其其成成员员的的类类型型,,若若是是基基本本类类型型或或是是字字符符数数组组,,则则可可以以直直接接输输入入输出3 3、、结结构构体体变变量量可可以以作作为为函函数数的的参参数数,,函函数数也也可可以以返返回回结结构构体体的的值值当当函函数数的的形形参参与与实实参参为为结结构构体体类类型型的的变变量量时时,,这这种种结结合合方方式式属属于于值值调调用用方方式式,,即即属属于值传递举例说明)于值传递举例说明)399 结构体数组结构体数组结构体数组中的结构体数组中的每个元素都是一个结构体类型的变每个元素都是一个结构体类型的变量量,其中包括该类型的各个成员数组各元素在内,其中包括该类型的各个成员数组各元素在内存中连续存放存中连续存放400 一、结构体数组的定义一、结构体数组的定义struct   student   {    int  num;         char  name[20];         char  sex;         int  age;         float  score;         char  addr[30];} ;struct  student  stu[30];struct   student   {    int  num;         char  name[20];         char  sex;         int  age;         float  score;         char  addr[30];} stu[30];直接定义直接定义401 二、结构体数组的初始化二、结构体数组的初始化struct   student   {    int  num;         char  name[20];         char  sex;} stu[3]={ {1011, "Li Lin",'M'}, {1012,"Wang Lan",'F'},                   {1013,"Liu Fang",'F'};402 struct   student   {    int  num;         char  name[20];         char  sex;} stu[ ]={ {1011,"Li Lin",'M'}, {1012,"Wang Lan",'F'},                   {1013,"Liu Fang",'F'}};403 以下程序的结果是:以下程序的结果是:void main(void){  struct  date     {  int  year, month,  day;     }  today;    cout<

      <类型类型> <结构体类型名结构体类型名>::::<静态成员名静态成员名>;;其中类型要与在结构体中定义该成员的类型一致,结构体类型名其中类型要与在结构体中定义该成员的类型一致,结构体类型名指明静态成员属于哪一个结构体指明静态成员属于哪一个结构体 struct  s{static int  id;int  eng;};int  s::id=50;这时,未定义结构体变量,这时,未定义结构体变量,但已将静态成员的空间安但已将静态成员的空间安排好排好数据类型结构体类型若有定义:s  s1,s2;则变量s1,s2的id成员占用同一存储空间(静态区)406 在结构体中说明的静态成员属于引用性说明,必须在文件作用域中的某一个地方对静态的成员进行定义性说明,且仅能说明一次int  s::id; 说明id的初值为0(静态变量的缺省初值均为静态变量的缺省初值均为0)  407 共用体共用体C++语言中,允许语言中,允许不同的数据类型使用不同的数据类型使用同一存储区域同一存储区域,即,即同一存储区域由不同类型的变量共同表示这种数据类型同一存储区域由不同类型的变量共同表示这种数据类型就是共用体就是共用体union  共用体名共用体名{  成员表列;成员表列;} 变量表列;变量表列;union  data{  int  i;    char  ch;    float  f;}  a, b, c;union  data  a, b, c;这几个成员在共用体变量中存放在同一地址,相互覆盖,这几个成员在共用体变量中存放在同一地址,相互覆盖,其长度为最长的成员的长度其长度为最长的成员的长度。

      408 共用体变量的引用共用体变量的引用不能整体引用共用体变量,只能引用变量中不能整体引用共用体变量,只能引用变量中的成员a.i    表示为整型表示为整型a.ch   表示为字符型表示为字符型a.f    表示为符点型表示为符点型409 共用体变量的特点共用体变量的特点1、共用体的空间在某一时刻只有一个成员在起作、共用体的空间在某一时刻只有一个成员在起作用2、共用体变量中的成员是最后一次放入的成员共用体变量中的成员是最后一次放入的成员3、共用体变量不能在定义时赋初值共用体变量不能在定义时赋初值4、共用体变量不能作为函数的参数或函数值,但、共用体变量不能作为函数的参数或函数值,但可使用指向共用体的指针变量可使用指向共用体的指针变量5、共用体可以作为结构的成员,结构体也可以作、共用体可以作为结构的成员,结构体也可以作为共用体的成员为共用体的成员410 union  un{  int  i;    double  y;};struct  st{  char  a[10];   union  un   b;};cout<

      为枚举类型枚举类型就是将变量的值一一列举出来,枚举类型就是将变量的值一一列举出来,变变量的值仅限于列举出来的值的范围内量的值仅限于列举出来的值的范围内414 enum  weekday  {sun, mon, tue, wed, thu,  fri,  sat};enum  weekday   workday,  weekend ;workday  和和  weekend  值值只能只能是是sun  到到  sat  其中之一其中之一enum  {sun, mon, tue, wed, thu,  fri,  sat}    workday,  weekend ;其中其中sun, mon,....,sat称为称为枚举元素枚举元素或枚举常量,为用户定义或枚举常量,为用户定义的标识符,的标识符,所代表的意义所代表的意义由用户决定,在由用户决定,在程序中体现出来程序中体现出来数据类型数据类型可能取的值可能取的值变量变量另一种定义变量的方法另一种定义变量的方法415 1 1、枚举元素为常量,不可赋值运算枚举元素为常量,不可赋值运算 sun=0; sun=0; monmon=1;=1;2 2、在定义枚举类型的同时,编译程序按顺序给每个枚举元、在定义枚举类型的同时,编译程序按顺序给每个枚举元素一个对应的序号,序号从素一个对应的序号,序号从0 0开始,后续元素依次加开始,后续元素依次加1 1。

      enumenum weekday {sun, weekday {sun, monmon, , tuetue, wed, , wed, thuthu, , frifri, , sat};sat}; 0 , 1, 2, 0 , 1, 2, 3, 4, 5, 6 3, 4, 5, 6 3 3、可以在定义时人为指定枚举元素的序号值可以在定义时人为指定枚举元素的序号值enumenum weekday {sun=9, weekday {sun=9, monmon=2, =2, tuetue, wed, , wed, thuthu, , frifri, , sat};sat}; 9 , 2, 9 , 2, 3, 4, 5, 6 , 7 3, 4, 5, 6 , 7 4 4、、只能给枚举变量赋枚举值只能给枚举变量赋枚举值,若赋序号值必须进行强制类,若赋序号值必须进行强制类型转换。

      型转换day=day=monmon ; ; day=1day=1; day=(; day=(enumenum weekday)1;weekday)1;416 5、枚举元素可以用来进行比较判断枚举元素可以用来进行比较判断if (workday= = mon)                if (workday>sun)6、枚举值可以进行加减一个整数、枚举值可以进行加减一个整数n的运算,得到其前后第的运算,得到其前后第n个元素的值个元素的值workday=sun;workday=(week)(workday+2);workday= = tue7、枚举值可以按整型输出其序号值枚举值可以按整型输出其序号值workday=tue;cout<

      字符型占空间字符型占1个字节,整型数占个字节,整型数占4个字节个字节.....内存区的每个字节都有编号,称之为的每个字节都有编号,称之为地址地址2000H2001H2002H2003H2004H35内存内存内存单元内存单元的地址的地址内存单元内存单元的内容的内容420 1、直接访问、直接访问按变量地址存取变量的值按变量地址存取变量的值cin>>i;   实际上放到定义实际上放到定义 i 单元单元的的地址中地址中2、间接访问、间接访问将变量的地址存放在另一个单元将变量的地址存放在另一个单元p中中,通过,通过 p 取出变量的地取出变量的地址,再针对变量操作址,再针对变量操作一个变量的地址称为该变量的指针一个变量的地址称为该变量的指针如果在程序中定义了一个变量或数组,那么,这个变量或如果在程序中定义了一个变量或数组,那么,这个变量或数组的地址(指针)也就确定为一个数组的地址(指针)也就确定为一个常量常量ii2000H2000H3000Hp421 变量的变量的指针指针和指向变量的和指向变量的指针变量指针变量变量的指针就是变量的指针就是变量的地址变量的地址,,当变量定义后,其指针(地当变量定义后,其指针(地址)是一常量。

      址)是一常量 可以可以定义一个变量定义一个变量专门用来专门用来存放存放另一变量的另一变量的地址地址,这种,这种变量我们称之为变量我们称之为指针变量指针变量在编译时同样分配一定字节的在编译时同样分配一定字节的存储单元,未赋初值时,该存储单元内的值是存储单元,未赋初值时,该存储单元内的值是随机随机的指针变量定义的一般形式为:指针变量定义的一般形式为:类型标识符类型标识符       *变量名变量名int       *i_point;i2000Hint   i;  &i  ::2000H  指针类型指针类型变量名变量名422 指针指针变量变量同样也可以赋值:同样也可以赋值:int  i,  *i_point;i_point=&i;也可以在定义也可以在定义指针变量指针变量时赋初值:时赋初值:int  i;int   *i_point=&i;  * 在在定义语句定义语句中只表示变量的类型是指针,没有任何计算中只表示变量的类型是指针,没有任何计算意义  * 在语句中表示在语句中表示“指向指向”表示表示“地址地址”一个指针变量只能指向同一类型的变量一个指针变量只能指向同一类型的变量即整型指针变量即整型指针变量只能放整型数据的地址,而不能放其它类型数据的地址。

      只能放整型数据的地址,而不能放其它类型数据的地址3000H i_point2000H i2000H423 2000H2000H3000H i_pointint  i;int *i_point=&i;*i_point=3;表示表示指向指向表示表示类型类型i3424 指针变量的引用指针变量的引用指针变量只能指针变量只能存放地址存放地址,不要将非地址数据赋给指针变量不要将非地址数据赋给指针变量int  *p,  i;     p=100;         p=&i;void main(void){  int  a=10,  b=100;    int  *p1,  *p2;    p1=&a;   p2=&b;    cout<

      运算int  i,  *p1;     p1=&i;    通过指针对通过指针对变量赋值变量赋值但指针变量未赋值,即但指针变量未赋值,即指针指向未知地址指针指向未知地址用指针变量前,必须用指针变量前,必须对指针变量赋值对指针变量赋值427 输入输入a, b两个整数,按大小输出这两个数两个整数,按大小输出这两个数void main(void){   int  *p1, *p2, *p, a,b;    cin>>a>>b;    p1=&a;  p2=&b;    if (a

      表达式为3,    a=47532008H2004H2000Ha&ap(*p)++;  4429 int   a=3,  *p;p=&a;++, - -,  * 优先级相同,都是右结合性优先级相同,都是右结合性7532008H2004H2000Ha&ap2004H*(p++)首先首先*p ,然后,然后p=p+1,指针指向下一指针指向下一个个int单元单元   表达式为表达式为3,  p=2004Hp++;     430 int   a=3,  *p;p=&a;++, - -,  * 优先级相同,都是右结合性优先级相同,都是右结合性7532008H2004H2000Ha&ap4++(*p)      *p=*p+1   a=4++*p431 int   a=3,  *p;p=&a;++, - -,  * 优先级相同,都是右结合性优先级相同,都是右结合性7532008H2004H2000Ha&ap2004H*(++p),首先:,首先:p=p+1,   然后取然后取*p即取p所指的下一个所指的下一个int单元的内容单元的内容表达式为表达式为5    p==2004H*++p     432 指针变量作为函数参数:指针变量作为函数参数:函数的参数可以是指针类型,函数的参数可以是指针类型,它的作用是将它的作用是将一个变量的一个变量的地址地址传送到另一个函数中传送到另一个函数中。

      指针变量作为函数参数与变量本身作函数参指针变量作为函数参数与变量本身作函数参数不同,数不同,变量作函数参数传递的是具体值变量作函数参数传递的是具体值,,而而指针指针作函数参数传递的是作函数参数传递的是内存的地址内存的地址433 输入输入a, b两个整数,按大小输出这两个数两个整数,按大小输出这两个数void main(void){   int  *point1, *point2, a,b;    cin>>a>>b;    point1=&a;  point2=&b;    if (a

      两个整数,按大小输出这两个数void main(void){   int  *point1, *point2, a,b;    cin>>a>>b;    point1=&a;  point2=&b;    if (a

      了的值函数调用函数调用不能改变实参指针变量的值,但不能改变实参指针变量的值,但可可以改变实参指针变量所指向变量的值以改变实参指针变量所指向变量的值436 void  grt(int  *x ,  int *y ,  int  *z){   cout<< ++*x<<‘,’<< ++*y<<‘,’<<*(z++)<>*p;          sum=s(p);        cout<<“sum=”<sum=11sum=13sum=15p&aa1p&asum10sumint s( int  *p){    int  sum=10;     sum=sum + *p;     return sum; }1111438 sub( int  *s){  static  int  t=0;    t=*s + t;    return t;} void main(void){  int  i, k;    for (i=0; i<4; i++)      {   k=sub(&i);           cout<<“sum=“<

      址,一样可以用指针来表示C++规定:规定:数组数组名就是数组的起始地址名就是数组的起始地址;又规定:;又规定:数组的指数组的指针就是数组的起始地址针就是数组的起始地址数组元素的指针就数组元素的指针就是数组元素的地址是数组元素的地址442 一、指向数组元素的指针变量的定义与赋值一、指向数组元素的指针变量的定义与赋值int   a[10], *p;p=&a[0]; p=a;p是变量,是变量,a为常量2024H2020H201CH2018H2014H2010H200CH2008H2004H2000Ha[9]a[8]a[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0]ap&a[0]若数组元素为若数组元素为int型,则指向其的指针变型,则指向其的指针变量也应定义为量也应定义为int型int  a[10];int    *p=a;     int *p=&a[0];数组第一个元素的地址数组第一个元素的地址直接用数组名赋值直接用数组名赋值这两种情况均为赋初值这两种情况均为赋初值443 二、通过指针引用数组元素二、通过指针引用数组元素int  a[10];int  *p=a;     2024H2020H201CH2018H2014H2010H200CH2008H2004H2000Ha[9]a[8]a[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0]ap&a[0]*p=1;   a[0]=1;   1C++C++规定,规定,p+1p+1指向数组的指向数组的下一下一个元素个元素,,而不是下一个字节。

      而不是下一个字节p+1)=2;a[1]=2;2*++p=2;p=p+1;  *p=2;    p=2004H为指针变量赋初值为指针变量赋初值通过指针变量为通过指针变量为数组元素赋值数组元素赋值指针变量也重新赋值指针变量也重新赋值444 *(a+1)=2;*(a+1)与与a[1]等同a=2;a为常量,不可赋值为常量,不可赋值p+i 或或 a+i 均表示均表示 a[i] 的地址的地址 &a[i]2024H2020H201CH2018H2014H2010H200CH2008H2004H2000Ha[9]a[8]a[7]a[6]a[5]a[4]a[3]a[2]a[1]a[0]ap&a[0]12*(p+1)=2;a[1]=2;*++p=2;错误错误*(a+i)a[i]*(p+i)p[i]p=p+1; *p=2; p=2004H445 用用指向数组的指针变量指向数组的指针变量输出数组的全部元素输出数组的全部元素void main(void){   int  a[10], i;     int  *p;     for (i=0; i<10; i++)           cin>>a[i];     for (p=a;  p>a[i];     for (i=0; i<10; i++)          cout<<*p++<<‘\t’;}输入数组元素输入数组元素指针变量赋初值指针变量赋初值指向下一元素指向下一元素输出指针指向的数据输出指针指向的数据*p,   p=p+1输出数据后指针加输出数据后指针加1446 void main(void){   int  x[ ]={1,2,3};     int  s, i, *p;     s=1;  p=x;     for (i=0; i<3; i++)          s*=*(p+i);      cout<

      这样,这样,实参、形参共同指向同一段内存单元实参、形参共同指向同一段内存单元,,内存单元中的数据发生变化,这种变化会反应到主内存单元中的数据发生变化,这种变化会反应到主调函数内调函数内在函数调用时,在函数调用时,形参数组并没有另外开辟新的存储形参数组并没有另外开辟新的存储单元单元,而是以实参数组的首地址作为形参数组的首,而是以实参数组的首地址作为形参数组的首地址这样形参数组的元素值发生了变化也就使实这样形参数组的元素值发生了变化也就使实参数组的元素值发生了变化参数组的元素值发生了变化449 void main(void){  int  array[10];    ......    f(array, 10);    .....}f(int  arr[ ], int n) {        ......}实参数组实参数组形参数组形参数组,必须进行类型说明必须进行类型说明用数组名作形参,因为接收的是地址,用数组名作形参,因为接收的是地址,所以可以不指定具体的元素个数所以可以不指定具体的元素个数1、形参实参都用数组名、形参实参都用数组名450 2028H2024H2020H201CH2014H2010H200CH2008H2004H2000Harray[9]array[8]array[7]array[6]array[5]array[4]array[3]array[2]array[1]array[0]array,arrarr[0]指向同一指向同一存储区间存储区间451 2、实参用数组名,形参用指针变量、实参用数组名,形参用指针变量void main(void){  int  a [10];    ......    f(a, 10);    .....}f(int *x, int n ){        ......}实参数组实参数组形参指针形参指针452 3、形参实参都用指针变量、形参实参都用指针变量void main(void){  int  a [10],,*p;    p=a;    ......    f(p, 10);    .....}f(int *x, int n ) {        ......}实参指针实参指针形参指针形参指针实参指针变量调用前必须赋值实参指针变量调用前必须赋值453 4、实参为指针变量,形参为数组名、实参为指针变量,形参为数组名void main(void){  int  a [10],,*p;    p=a;    ......    f(p, 10);    .....}f(int x[ ], int n ) {        ......}实参指针实参指针形参数组形参数组454 将数组中的将数组中的n个数按相反顺序存放。

      个数按相反顺序存放void  inv(int x[ ], int n){   int  t, i, j, m=(n-1)/2;    for (i=0;i<=m; i++)      {  j=n-1-i;          t=x[i]; x[i]=x[j];  x[j]=t;       }}  void main(void){  int   i, a[10]={3,7,9,11,0,6,7,5,4,2};    inv(a,10);         for (i=0;i<10; i++)       cout<

      写对换,把最大的数与最后一个数对换写3 3个个函数:函数:①①输入输入1010个数;个数;②②进行处理;进行处理;③③输出输出1010个数457 编写函数编写函数 int  fun(int x, int *pp),其功能是,求出其功能是,求出能整除能整除x且不是偶数的各整数,并按照从小到大的且不是偶数的各整数,并按照从小到大的顺序放在顺序放在pp指向的内存中,函数返回值为这些整指向的内存中,函数返回值为这些整数的个数数的个数若若x的值为的值为30,, 数组中的数为数组中的数为1,,3,,5,,15,函数返回,函数返回4458 int fun(int x, int *pp){ int k=0;   for(int i=1;i>x;    n=fun(x,a);    for(int i=0;i

      是小写字符则不必转换)460 void change(char *pchar){  while(*pchar)   {  if(*pchar>='a'&&*pchar<='z') *pchar=*pchar-32;       pchar++;       if(*pchar==0)break;       pchar++;    }}void main(void){  char str[100];    cin.getline(str,100);    change(str);    cout<

      地址这样形参数组的元素值发生了变化也就使实这样形参数组的元素值发生了变化也就使实参数组的元素值发生了变化参数组的元素值发生了变化462 既然数组做形参没有开辟新的内存单元,接受的只既然数组做形参没有开辟新的内存单元,接受的只是实参数组的首地址,那么,这个首地址也可以在是实参数组的首地址,那么,这个首地址也可以在被调函数中用一个被调函数中用一个指针变量指针变量来接受,通过在被调函来接受,通过在被调函数中对这个数中对这个指针变量的指针变量的指向指向进行操作而使实参数组进行操作而使实参数组发生变化发生变化ap实参实参,在主调函在主调函数开辟的空间数开辟的空间形参形参,用指针变用指针变量来接受地址量来接受地址实际上在被调函数中只开辟了实际上在被调函数中只开辟了p的空间,里面放的是的空间,里面放的是a的值463 四、指向多维数组的指针和指针变量四、指向多维数组的指针和指针变量用指针变量也可以指向多维数组,表示的同样是多维数组用指针变量也可以指向多维数组,表示的同样是多维数组的首地址的首地址int  a[3][4];  //首地址为首地址为2000H  a[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000Haa[2]a[1]a[0]2000H2010H2020H可以将可以将a数组看作一个一维数组,这个一维数组的数组看作一个一维数组,这个一维数组的每个元素每个元素又是一个具有又是一个具有4个个int型数据的一维数组型数据的一维数组,这样,,这样,我们就可我们就可以利用一维数组的概念来以利用一维数组的概念来标记标记一些写法。

      一些写法a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1] a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]2000H2008H2010H 2014H201cH 2020H2028H 202cH464 a[0]=*(a+0)a+0为为a[0]的地址的地址&a[0],其值为,其值为2000Ha[1]=*(a+1)a+1为为a[1]的地址的地址&a[1],其值为,其值为2010Ha[2]=*(a+2)a+2为为a[2]的地址的地址&a[2],其值为,其值为2020Ha[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000Haa[2]a[1]a[0]2000H2010H2020H    a[0]为一维数组名为一维数组名,其数组有四个,其数组有四个int型的元素:型的元素:    a[0][0],,a[0][1],,a[0][2],,a[0][3]同样,同样,a[0]代表一维数组的首地址,所以,代表一维数组的首地址,所以,a[0]为为&a[0][0]。

      465 a[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000H2020H2010H2000Haa[2]a[1]a[0]a[0]代表一维数组的首地址代表一维数组的首地址,也就是也就是一维数组名一维数组名,a[0]为为&a[0][0]a[0]为为&a[0][0]a[0][0]=*(a[0]+0)b[0] = *(b+0)a[0]+1为为&a[0][1]a[0][1]=*(a[0]+1)b[1] = *(b+1)a[0]+2为为&a[0][2]a[0][2]=*(a[0]+2)b[2] = *(b+2)a[0]+3为为&a[0][3]a[0][3]=*(a[0]+3)b[3] = *(b+3)a[1]+2为为&a[1][2]a[1][2]=*(a[1]+2)行行列列把把a[0]看成看成一维数组一维数组ba[i][j]=*(a[i]+j)466 a为二维数组名为二维数组名,,a+1为为a[1]的的地址地址,也就是数组第,也就是数组第一行的地址,所以一行的地址,所以a为为行指针行指针。

      a[1]为一维数组名为一维数组名,,a[1]+1为为a[1][1]的的地址地址,也就是,也就是数组第一行第一列的地址,所以数组第一行第一列的地址,所以a[1]为为列指针列指针a[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000H2020H2010H2000Haa[2]a[1]a[0]a[1]+2为为&a[1][2]a[1][2]=*(a[1]+2)行行列列a[i][j]=*(a[i]+j)467 可以看到:可以看到:a,  a+0 ,  *(a+0), a[0], &a[0][0]表示的都表示的都是是2000H,即二维数组的首地址即二维数组的首地址   实际上,实际上,a[0], a[1], a[2]并不是并不是实际的元素实际的元素,它们在,它们在内存内存并不占具体的存储单元并不占具体的存储单元,只是为了我们表示方,只是为了我们表示方便起见而设计出的一种表示方式便起见而设计出的一种表示方式a为行指针,加为行指针,加1移动一行移动一行a或或a[0]为列指针,加为列指针,加1移动一列。

      移动一列a[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000H2020H2010H2000Haa[2]a[1]a[0]468 a[1]=*(a+1)*(a+1)+2=&a[1][2]*(*(a+1)+2)=a[1][2]**(a+1)=*(a[1])=*(*(a+1)+0)=a[1][0](*(a+1))[1]=*(*(a+1)+1)=a[1][1]*(a+1)[1]=*((a+1)[1])=*(*((a+1)+1))=**(a+2)=a[2][0]注意二维数组的各种表示法,注意二维数组的各种表示法,a为常量a[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000H2020H2010H2000Haa[2]a[1]a[0]469 int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};设数组的首地址为设数组的首地址为1900H,则:,则:          a为为_____________         *a为为______________     a+2为为_____________       *a+2为为______________*(a+1)+2为为_____________    **a为为_______________ *(*a+9)为为_____________  (a+1)[1]为为_____________ 1908H1900H1920H1900H1918H1191920Ha[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]190CH1908H1904H1900H1920H1910H1900Haa[2]a[1]a[0]470 void main(void){  static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};    int  *p;    for(p=a[0]; p

      是个常数为第二维的维数是个常数p+2p+4472 fun(int *q1, int *q2, int *q3){ *q3=*q2+*q1;  }void main ( void){  int i , j, a[3][3]={1,1},*p1,*p2,*p3;p1=a[0], p2=a[0]+1,p3=a[0]+2;for(i=2;i<9;i++)  fun(p1++, p2++, p3++);for(i=0;i<3; i++)  for(j=0;j<3;j++) {  cout<

      这样,这样,a与与p等同等同a[2][3]  *(*(a+2)+3)   p[2][3]      *(*(p+2)+3)    ap==a两种表示两种表示完全等价完全等价a为常量为常量p为变量为变量475 若有以下的定义和语句,则下面各个符号的若有以下的定义和语句,则下面各个符号的正确含义是:正确含义是:int a[3][4] ,  (*p)[4];p=a;1.p+12.*(p+2)   3.*(p+1)+24.*(*p+2)  a[2][3]a[2][2]a[2][1]a[2][0]a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]200CH2008H2004H2000Hpp+1p+2aa数组第一行元素的首地址数组第一行元素的首地址为行指针为行指针a数组第二行元素的首地址数组第二行元素的首地址为列指针为列指针&a[2][0]&a[1][2]为列指针为列指针数据元素数据元素*(*(p+0)+2)=a[0][2]476 若若有有以以下下的的定定义义和和语语句句,,则则对对a数数组组元元素素的的非非法引用是:法引用是:int  a[2][3],  (*pt)[3];pt=a;1)pt[0][0]          2)  *(pt+1)[2]2)3) *(pt[1]+2)     3)  *(a[0]+2)*(pt+1)[2]  右右结结合合性性==*((pt+1)[2])==*(*(pt+1+2))==*(*(pt+3))=pt[3][0]477 多维数组的指针作函数参数多维数组的指针作函数参数主要注意的是函数的主要注意的是函数的实参实参究竟是行指针还是究竟是行指针还是列指针,从而决定函数列指针,从而决定函数形参形参的类型。

      的类型要求要求实实参、形参一一对应,类型一致参、形参一一对应,类型一致举例)478 求二维数组求二维数组a[3][4]的平均值的平均值void  main(void){     float score[3][4] = { {65,67,70 ,60}, {80,87,90,81},             {90,99,100,98} };      float sum=0;     for(int i=0;i<3;i++)          for(int  j=0;j<4;j++)                sum=sum+score[i][j];   cout<<“aver=“<

      为数组名,代表数组的首地址,是常量数组首地址数组首地址481 char  string[20];string=“I love China”;strcpy(string, “I love China”);cin.getline(string);  //从键盘输入从键盘输入\0anihCevolI  string错误!常量不错误!常量不能赋值能赋值正确赋值形式正确赋值形式482 2、用字符、用字符指针指针表示字符串表示字符串void main(void){  char *string=“I love China”;    cout<

      void main(void){  char  a[ ]=“I am a  boy”,   b[20];    int  i;    for(i=0;  *(a+i)!=‘\0’; i++)        *(b+i)=*(a+i);     *(b+i)=‘\0’;    cout<

      void main(void){  char s[81], cr, *pi, *pj;   int i, j, n;   cin.getline(s);    n=strlen(s);   pi=________; pj=________;//pi指向串开始,指向串开始,pj指向最后指向最后   while(*pi==‘  ‘) _________;   while(*pj==‘ ‘) ________;  while( ( ___________) &&(*pi==*pj) )               {  pi++;  _______; }   if((pi

      被调函数中可以改变原字符串的内容489 将字符串将字符串a复制到字符串复制到字符串bvoid main(void){  char  a[ ]={“I am a teacher”};    char  b[ ]={“You are a student”};    copy_string(a , b);    cout<

      小字符指针变量是变量字符指针变量是变量,里面存储的是字符型地址,,里面存储的是字符型地址,可以整体赋值,可以整体赋值,但字符串必须以但字符串必须以‘\0’结尾结尾492 void main(void){  char  str[80]= “hcance”;    fun(str);    cout<0)  swap(s1,s2);    if(strcmp(s2,s3)>0)  swap(s2,s3);    if(strcmp(s1,s2)>0)  swap(s1,s2);   cout<

      写一函数,将此字符个字符写一函数,将此字符串中从第串中从第m m个字符开始的全部字符复制成为另一个个字符开始的全部字符复制成为另一个字符串void main(void){   char str1[100]={“I am a student”},str2[100];    int m;   cin>>m;   fun(str1,str2,m);   cout<

      函数在编译时被分配给一个入口地址函数在编译时被分配给一个入口地址这个入口地这个入口地址就称为函数的地址,也是址就称为函数的地址,也是函数的指针函数的指针像数组一像数组一样,样,C++语言规定,语言规定,函数名就代表函数的入口地址函数名就代表函数的入口地址一个存放一个存放地址地址的指针变量空间可以存放的指针变量空间可以存放数据数据的地址的地址(整型、字符型),也可以存放(整型、字符型),也可以存放数组、字符串数组、字符串的地的地址,还可以存放址,还可以存放函数函数的地址497 p=max;直接用函数名为指针变量赋值直接用函数名为指针变量赋值int  max (int  x, int  y){  return  x>y?x:y;}这时,指针变量这时,指针变量p中放的是中放的是max函数在内存中的入口地址函数在内存中的入口地址函数类型函数类型     (*指针变量名指针变量名)(参数类型参数类型 );int   (*p)( int, int);专门存放函数地址的专门存放函数地址的指针变量指针变量称为称为指向函数的指针指向函数的指针变量变量p空间的内容只能空间的内容只能放函数的地址放函数的地址且该函数的返回值为整型数且该函数的返回值为整型数同时该函数具有两个整型形参同时该函数具有两个整型形参498 函数名函数名max代表函数在内存中的入口地址,代表函数在内存中的入口地址,是一个是一个常量常量,不可被赋值。

      不可被赋值而指向函数的指针变量而指向函数的指针变量 p 可以先后指向不同的可以先后指向不同的同种同种类型类型的函数但不可作加减运算但不可作加减运算p=max;p=min;int   (*p)( int , int);定义定义赋值赋值499 如何用指向函数的指针变量调用函数?如何用指向函数的指针变量调用函数?int  max(int x,  int  y){  return  x>y?x:y; }void main(void){  int  a, b, c;    cin>>a>>b;    c=max(a,b);  cout<y?x:y; }void main(void){  int  a, b, c,,max(int,int);    int  (*p)(int, int );    p=max ;    cin>>a>>b;    c=p(a,b);  cout<

      用二分法求方程的解f1(x)=x2-3指向函数的指针变量作指向函数的指针变量作函数参数函数参数(实现通用函数)(实现通用函数)501 二分法求解方程二分法求解方程f(x)xyx01、在、在x轴上取两点轴上取两点x1和和x2, 要确保要确保x1与与x2之间有且只有方程之间有且只有方程唯一的解唯一的解x1x2x02、做、做x0=(x1+x2)/23、若、若|f(x0)|满足给定的精度,则满足给定的精度,则x0即是方程的解,否则,即是方程的解,否则,若若f(x0)*f(x1)<0,则,则方程的解应在方程的解应在x1与与x0之间,令之间,令x2=x0,,继续做继续做2同理,若同理,若f(x0)*f(x1)>0,则,则方程的解应在方程的解应在x2与与x0之间,令之间,令x1=x0,,继续做继续做2 ,直至满足精度为止直至满足精度为止x2x0x2= x0x0=(x1+x2)/2502 用二分法求方程的解用二分法求方程的解f1(x)=x2-3void main(void){  float  x1, x2, x0;   do  {   cout<<“Input two real number\n”;         cin>>x1>>x2;    }while (f1(x1)*f1(x2)>0);float  f1(float x){return  x*x-3;}do  {   x0=(x1+x2)/2;              if  ( (f1(x1)*f1(x0)) <0 )            x2=x0;       else   x1=x0;   }while (fabs (f1(x0))>=1e-6);cout<>x1>>x2;    }while (f2(x1)*f2(x2)>0);float  f2(float x){return  3*x*x-5*x-3;}do  {   x0=(x1+x2)/2;              if  ( (f2(x1)*f2(x0)) <0 )            x2=x0;       else   x1=x0;   }while (fabs (f2(x0))>=1e-6);cout<

      通用可以用指向函数的指针变量,设计相同算法的可以用指向函数的指针变量,设计相同算法的通用函数通用函数504 float devide(float (*fun)(float )){  float  x1, x2, x0;   do  {    cout<<“Input two number\n”;         cin>>x1>>x2;    }while ( fun(x1) * fun(x2) >0); do  {   x0=(x1+x2)/2;              if  ( fun(x1) * fun(x0) <0 )            x2=x0;       else   x1=x0;   }while (fabs ( fun(x0) )>=1e-6);return   x0;}float  f1(float x){return  x*x-3;}float  f2(float x){return  3*x*x-5*x-3;}main( ){    float y1,y2;    y1=devide(f1);    y2=devide(f2);   cout<

      面积之和S=∑[(上底+下底)上底+下底)*高高/2]= ∑[(f(a+i*h)+f(a+(i+1)*h))*h/2]其中其中  i=0~(n-1)  a+n*h=b任意一份:高:任意一份:高:h上底:上底:f(a+i*h)a+i*h下底:下底:f(a+(i+1)*h)507 S=[ (f(a)+f(b))/2+ ∑f(a+i*h) ]*h    (i=1~(n-1))将上式展开,除将上式展开,除f(a),,f(b)外,每一底边都参与运算两次,所以有:外,每一底边都参与运算两次,所以有:y=(f(a)+f(b))/2;h=(b-a)/n;for(i=1;i

      所以函数的类型为所以函数的类型为指针类型指针类型类型标识符类型标识符     *函数名函数名(参数表参数表)指出返回是什指出返回是什么类型的地址么类型的地址int   *max(x, y)510 void main(void){  int  a, b , *p;    cin>>a>>b;    p=max(&a,&b);    cout<<*p<*y)       pt=x;      else  pt=y;      return  pt;}返回类型是指针返回类型是指针用指针类用指针类型接收型接收ab随机随机p&ax24&bypt&b&b输出:输出:4该指针所指向的空间是在主调该指针所指向的空间是在主调函数中开辟的函数中开辟的511 char  *strc(char  *str1,  char  *str2){   char  *p;     for(p=str1;*p!=‘\0’; p++);     do {*p++=*str2++; }while (*str2!=‘\0’);     *p=‘\0’;      return  (str1);} void main(void){char  s1[80]=“computer”, s2[ ]=“language”, *pt;  pt=strc(s1, s2);  cout<

      也就是说,数组也就是说,指针数组中的每一个元素都是指指针数组中的每一个元素都是指针变量,可以放地址针变量,可以放地址类型标识类型标识   *数组名数组名[数组长度说明数组长度说明]int  *p[4];            int  (*p)[4];            pp[3]p[2]p[1]p[0]地址地址地址地址地址地址地址地址p为数组名,内有四个元为数组名,内有四个元素,每个元素可以放一素,每个元素可以放一个个int型数据的地址型数据的地址            p为指向有四个为指向有四个int型元素的一维数组的行指针型元素的一维数组的行指针            515 void main(void){float a[]={100,200,300,400,500};float  *p[]={&a[0],&a[1],&a[2],&a[3],&a[4]};int i;for(i=0;i<5;i++)cout<<*p[i]<<'\t';cout<

      样比字符数组节省空间char  *str[ ]={“China”, “Japan”, “America”};3090H3000H2000Hstrstr[2]str[1]str[0]“America”“Japan”“China”str[1][4]*(*(str+1)+4)*str[2]*(*(str+2)+0)**str*(*(str+0)+0)nAC518 将若干字符串按字母顺序(由小到大)输出将若干字符串按字母顺序(由小到大)输出void main(void){  void  sort( );   void   print( );    char  *alpha[ ]={“Follow me”, “Basic”, “Great Wall”, “FORTRAN”, “Computer design”};    int  n=5;    sort (alpha,  n);    print(alpha, n);}519 void sort(char  *alpha[ ], int  n){   char  *temp;     int  i, j, k;     for(i=0;i0)                        k=j;           if (k!=i)             { temp=alpha[i];                alpha[i]=alpha[k];                 alpha[k]=temp;              }         }} void print(char  *alpha[ ], int  n){   int  i;     for(i=0;i

      它prt=&p;    p=&iint   i, *p,  **prt;称称prtprt为为指向指针指向指针的指针变量其的指针变量其基类型基类型是指向整是指向整型数据的型数据的指针变量指针变量,而非整型数据而非整型数据521 prt=p;p=&i;prt=&p;prt=&i;*p=i;**prt=i;非法非法,基类基类型不符型不符i2000H2000Hp3000H3000Hprt5000H522 void main(void){ a[5]={1,3,5,7,9};    int  *num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};    int  **p, i;    p=num;    for(i=0;i<5;i++)      {   cout<<**p<<‘\t’;             p++;        }} 97531a&a[4]&a[3]&a[2]&a[1]&a[0]numnumpp=p+1;指向指向num数组下一个元素数组下一个元素13579p=&num[0]523 void main(void){char  *alpha[ ]={“Follow me”, “Basic”, “Great Wall”,                              “FORTRAN”, “Computer design”};     char  **p;     int  i;     for(i=0; i<5; i++)      {   p=alpha+i;           cout<<*p<

      若有以下定义,则下列哪种表示与之等价char  s[3][5]={“aaaa”,”bbbb”,”cccc”};A)char   **s1= {“aaaa”,”bbbb”,”cccc”};B)char  *s2[3]= {“aaaa”,”bbbb”,”cccc”};C)char  s3[ ][3]= {“aaaa”,”bbbb”,”cccc”};D)char  s4[ ][4]= {“aaaa”,”bbbb”,”cccc”};528 以下程序调用函数以下程序调用函数swap_p将指针将指针s和和t所指单元所指单元(a和和b)中的内容交换,中的内容交换,请填空void swap_p (______ss, ______tt){      int  term;        term=_________;         **ss=_________;        **tt=term;}main( ){   int  a=10,  b=20,  *s,*t;     s=&a;  t=&b;     swap_p(&s,&t);     printf(“%d   %d”,a,b);}int **int ****ss **tt10a&as20b&bt&sss&tttterm529 假设有说明:假设有说明:  char *argv[ ]={“hello”, “nanjing”, “jiangsu”};  char **pargv=argv;   以下语句的输出结果如何?以下语句的输出结果如何?  cout<<*(pargv+1)<

      函数处向下执行的main函数也可以带参函数也可以带参数其它函数由其它函数由main函数调用的,即在程序中调用的,函数调用的,即在程序中调用的,但但main函数却是由函数却是由DOS系统调用的系统调用的,,所以所以main函数实参的值是在函数实参的值是在DOS命令行中给出的命令行中给出的,是随着文件的运行命令一起给出的是随着文件的运行命令一起给出的可执行文件名可执行文件名    实参实参1    实参实参2    ......   实参实参nS9_16    CHINA    JAPAN     AMERICAN可执行文件可执行文件S9_16.EXE三个形参三个形参534 main函数形参的形式:函数形参的形式:main(  int argc, char * argv[ ])main( int  argc, char  **argv)argc为命令行中参数的个数(包括文件名);为命令行中参数的个数(包括文件名);argv为指向命令行中参数(字符串)的指针数组为指向命令行中参数(字符串)的指针数组S9_16    CHINA    JAPAN     AMERICAN文件名文件名实参实参1实参实参2实参实参3argc=4argv[3]argv[2]argv[1]argv[0]“AMERICAN”“JAPAN”“CHINA”“S9_16.EXE”argvargv535 main(  int argc,   char *argv[ ]){  while  (argc>1)   {  cout<<*argv<文件名文件名实参实参1实参实参2实参实参3536 B9_1  Beijing    Chinamain(int argc,   char  **argv ){     while (argc-- >1)          cout<< *(++argv)<

      指针变量可以有空值,即指针变量不指向任何地址int  *p;p=0;#include “iostream.h”int  *p;  p=NULL;#define  NULL   02 2、两指针可以相减,、两指针可以相减,不可相加不可相加若要进行相减运算,则两若要进行相减运算,则两指针必须指向同一数组,指针必须指向同一数组,相减结果为相距的数组元素个数相减结果为相距的数组元素个数int   a[10],*p1,*p2;p1=a;   p2=a+9;p2-p1 :   9   3 3、指向、指向同一数组同一数组的两个指针变量可以比较大小:的两个指针变量可以比较大小:p2>p1p2>p1538 在内存动态分配存储空间在内存动态分配存储空间在定义变量或数组的同时即在定义变量或数组的同时即在内存为其开辟了指定在内存为其开辟了指定的固定空间的固定空间int  n,   a[10];char    str[100]; 在程序内我们有时需要根据实际需要开辟空间在程序内我们有时需要根据实际需要开辟空间,如,如输入学生成绩,但每个班的学生人数不同,一般将输入学生成绩,但每个班的学生人数不同,一般将人数定得很大,这样占用内存。

      人数定得很大,这样占用内存一经定义,即为固定地址的一经定义,即为固定地址的空间,在内存不能被别的变空间,在内存不能被别的变量所占用量所占用539 #define   N    100......float    score[N][5];cin>>n;for(int i=0;i>score[i][j];......无论班级中有多少个学无论班级中有多少个学生,程序均在内存中开生,程序均在内存中开辟辟100×5100×5个实型数空间个实型数空间存放学生成绩,造成内存放学生成绩,造成内存空间的浪费存空间的浪费540 如何根据需要在程序的运行过程中如何根据需要在程序的运行过程中动态分配动态分配存储内存空间存储内存空间??int n;cin>>n;float  score[n][5];  错误!错误!数组的维数数组的维数必须是常量必须是常量利用利用  new 运算符可以在程序中动态开辟内存空间运算符可以在程序中动态开辟内存空间new   数据类型数据类型[单位数单位数];new  int[4];在内存中开辟了在内存中开辟了4个个int型的数据空间,即型的数据空间,即16个字节个字节541 new new 相当于一个函数,在内存开辟完空间后,返相当于一个函数,在内存开辟完空间后,返回这个空间的首地址,这时,回这个空间的首地址,这时,这个地址必须用一这个地址必须用一个指针保存下来个指针保存下来,才不会丢失。

      才不会丢失int    *p;pp=new  int;new开辟的空间开辟的空间*p=6;6可以用可以用*p对这个空间进行运算对这个空间进行运算new  int;在内存中开辟出四在内存中开辟出四个字节的空间个字节的空间542 int  n,* p;cin>>n;p=new int[n];p指向新开辟空间的首地址指向新开辟空间的首地址p同样,利用同样,利用new运算符也可以开辟连续的多个空间运算符也可以开辟连续的多个空间(数组数组)for(int i=0;i>p[i];可以用可以用p[i]的形式来引用新开辟的内存单元的形式来引用新开辟的内存单元543 注意:用注意:用newnew开辟的内存单元没有名字,指向其开辟的内存单元没有名字,指向其首地址的首地址的指针指针是引用其的唯一途径,若指针变量重新赋值,则用是引用其的唯一途径,若指针变量重新赋值,则用newnew开辟的内存单元就在内存中开辟的内存单元就在内存中““丢失丢失””了,别的程序也了,别的程序也不能占用这段单元,直到重新开机为止不能占用这段单元,直到重新开机为止int  * p, a[4];p=new int[4];p=a;anew开辟的单元开辟的单元p该段内存由于失去了该段内存由于失去了“名名字字”,再也无法引用,再也无法引用544 用用 new new 运算符分配的空间,运算符分配的空间,不能在分配空间时不能在分配空间时进行初始化进行初始化。

      deletedelete运运算算符符用用来来将将动动态态分分配配到到的的内内存存空空间间归归还还给给系统,使用格式为:系统,使用格式为: delete pdelete p;;同样,用同样,用newnew开辟的内存单元如果程序不开辟的内存单元如果程序不““主动主动””收回,那么这段空间就一直存在,直到重新开机收回,那么这段空间就一直存在,直到重新开机为止545 delete也可以收回用也可以收回用new开辟的连续的空间开辟的连续的空间int  *point;cin>>n;point=new   int[n];.......delete  [ ]point;;int  *point;point=new  int;......delete   point;注意:在此期间,注意:在此期间,point指针不能重指针不能重新赋值,新赋值,只有用只有用new开辟的空间才开辟的空间才能用能用delete收回收回当内存中没有足够的空间给予当内存中没有足够的空间给予分配时,分配时,new 运算符返回空指运算符返回空指针针NULL((0)546 以下程序求两个数的大者,请填空以下程序求两个数的大者,请填空。

      void main(void ){  int  *p1,  *p2;    p1=___________;;    p2=___________;    cin>>_______________;    if (*p2>*p1)    *p1=*p2;     delete  p2;    cout<<“max=”<< _______<>*p2547 main( ){   int  *s1, *s2;     sub1(&s1,&s2);     sub2(&s1,&s2);       cout<<*s1<<‘\t’<<*s2<

      变量的引用<类型类型>   &<引用变量名引用变量名> = <原变量名原变量名>;; 其中其中原变量名原变量名必须是一个已定义过的变量必须是一个已定义过的变量如:int   max ;int  &refmax=max;refmax并没有并没有重新在内存中开辟单元,只是重新在内存中开辟单元,只是引用引用max的单元max与与refmax在内存中占用同一地址在内存中占用同一地址,,即同一地址两个名字即同一地址两个名字549 maxrefmax510int   max ;int  &refmax=max;max=5 ;20refmax=10;refmax=max+refmax;max与与refmax同一地址同一地址550 对引用类型的变量,说明以下几点:对引用类型的变量,说明以下几点:1、引用在定义的时候要初始化引用在定义的时候要初始化2、对引用的操作就是对被引用的变量的操作对引用的操作就是对被引用的变量的操作 int  &refmax; int  &refmax=max;错误,没有具体的引用对象错误,没有具体的引用对象max是已定义过的变量是已定义过的变量3、、 引用类型变量的初始化值不能是一个常数。

      引用类型变量的初始化值不能是一个常数如:如:int  &ref1 = 5;    // 是错误的是错误的int  &ref=i;551 4、引用同变量一样有地址,可以对其地址进行、引用同变量一样有地址,可以对其地址进行操作,即将其地址赋给一指针操作,即将其地址赋给一指针int   a, *p;int  &m=a;apm10p=&m;*p=10;&m&是变量的引用是变量的引用&是变量的地址是变量的地址552 5、可以用动态分配的内存空间来初始化一个引用变量可以用动态分配的内存空间来初始化一个引用变量float  &reff = * new float ; //用用new开辟一个空间,取一个别名开辟一个空间,取一个别名reff reff= 200;//给空间赋值给空间赋值 cout << reff ;//输出输出200 delete &reff; //收回这个空间收回这个空间这个空间只有别名,但程序可以引用到这个空间只有别名,但程序可以引用到float  *p,  a;p=new  float;float  a=* new  float;错误!错误!553 指针与引用的区别:指针与引用的区别:1、指针是通过地址、指针是通过地址间接间接访问某个变量,而引用是访问某个变量,而引用是通过别名通过别名直接直接访问某个变量。

      访问某个变量2、引用必须初始化,而、引用必须初始化,而一旦被初始化后不得再作一旦被初始化后不得再作为其它变量的别名为其它变量的别名554 当当&a&a的前面有的前面有类型符类型符时时(如(如int &aint &a),它必然是),它必然是对引用的声明对引用的声明;如果前面;如果前面无类型符(如无类型符(如cout<<&acout<<&a)), ,则是取变量的地址则是取变量的地址 555 以下的声明是非法的以下的声明是非法的1、企图建立数组的引用、企图建立数组的引用            int & a[9];2、企图建立指向引用的指针、企图建立指向引用的指针    int & *p;3、企图建立引用的引用、企图建立引用的引用            int & &px;int  m=10;int  &y=10;int   &z;float  &t=&m;int  &x=m;556 void main(void){const int &r=8; //说明说明r为常量,不可赋值为常量,不可赋值cout<<"r="<

      函数的返回值引用作函数的形参,实际上是在被调函数中对引用作函数的形参,实际上是在被调函数中对实参变量实参变量进行操作进行操作void  change(int &x,  int &y)//x,y是实参是实参a,b的别名的别名{   int   t;     t=x;  x=y;   y=z;}void main(void){   int  a=3,b=5;    change(a,b);  //实参为变量实参为变量   cout<

      这了一个变量,所以可对其返回值进行赋值操作这一点类同于函数的返回值为指针类型一点类同于函数的返回值为指针类型 562 先调用,再赋值先调用,再赋值  int  a=4;int  &f(int  x){    a=a+x;      return  a;}void main(void){    int   t=5;     cout<

      返回的变量的引用,返回的变量的引用,这个变量必须是全局变量或静这个变量必须是全局变量或静态局部变量,即存储在静态区中的变量态局部变量,即存储在静态区中的变量       564 我们都知道,函数作为一种程序实体,它有我们都知道,函数作为一种程序实体,它有名字、类型、地址和存储空间,一般说来名字、类型、地址和存储空间,一般说来函函数不能作为左值数不能作为左值(即函数不能放在赋值号左(即函数不能放在赋值号左边)但如果将函数定义为返回引用类型,边)但如果将函数定义为返回引用类型,因为返回的是一个变量的别名,就可以将函因为返回的是一个变量的别名,就可以将函数放在左边,即给这个变量赋值数放在左边,即给这个变量赋值565 int  &f(int  &x){    static  int  t=2;     t=x++;     return   t;}void main(void){   int  a=3;     cout<

      可分为const型常量和const型指针 可用const限制定义标识符量,如:const  int MaxLine =1000;const  float  Pi=3.1415926 用const定义的标识符常量时,一定要对其初始化在说明时进行初始化是对这种常量置值的唯一方法 ,不能用赋值运算符对这种常量进行赋值如:MaxLine =35; 567 const 型指针1)禁写指针声明语句格式为:     数据类型    *  const   指针变量名如:int  r=6;         int * const  pr=&r;则指针pr被禁写,即pr将始终指向一个地址,成为一个指针常量它将不能再作为左值而放在赋值号的左边举例说明)虽然指针被禁写,但其间接引用并没有被禁写即可以通过pr对r赋值pr=8;同样,禁写指针一定要在定义的时候赋初值568 void main(void){    int  a,b;    int  *const  pa=&a;  //一定要赋初值,pa是常量,不能在程序中//被改变   *pa=10;//可以间接引用    pa=&b;//非法,pa为常量}ab&apa10569 2)禁写间接引用声明语句格式如下:             const  数据类型   *指针变量名;所声明的指针指向一禁写的实体,即间接引用不能被改写。

      如:  const  int  *p;所以程序中不能出现诸如  *p=  的语句,但指针p并未被禁写,因而可对指针p进行改写570 void main(void){        int  a=3,b=5;        const  int  *pa=&b;//可以不赋初值        pa=&a;//指针变量可以重新赋值        cout<<*pa<

      的变量,各个结点的类型相同,但其地址不一定连续具具体结点的个数根据需要动态开辟体结点的个数根据需要动态开辟每个结点由两部分组成,每个结点由两部分组成,第一部分放若干数据第一部分放若干数据,,第二部分第二部分是指针变量,放下一结点的地址是指针变量,放下一结点的地址链表头是一指针变量,链表头是一指针变量,放第一个结点的地址,若结点的第二部分的值为放第一个结点的地址,若结点的第二部分的值为NULLNULL,表,表示此链表结束示此链表结束573 二、如何处理链表二、如何处理链表struct  student{   int  num;     float  score;     struct  student  *next;} ;#define   STU  struct  studentSTU{   int  num;     float  score;     STU   *next;} ;链表结点的结构:链表结点的结构:指向同一结构体指向同一结构体类型的指针变量类型的指针变量指向同一结构体类指向同一结构体类型的指针变量型的指针变量1、建立链表、建立链表574 struct  student{   int  num;     float  score;     struct  student  *next;} ;struct student  *p;  //定义了结构体类型的指针定义了结构体类型的指针p=new student;  //用用new开辟一结构体空间,将地址赋给开辟一结构体空间,将地址赋给pp->num=10;   //为新开辟的结构体空间中的为新开辟的结构体空间中的num成员赋值成员赋值p->score=90;nextscorenump1090 用指针引用结用指针引用结构体内的成员构体内的成员(*p).num575 1、首先定义两个结构体类型的指针、首先定义两个结构体类型的指针   STU   *p1, *p2;2、用、用new在内存中开辟一个结构体变量的空间,将地址赋给在内存中开辟一个结构体变量的空间,将地址赋给p1。

      p1=new student; /*  STU  struct  student    */3、将数据赋给刚开辟的变量空间将数据赋给刚开辟的变量空间cin>>p1->num>>p1->score;4、若输入的数据有效,将首地址作为链表头,、若输入的数据有效,将首地址作为链表头,head=p1; 令令p2=p1,,p1继续用继续用new开辟新的开辟新的内存空间内存空间5、将下一个数据赋给新开辟的变量空间将下一个数据赋给新开辟的变量空间p1=new student; /*  STU  struct  student    */cin>>p1->num>>p1->score;6、若输入的数据有效,将、若输入的数据有效,将p2与与p1连接起来连接起来,,p2->next=p1  再令再令p2=p1,,p1继续用继续用new开辟开辟新的内存空间做新的内存空间若输入的数据无效,若输入的数据无效,p2就是链表的尾,则就是链表的尾,则p2->next=NULLheadp2A2000Hp13000HBp13000Hp22090HCp12090Hp26000HDp1‘\0’ABC576 headp2A2000Hp13000HBp13000Hp22090HCp12090Hp26000HDp1‘\0’ABC577 STU    *p1, *p2,  *head;head=NULL;p1=p2=new student;cin>>p1->num>>p1->score;if (p1->num!=0)     head=p1;p1=new student;cin>>p1->num>>p1->score;if (p1->num!=0){ p2->next=p1;   p2=p1;}p1=new student;cin>>p1->num>>p1->score;if (p1->num!=0){   p2->next=p1;     p2=p1;    }p1=new student;cin>>p1->num>>p1->score;if (p1->num= =0)       p2->next=NULL;return (head);第一结点第一结点第二结点第二结点第三结点第三结点最后结点最后结点返回链表头返回链表头578 STU  *creat( ){  STU  *head, *p1,*p2;    n=0;    head=NULL;    p1=p2=new student;    cin>>p1->num>>p1->score;    while (p1->num!=0)     {     n=n+1;            if  (n= =1)   head=p1;            else              p2->next=p1;             p2=p1;             p1=new student;             cin>>p1->num>>p1->score;       }     p2->next=NULL;     return(head);} n为全局变量,表示结点数为全局变量,表示结点数开辟新结点开辟新结点向新结点输入数据向新结点输入数据不满足输入条件,结束不满足输入条件,结束579 2、输出链表、输出链表void print(STU  * head){  STU   *p;    p=head;    while(p!=NULL)    {  cout<num<<‘\t’<score<<‘\n’;        p=p->next;     }}     A3000H2000H3000HB3050H3050HC6000H6000HD2090H2090HB‘\0’head输出数据输出数据p指向下一结点指向下一结点580 3、删除链表、删除链表A3000H2000H3000HB6000H6000HD2090H2090HB‘\0’head1、首先定义两个结构体类型的指针、首先定义两个结构体类型的指针   STU   *p1, *p2;2、将链表的表头赋给、将链表的表头赋给p1,  p1=head;3、判断、判断p1所指向的结点是否是要删除的结点所指向的结点是否是要删除的结点   p1->num     a1。

      4、若、若p1->num!=a1, p2=p1; p1指向下一个结点指向下一个结点p1=p1->next,继续判断继续判断下一个结点是否是要删除的结点继续做下一个结点是否是要删除的结点继续做35、若、若p1->num= =a1,,则则p1当前指向的结点就是要删除的结点,将当前指向的结点就是要删除的结点,将p2的指针成员指向的指针成员指向p1所指的下一个结点所指的下一个结点p2->next=p1->next;这样就删除了一个结点这样就删除了一个结点p2p1p1p1p22090H581 特殊情况:特殊情况:1 1、若链表为空链表,返回空指针若链表为空链表,返回空指针2 2、删除的结点为头结点时,、删除的结点为头结点时,headhead指向下一个结点指向下一个结点3 3、链表内没有要删除的结点,返回提示信息链表内没有要删除的结点,返回提示信息582 struct  student  *del(struct  student  * head, int num){   struct  student  *p1,*p2;     if (head= =NULL)     {  cout<<“list null\n”;  return  NULL;}     p1=head;     while (num!=p1->num&&p1->next!=NULL)        {   p2=p1;  p1=p1->next;   }      if(num= =p1->num)      {    if (num= =head->num)   head=p1->next;            else  p2->next=p1->next;            n=n-1;        }       else  cout<<“Not  found\n”;       return  head;}链表为空链表为空未找到结点,循环未找到结点,循环结点为第一个结点为第一个循环结束,没有要找的结点循环结束,没有要找的结点找到结点找到结点583 4、插入结点:要插入结点的链表是排序的链表。

      插入、插入结点:要插入结点的链表是排序的链表插入1033000H2000H3000H76000H6000H122090H2090H28‘\0’head1、定义三个结构体指针变量、定义三个结构体指针变量   STU  *p1,*p2,*p0;  p0指向要插入的结指向要插入的结点p1=head;107000Hp0p12、比较、比较p1->num 与与p0->num,,若若p1->numnum,,p2=p1; p1=p1->next;    继续比较继续比较3、若、若p1->num> =p0->num,,p0应插在应插在p1与与p2之间,则之间,则p2->next=p0 ;          p0->next=p1;p2p1p17000H6000Hp2584 特殊情况:特殊情况:1、若链表为空链表,将插入结点作为唯一的结点,、若链表为空链表,将插入结点作为唯一的结点,head=p0;返回2、若插入结点中的数据最小,则插入的结点作为、若插入结点中的数据最小,则插入的结点作为头结点3、插入到链尾,插入结点为最后一个结点插入到链尾,插入结点为最后一个结点p2->next=p0;p0->next=NULL;p0->next=head;  head=p0; 585 STU  *insert(STU  * head, STU  * stud){   STU  *p0,*p1,*p2;     p1=head;    p0=stud;     if (head= =NULL)           {   head=p0;  p0->next=NULL;}     else          while((p0->num>p1->num)&&(p1->next!=NULL))                     {   p2=p1;  p1=p1->next;  }           if (p0->num<=p1->num)              {     if (head= =p1)  head=p0;                    else              p2->next=p0;                     p0->next=p1;                 }           else  {p1->next=p0;  p0->next=NULL;}        n=n+1;          return (head);    }链表为空链表为空未找到结点,循环未找到结点,循环找到结点找到结点插入在第一个结点前插入在第一个结点前插入在最插入在最后一个后后一个后586 void main(void){  STU  *head,  stu;    int  del_num;    head=creat( );    print(head);    cout<<“Input the deleted number:\n”;    cin>>del_num;    head=del(head,del_num);        print(head);      cout<<“Input the inserted record:\n”;    cin>>stu.num>>stu.score;    head=insert(head, &stu);    print(head);}建立链表建立链表打印链表打印链表删除结点删除结点插入结点插入结点cout<<“Input the inserted record:\n”;     cin>>stu.num>>stu.score;    head=insert(head, &stu);    print(head);变量,固定空间变量,固定空间587 33000H2000H3000H76000H6000H122090H2090H28‘\0’head107000Hstu70006000H588 void main(void){  STU  *head,*stu;    int  num;     ......    cout<<“Input the inserted record:\n”;    stu=new student;    cin>>stu->num>>stu->score;    while (stu->num!=0)         {       head=insert(head, stu);              print(head);              cout<<“Input the inserted record:\n”;    stu=new student;  cin>>stu->num>>stu->score;       }}  如果要插入结点,动态开辟新结点如果要插入结点,动态开辟新结点指针,可以赋值指针,可以赋值重新开辟空间重新开辟空间589 用用typedef定义类型定义类型typedef定义新的类型来代替已有的类型。

      定义新的类型来代替已有的类型typedef     已定义的类型已定义的类型     新的类型新的类型typedef     float    REALREAL    x, y;1、、typedef可以定义类型,但不能定义变量可以定义类型,但不能定义变量2、、tyoedef只能对已经存在的类型名重新定义一个类型名,只能对已经存在的类型名重新定义一个类型名,而不能创建一个新的类型名而不能创建一个新的类型名typedef   struct  student  {   int  i;     int  *p;}    REC;REC   x, y,  *pt;struct  student   x, y,  *pt;float    x, y;590 typedef   char  *CHARP;CHARP    p1,p2;char   *p1,  *p2;typedef  char  STRING[81];STRING   s1, s2, s3;char   s1[81], s2[81],s3[81];1、先按定义变量的方法写出定义体、先按定义变量的方法写出定义体char   s[81];2、把变量名换成新类型名、把变量名换成新类型名char   STRING[81];3、在前面加、在前面加typedeftypedef     char   STRING[81];4、再用新类型名定义变量、再用新类型名定义变量STRING    s;;#define   REAL   float   编译前简单替换编译前简单替换typedef::编译时处理,定义一个类型替代原有的类型。

      编译时处理,定义一个类型替代原有的类型591 第九章第九章         类和对象类和对象 面向对象的程序设计面向对象的程序设计592 按钮对象:按钮对象:按钮的内容、大小,按钮的字体、图案等等按钮的内容、大小,按钮的字体、图案等等针对按钮的各种操作,创建、单击、双击、拖动等针对按钮的各种操作,创建、单击、双击、拖动等班级对象:班级对象:班级的静态特征,所属的系和专业、班级的人数,班级的静态特征,所属的系和专业、班级的人数,所在的教室等这种静态特征称为属性;所在的教室等这种静态特征称为属性;班级的动态特征,如学习、开会、体育比赛等,班级的动态特征,如学习、开会、体育比赛等,这种动态特征称为行为这种动态特征称为行为 593 任何一个对象都应当具有这两个要素,一是属性任何一个对象都应当具有这两个要素,一是属性(attribute);二是行为;二是行为(behavior),即能根据外,即能根据外界给的信息进行相应的操作界给的信息进行相应的操作对象是由一组属性和对象是由一组属性和一组行为构成的一组行为构成的 面向对象的程序设计采用了以上人们所熟悉的这种面向对象的程序设计采用了以上人们所熟悉的这种思路。

      使用面向对象的程序设计方法设计一个复杂思路使用面向对象的程序设计方法设计一个复杂的软件系统时,的软件系统时,首要的问题是确定该系统是由哪些首要的问题是确定该系统是由哪些对象组成的,并且设计这些对象在对象组成的,并且设计这些对象在C++中,中,每个每个对象都是由数据和函数对象都是由数据和函数(即操作代码即操作代码)这两部分组成这两部分组成的 594 我们可以对一个对象进行封装处理,把它的我们可以对一个对象进行封装处理,把它的一部分属性和功能对外界屏蔽,也就是说从一部分属性和功能对外界屏蔽,也就是说从外界是看不到的、甚至是不可知的外界是看不到的、甚至是不可知的 使用对象的人完全可以不必知道对象内部的使用对象的人完全可以不必知道对象内部的具体细节,只需了解其外部功能即可自如地具体细节,只需了解其外部功能即可自如地操作对象操作对象 把对象的内部实现和外部行为分隔开来把对象的内部实现和外部行为分隔开来 595 传统的面向过程程序设计是围绕功能进行的,用一传统的面向过程程序设计是围绕功能进行的,用一个函数实现一个功能个函数实现一个功能所有的数据都是公用的所有的数据都是公用的,一,一个函数可以使用任何一组数据,而一组数据又能被个函数可以使用任何一组数据,而一组数据又能被多个函数所使用。

      程序设计者必须考虑每一个细节,多个函数所使用程序设计者必须考虑每一个细节,什么时候对什么数据进行操作什么时候对什么数据进行操作 面向对象程序设计采取的是另外一种思路它面对面向对象程序设计采取的是另外一种思路它面对的是一个个对象实际上,每一组数据都是有特定的是一个个对象实际上,每一组数据都是有特定的用途的,是某种操作的对象也就是说,的用途的,是某种操作的对象也就是说,一组操一组操作调用一组数据作调用一组数据 596 程序设计者的任务包括两个方面:一是程序设计者的任务包括两个方面:一是设计所需的各种类和对象,即决定把哪些数设计所需的各种类和对象,即决定把哪些数据和操作封装在一起;二是考虑怎样向有关据和操作封装在一起;二是考虑怎样向有关对象发送消息,以完成所需的任务对象发送消息,以完成所需的任务各个对各个对象的操作完成了,整体任务也就完成了象的操作完成了,整体任务也就完成了 因此人们设想把相关的数据和操作放在因此人们设想把相关的数据和操作放在一起,形成一个整体,与外界相对分隔一起,形成一个整体,与外界相对分隔这就是面向对象的程序设计中的对象就是面向对象的程序设计中的对象 597 程序程序= =算法+数据结构算法+数据结构在面向过程的结构化程序设计中,人们常使在面向过程的结构化程序设计中,人们常使用这样的公式来表述程序用这样的公式来表述程序∶∶ 598 对象对象 = = 算法算法 ++ 数据结构数据结构程序程序=(=(对象对象+ +对象对象+ +对象对象+……)+ +……)+ 消息消息 消息的作用就是对对象的控制。

      消息的作用就是对对象的控制程序设计的关键是设计好每一个对象以及确程序设计的关键是设计好每一个对象以及确定向这些对象发出的命令,使各对象完成相定向这些对象发出的命令,使各对象完成相应的操作应的操作 面向对象的程序组成:面向对象的程序组成:599 每一个实体都是对象有一些对象是具有相每一个实体都是对象有一些对象是具有相同的结构和特性的同的结构和特性的 每个对象都属于一个特定的类型每个对象都属于一个特定的类型 在在C++C++中对象的类型称为类中对象的类型称为类(class)(class)类代表类代表了某一批对象的共性和特征了某一批对象的共性和特征类是对象的抽类是对象的抽象,而对象是类的具体实例象,而对象是类的具体实例(instance)(instance) 600 类是一种复杂的数据类是一种复杂的数据类型类型,它是将,它是将不同类型不同类型的数据的数据和和与这些数据相关的运算与这些数据相关的运算封装在一起封装在一起的的 集合体类的定义类的定义类将一些数据及与数据相关的类将一些数据及与数据相关的函数函数封装在一封装在一起,使类中的数据得到很好的起,使类中的数据得到很好的“保护保护”在大型程序中不会被随意修改。

      大型程序中不会被随意修改601 类的定义格式:类的定义格式:class  类名类名{    private :            成员数据成员数据;成员函数;成员函数;     public :            成员数据成员数据;成员函数;成员函数;    protected:成员数据成员数据;成员函数;成员函数;};关键字关键字类名类名私有私有公有公有保护保护class  Student{ private :     char Name[20];     float Math;     float Chiese;  public :     float  average;     void SetName(char *name);     void  SetMath(float math);     void  SetChinese(float ch);     float GetAverage(void);};分号不能少分号不能少602 用关键字用关键字priviate限定的成员称为限定的成员称为私有成员私有成员,,对私有成员对私有成员限定在该类的内部使用限定在该类的内部使用,即,即只只允许该类中的成员函数使用私有的成员数允许该类中的成员函数使用私有的成员数据据,对于私有的成员函数,只能被,对于私有的成员函数,只能被该类内该类内的成员函数调用的成员函数调用;类就相当于私有成员的;类就相当于私有成员的作用域。

      作用域 603 用关键字用关键字public限定的成员称为限定的成员称为公有成员公有成员,,公有成员的数据或函数不受类的限制,公有成员的数据或函数不受类的限制,可以可以在类内或类外自由使用在类内或类外自由使用;对类而言是透明的对类而言是透明的604 而用关键字而用关键字protected所限定的成员称为所限定的成员称为保护保护成员成员,只允许在类内及该类的派生类中使用,只允许在类内及该类的派生类中使用保护的数据或函数即保护成员的作用域是保护的数据或函数即保护成员的作用域是该类及该类的派生类该类及该类的派生类605 私有成员私有成员 公有成员公有成员 保护成员保护成员类内函数类内函数 可以调用可以调用 可以调用可以调用 可以调用可以调用类外函数类外函数 不可调用不可调用 可以调用可以调用 不可调用不可调用私有函数私有函数 公有函数公有函数 保护函数保护函数类内函数类内函数 可以调用可以调用 可以调用可以调用 可以调用可以调用类外函数类外函数 不可调用不可调用 可以调用可以调用 不可调用不可调用606 每一个限制词每一个限制词(private等等)在类体中可使用多在类体中可使用多次一旦使用了限制词,该限制词一直有效,次。

      一旦使用了限制词,该限制词一直有效,直到下一个限制词开始为止直到下一个限制词开始为止如果未加说明,类中成员默认的访问权限是如果未加说明,类中成员默认的访问权限是private,即私有的即私有的607 class  Student{char Name[20];float Math;float Chiese;     public :float  average;          void SetName(char *name);void  SetMath(float math);void  SetChinese(float ch);    float GetAverage(void);};均为私有权限均为私有权限均为公有权限均为公有权限608 class  A{     float  x, y;  public:      void Setxy(float a,float  b)     {  x=a;   y=b;   }      void  Print(void)    {   cout<

      609 成员函数与成员数据的定义不分先后,可以先说明成员函数与成员数据的定义不分先后,可以先说明函数原型函数原型,再在类体外定义函数体再在类体外定义函数体class  A{       float  x, y;  public:      void Setxy(float a,float  b)     {  x=a;   y=b;   }      void  Print(void)     {   cout<   < class_name > :: < func_name > (<参数表参数表>){......  //函数体函数体}在类体外定义成员函数的格式:在类体外定义成员函数的格式:void    A::Setxy(float a,float  b)     {  x=a;   y=b;   }函数类型函数类型类名类名函数名函数名形参列表形参列表函数体函数体612 在定义一个类时,要注意如下几点:在定义一个类时,要注意如下几点:1、、类类具具有有封封装装性性,,并并且且类类只只是是定定义义了了一一种种结结构构((样样板板)),,所所以以类类中中的的任任何何成成员员数数据据均均不不能能使使用用关关键键字字extern,,auto或或register限定其存储类型限定其存储类型。

      2、、在在定定义义类类时时,,只只是是定定义义了了一一种种导导出出的的数数据据类类型型,,并并不不为为类类分分配配存存储储空空间间,,所所以以,,在在定定义义类类中中的的数数据据成成员员时时,,不能对其初始化不能对其初始化如:class  Test {  int  x=5,y=6;   //是不允许的是不允许的  extern  float  x;  //是不允许的是不允许的  }613 在在C++语言中,语言中,结构体类型结构体类型只是类的一个特只是类的一个特例结构体类型与类的唯一的区别在于:例结构体类型与类的唯一的区别在于:在在类中,其成员的缺省的存取权限是私有的;类中,其成员的缺省的存取权限是私有的;而在结构体类型中,其成员的缺省的存取权而在结构体类型中,其成员的缺省的存取权限是公有的限是公有的 614  内联成员函数内联成员函数 当当我我们们定定义义一一个个类类时时,,可可以以在在类类中中直直接接定定义义函函数数体体这这时时成成员员函函数在编译时是作为数在编译时是作为内联函数内联函数来实现的来实现的 同时,我们也可以在类体外定义类的内联成员函数,在类体内说明同时,我们也可以在类体外定义类的内联成员函数,在类体内说明函数,函数,在类体外定义时,在成员函数的定义前面加上关键字在类体外定义时,在成员函数的定义前面加上关键字inline。

       class  A{       float  x, y;  public:      void Setxy(float a,float  b);;      void  Print(void);;};inline   void A::Setxy(float a,float  b)     {  x=a;   y=b;   }inline  void  A::Print(void)     {   cout<

       《《存储类型存储类型》》类名类名   对象对象1,对象,对象2《《,......》》;;Student   st1,,st2;; 对象的定义格式:对象的定义格式:类名类名对象名对象名在建立对象时,只为对象分配用于保存数据成员的内存空在建立对象时,只为对象分配用于保存数据成员的内存空间,间,而成员函数的代码为该类的每一个对象所共享而成员函数的代码为该类的每一个对象所共享 617 对象的定义方法同结构体定义变量的方法一样,也对象的定义方法同结构体定义变量的方法一样,也分三种,分三种,当类中有数据成员的访问权限为私有时,当类中有数据成员的访问权限为私有时,不允许对对象进行初始化不允许对对象进行初始化class  A {        float  x,y;public:          void Setxy( float a, float b  ){  x=a;   y=b;   }       void  Print(void) {  cout<

      运算符619 class  A {        float  x,y;public:         float   m,n;        void Setxy( float a, float b  ){  x=a;   y=b;   }       void  Print(void) {  cout<

       621 class  A {        float  x,y;public:         float   m,n;        void Setxy( float a, float b  ){  x=a;   y=b;   }       void  Print(void) {  cout<

      这与一般变量作为函数的参以作函数的出口参数这与一般变量作为函数的参数是完全相同的数是完全相同的 可以定义类类型的指针,类类型的引用,对象数可以定义类类型的指针,类类型的引用,对象数组,指向类类型的指针数组和指向一维或多维数组,指向类类型的指针数组和指向一维或多维数组的指针变量组的指针变量 一个类的对象,可作为另一个类的成员一个类的对象,可作为另一个类的成员 624 类体的区域称为类体的区域称为类作用域类作用域类的成员函数与类的成员函数与成员数据,其作用域都是属于类的作用域,成员数据,其作用域都是属于类的作用域,仅在该类的范围内有效,仅在该类的范围内有效,故不能在主函数中故不能在主函数中直接通过函数名和成员名来调用函数直接通过函数名和成员名来调用函数  类作用域、类类型的作用域和对象的作用域类作用域、类类型的作用域和对象的作用域 625 class  A {        float  x,y;public:         float   m,n;        void Setxy( float a, float b  ){  x=a;   y=b;   }       void  Print(void) {  cout<

      对象的作用域对象的作用域与前面介绍的变量作用域完全与前面介绍的变量作用域完全相同相同 , 全局对象、局部对象、局部静态对象全局对象、局部对象、局部静态对象等627 class  A {        float  x,y;public:         float   m,n;        void Setxy( float a, float b  ){  x=a;   y=b;   }       void  Print(void) {  cout<

      在函数内有效全局对象全局对象局部对象局部对象628 类的嵌套在定义一个类时在定义一个类时, 在其类体中又包含了一个在其类体中又包含了一个类的完整定义,称为类的嵌套类的完整定义,称为类的嵌套 类是允许嵌套定义的类是允许嵌套定义的 629 class  A {        class B{                 int i,j;      public :             void Setij(int  m,  int n){   i=m;   j=n;  }        };        float  x,y;public:         B  b1,b2;       void Setxy( float a, float b  ){  x=a;   y=b;   }       void  Print(void) {  cout<

      嵌套类的作用域在类嵌套类的作用域在类A的定义结的定义结束时结束束时结束630 类的对象如何引用私有数据成员类的对象如何引用私有数据成员1、通过公有函数为私有成员赋值、通过公有函数为私有成员赋值class  Test{int  x ,  y;    public:       void Setxy(int  a, int b){x=a;y=b;}       void  Printxy(void) {cout<<"x="<

      重载时,函数的形参必须在重载时,函数的形参必须在类型类型或或数目数目上不上不同641 class  Test{int  x ,  y;int  m,  n;    public:        void Setxy(int  a, int b){x=a;y=b;}        void  Setxy(int a,int b,int c,int d){ x=a;y=b;m=c;n=d;}        void Printxy(int x){cout<< “m="<

      开始缺省644 缺省参数的成员函数缺省参数的成员函数class A{float  x,y;public:float Sum(void) {   return  x+y;   }void Set(float a,float b=10.0) {    x=a;y=b;}      void Print(void) {cout<<"x="<Set(2.0,  3.0);    //通过指针引用对象的成员函数通过指针引用对象的成员函数            p->Print();            cout<Sum()<Show ();//指针变量指向数组元素指针变量指向数组元素pstu++;//指针变量加一,指向下一元素指针变量加一,指向下一元素}}stupstupstu647 返回引用类型的成员函数返回引用类型的成员函数(可以返回私有数据成员的引用可以返回私有数据成员的引用)class A{float  x,y;public:float &Getx(void ) {   return  x;   }  //返回返回x的引用的引用void Set(float a,float b) {    x=a;   y=b;   }void Print(void) {   cout<

      当存放的数据大于原先开辟的空间时,线性表的首地址当存放的数据大于原先开辟的空间时,线性表自动自动动态开辟动态开辟空间,储存所有的整数空间,储存所有的整数线性表有线性表有三个参数三个参数来描述:指向线性表存储空间首地址的来描述:指向线性表存储空间首地址的指针变量指针变量List;无符号整数;无符号整数nMax,,指示表的最大长度;无指示表的最大长度;无符号整数符号整数nElem,,指示表中实际所放的数据个数指示表中实际所放的数据个数实际上,线性表相当于一个整型数组,实际上,线性表相当于一个整型数组,List为数组的首地为数组的首地址,址,nMax为数组在内存开辟的空间数,为数组在内存开辟的空间数,nElem为数组中为数组中实际存放的元素个数只不过实际存放的元素个数只不过数组的空间是动态开辟的数组的空间是动态开辟的649 class ListClass {   int *List;    //指向线性表的指针指向线性表的指针   unsigned nMax;    //表的最大长度表的最大长度   unsigned nElem;    //表中当前的元素个数表中当前的元素个数  .......};3 7 9 2 4ListnElemnMax空间是动态开辟的空间是动态开辟的650 class ListClass {   int *List;    //指向线性表的指针指向线性表的指针   unsigned nMax;    //表的最大长度表的最大长度   unsigned nElem;    //表中当前的元素个数表中当前的元素个数public:void Init(int n=10);   //初始化针表,最大长度的缺省值为初始化针表,最大长度的缺省值为10void Elem(int); //性表尾增加一个元素性表尾增加一个元素int & Elem(unsigned n);//返回线性表中第返回线性表中第n个元素的引用个元素的引用unsigned Elem(void);//返回当前线性表中元素的个数返回当前线性表中元素的个数unsigned Max(void);//返回线性表的长度(占用空间数)返回线性表的长度(占用空间数)void Print(void);//输出线性表中所有的元素输出线性表中所有的元素int GetElem(int i);//返回线性表中第返回线性表中第i个元素的值个元素的值void Destroy(void); //收回线性表占用的存储空间收回线性表占用的存储空间};651 void ListClass::Elem (int elem) //性表尾增加一个元素性表尾增加一个元素{nElem=nElem+1;if(nElem>nMax)//空间不够,动态开辟存储空间空间不够,动态开辟存储空间{int *list;list=new int[nMax+1]; //开辟一较大的空间开辟一较大的空间for(int i=0;i

      空间652 this 指针指针不同对象占据内存中的不同区域,它们所保存的数不同对象占据内存中的不同区域,它们所保存的数据各不相同,但据各不相同,但对成员数据进行操作的成员函数的对成员数据进行操作的成员函数的程序代码均是一样的程序代码均是一样的class A{       int x,y;    public:       void Setxy(int a, int b)    {  x=a;   y=b;}};A   a1,  a2;a1.xa1.ya2.xa2.y......x=a ;y=b ;......a1. Setxy()a2. Setxy()a1.Setxy(1,2);a2.Setxy(3,4);this->x=a;this->y=b;系统自动将对象的指系统自动将对象的指针带到成员函数中针带到成员函数中653 当对一个对象调用成员函数时,当对一个对象调用成员函数时,编译程序先编译程序先将对象的地址赋给将对象的地址赋给this指针,然后调用成员函指针,然后调用成员函数,数,每次成员函数存取数据成员时,也隐含每次成员函数存取数据成员时,也隐含使用使用this指针this指针具有如下形式的缺省说明:指针具有如下形式的缺省说明:   Stu   *const    this;  类名类名即即 this 指针里的地址是一个常量指针里的地址是一个常量654 class S{public :         char  *strp;         int length;         void Ini(char *s);          void Print(void);         void Copy(S  &s);};void main(void){S  s1,s2;s1.Ini(“China”);          s2.Ini(“”);s1.Print();          s2.Copy(s1);          s2.Print();          s1.Copy(s1);}void S::Ini(char *s){   length=strlen(s);    strp=new char[length+1];     strcpy(strp, s);}void S::Print(void){     cout<

      构造函数是在创建对象时,使用给定的值来构造函数是在创建对象时,使用给定的值来将对象初始化将对象初始化析构函数的功能正好相反,是在系统释放对析构函数的功能正好相反,是在系统释放对象前,对对象做一些善后工作象前,对对象做一些善后工作660 构构造造函函数数是是类类的的成成员员函函数数,,系系统统约约定定构构造造函函数数名名必必须须与与类类名名相相同同构构造造函函数数提提供供了了初初始始化对象的一种简单的方法化对象的一种简单的方法构造函数构造函数可以带参数、可以重载可以带参数、可以重载,同时没有,同时没有返回值661 class A{float  x,y;public:A(float a,float b){  x=a;   y=b;}//构造函数,初始化对象构造函数,初始化对象float Sum(void) {   return  x+y;   }void Set(float  a,float  b) {    x=a;y=b;}Print(void) {  cout<<"x="<

      构构造造函函数数的的主主要要作作用用是是完完成成初初始始化化对对象象的的数数据据成成员以及其它的初始化工作员以及其它的初始化工作2. 在在定定义义构构造造函函数数时时,,不不能能指指定定函函数数返返回回值值的类型,也不能指定为的类型,也不能指定为void类型类型3. 一一个个类类可可以以定定义义若若干干个个构构造造函函数数当当定定义义多个构造函数时,多个构造函数时,必须满足函数重载的原则必须满足函数重载的原则663 4.构造函数可以指定参数的缺省值构造函数可以指定参数的缺省值5.若若定定义义的的类类要要说说明明该该类类的的对对象象时时,,构构造造函函数数必必须须是是公公有有的的成成员员函函数数如如果果定定义义的的类类仅仅用用于于派派生生其其它它类类时时,,则则可可将将构构造造函函数数定定义义为为保护的成员函数保护的成员函数由由于于构构造造函函数数属属于于类类的的成成员员函函数数,,它它对对私私有有数数据据成成员员、、保保护护的的数数据据成成员员和和公公有有的的数数据据成成员员均能进行初始化均能进行初始化664 class  A{float   x,y;public:A(float a, float b=10){  x=a;   y=b;  } A(){    x=0;  y=0;} void  Print(void) {cout<

      系统默认缺省的构造函数class  A{float   x,y;public:A() {}{} void  Print(void) {cout<

      新产生对象的数据成员的值是不确定的 670 class A{float  x,y;public:A(){}//缺省的构造函数,编译器自动产生缺省的构造函数,编译器自动产生,可以不写可以不写float Sum(void) {   return  x+y;   }void Set(float a,float b) {    x=a;y=b;}      void Print(void) {cout<<"x="<

      因因为为在在撤撤消消对对象象时时,,系系统统自自动动收收回回为为对对象象所所分分配配的的存存储储空空间间,,而而不不能能自自动动收收回回由由new分分配配的的动动态态存存储储空间682 class Str{char *Sp;    int Length;public:Str(char *string){   if(string){Length=strlen(string);     Sp=new char[Length+1];strcpy(Sp,string);        }    else      Sp=0;}void Show(void){ cout<

      析构函数当使用运算符当使用运算符delete删除一个由删除一个由new动动态产生的对象时,它首先调用该对象的析构函数,态产生的对象时,它首先调用该对象的析构函数,然后再释放这个对象占用的内存空间然后再释放这个对象占用的内存空间可以用可以用new运算符为对象分配存储空间,如:运算符为对象分配存储空间,如:A   *p;p=new A;这时必须用这时必须用delete才能释放这一空间才能释放这一空间delete   p;685 class  A{float   x,y;public:  A(float a, float b){ x=a;y=b;cout<<"调用了构造函数调用了构造函数\n";}  void  Print(void){  cout<Print();    delete  pa1;  //调用析构函数调用析构函数    cout<<"退出退出main()函数函数\n";}进入进入main()函数函数调用了构造函数调用了构造函数35调用了析构函数调用了析构函数退出退出main()函数函数686 不同存储类型的对象调用构造函数及析构函数不同存储类型的对象调用构造函数及析构函数  1、、对对于于全全局局定定义义的的对对象象((在在函函数数外外定定义义的的对对象象)),,在在程程序序开开始始执执行行时时,,调调用用构构造造函函数数;;到到程程序序结结束束时时,,调用析构函数。

      调用析构函数2、、对对于于局局部部定定义义的的对对象象((在在函函数数内内定定义义的的对对象象)),,当当程程序序执执行行到到定定义义对对象象的的地地方方时时,,调调用用构构造造函函数数;;在退出对象的作用域时,调用析构函数在退出对象的作用域时,调用析构函数3、、用用static定定义义的的局局部部对对象象,,在在首首次次到到达达对对象象的的定定义时调用构造函数;到程序结束时,调用析构函数义时调用构造函数;到程序结束时,调用析构函数687  4、、对对于于用用new运运算算符符动动态态生生成成的的对对象象,,在在产产生生对对象象时时调调用用构构造造函函数数,,只只有有使使用用delete运运算算符符来来释释放放对对象象时时,,才才调调用用析析构构函函数数若若不不使使用用delete来来撤撤消消动动态态生生成成的的对对象象,,程程序序结结束束时时,,对对象象仍仍存存在在,,并并占占用用相相应应的的存存储储空空间间,,即即系系统统不不能能自自动动地地调调用用析析构构函函数来撤消动态生成的对象数来撤消动态生成的对象688 class  A{float   x,y;public:   A(float a, float b){x=a;y=b;cout<<"初始化自动局部对象初始化自动局部对象\n";}   A(){ x=0;  y=0;  cout<<"初始化静态局部对象初始化静态局部对象\n";}   A(float  a){ x=a;  y=0;  cout<<"初始化全局对象初始化全局对象\n"; }  ~A(){  cout<<“调用析构函数调用析构函数”<

      求指定数据范围内的所有素数如:如:  定义类定义类NUM的对象的对象test,查找范围为,查找范围为100~~200,正,正确的输出结果:确的输出结果:num=21101  103  107  109  113127  131 ……690 动态构造及析构对象数组动态构造及析构对象数组 用用new运算符来动态生成对象数组时,自动调用构运算符来动态生成对象数组时,自动调用构造函数,而用造函数,而用delete运算符来运算符来释放释放p1所指向的对象所指向的对象数组数组占用的存储空间时,在指针变量的前面必须加占用的存储空间时,在指针变量的前面必须加上上[ ],, 才能将数组元素所占用的空间全部释放才能将数组元素所占用的空间全部释放否则,只释放第否则,只释放第0个元素所占用的空间个元素所占用的空间pa1=new  A[3];..... delete  [ ]pa1; 691 class  A{float   x,y;public:    A(float a=0, float b=0){x=a;  y=b;cout<<"调用了构造函数调用了构造函数\n";}    void  Print(void){  cout<

       693 实现类型转换的构造函数实现类型转换的构造函数同类型的对象可以相互赋值,相当于类中的数据同类型的对象可以相互赋值,相当于类中的数据成员相互赋值;成员相互赋值;如果如果直接将数据赋给对象直接将数据赋给对象,所赋入的数据需要强,所赋入的数据需要强制类型转换,制类型转换,这种转换需要调用构造函数这种转换需要调用构造函数694 class A{float x,y;public:   A(float a,float b) {x=a;y=b;cout<<"调用构造函数调用构造函数\n";}   ~A() {cout<<"调用析构函数调用析构函数\n";}    void Print(void) {    cout<

      class B{float x;public:   B(float a) {x=a;  cout<<"调用构造函数调用构造函数\n";}             ~B() {  cout<<"调用析构函数调用析构函数\n";}             void Print(void) {    cout<

      构造函数常为完成拷贝功能的构造函数完成拷贝功能的构造函数的一般格式为:完成拷贝功能的构造函数的一般格式为:ClassName::ClassName(ClassName  &<变量名变量名>){......//   函数体完成对应数据成员的赋值函数体完成对应数据成员的赋值}697 class  A{float   x,y;public::         A(float a=0, float b=0){x=a;  y=b;}         A(A &a)          { x=a.x;  y=a.y;}};;void main(void){   A   a1(1.0,2.0);     A   a2(a1);}形参形参必须必须是同类型对象的引用是同类型对象的引用实参是同类型的对象实参是同类型的对象698 class  A{float   x,y;public:   A(float a=0, float b=0){x=a;  y=b;cout<<"调用了构造函数调用了构造函数\n";}   A(A &a)          { x=a.x;y=a.y;cout<<“调用了完成拷贝功能的构造函数调用了完成拷贝功能的构造函数\n”; }   void  Print(void){  cout<

       A::A(A &a){       x=a.x;       y=a.y; }隐含的构隐含的构造函数造函数700 class  A{float   x,y;public:   A(float a=0, float b=0){x=a;  y=b;cout<<"调用了构造函数调用了构造函数\n";}   void  Print(void){  cout<

      成员的拷贝但但是是,,当当类类中中的的数数据据成成员员中中使使用用new运运算算符符,,动动态态地地申申请请存存储储空空间间进进行行赋赋初初值值时时,,必必须须在在类类中中显显式式地地定定义义一一个个完完成成拷拷贝贝功功能能的的构构造造函函数,以便正确实现数据成员的复制数,以便正确实现数据成员的复制702 class  Str{    int Length;   char  *Sp;public:    Str(char *string){    if(string){Length=strlen(string);       Sp=new char[Length+1];       strcpy(Sp,string);}       else Sp=0;  } void Show(void){cout<

      行错误703 在这种情况下,在这种情况下,必须必须要定义完成拷贝功能的构造函数要定义完成拷贝功能的构造函数Str::Str(Str &s){  if(s.Sp){Length=s.Length ;Sp=new char[Length+1];strcpy(Sp,s.Sp);}else Sp=0;}       Str s2(s1);“Study  C++”s1.Sp原来原来s1开开辟的空间辟的空间“Study  C++”s2.Sp拷贝函数中用拷贝函数中用new开辟的空间开辟的空间704 构造函数与对象成员构造函数与对象成员对类对类A的对象初始化的同时还要对其的对象初始化的同时还要对其成员数成员数据类据类B的对象的对象进行初始化,所以,进行初始化,所以,类类A的构造的构造函数中要调用类函数中要调用类B的构造函数的构造函数class B{    ....};;class A{    int x , y;    B   b1,b2; };;在类在类A中包含中包含类类B的对象的对象705 class  A {float   x,y;public:    A(int a,int b){x=a;y=b;}   void Show(){ cout<< "x="<

      也可以仅对部分对象成员进行初始化也可以仅对部分对象成员进行初始化708 class  A {float   x,y;public: A(int a,int b) {x=a;y=b;}void Show(){ cout<< "x="<

      员初始化列表中的顺序无关当当建建立立类类ClassName的的对对象象时时,,先先调调用用各各个个对对象象成成员员的的构构造造函函数数,,初初始始化化相相应应的的对对象象成成员员,,然然后后才才执执行行类类ClassName的的构构造造函函数数,,初初始始化化类类ClassName中中的的其其它它成成员员析析构构函函数的调用顺序与构造函数正好相反数的调用顺序与构造函数正好相反710 class A{float  x;public:      A(int a){  x=a;  cout<<“调用了调用了A的构造函数的构造函数\n”;}     ~A(){cout<<“调用了调用了A的析构函数的析构函数\n”;}};class B{float  y;public:      B(int a){  y=a;  cout<<“调用了调用了B的构造函数的构造函数\n”;}     ~B(){cout<<“调用了调用了B的析构函数的析构函数\n”;}};class C{float z; B  b1;  A a1;public:      C(int a,int b,int c): a1(a),b1(b){z=c;cout<<“调用了调用了C的构造函数的构造函数\n”;}     ~C(){cout<<“调用了调用了C的析构函数的析构函数\n”;}};void main(void){   C  c1(1,2,3);   }调用了调用了B的构造函数的构造函数调用了调用了A的构造函数的构造函数调用了调用了C的构造函数的构造函数调用了调用了C的析构函数的析构函数调用了调用了A的析构函数的析构函数调用了调用了B的析构函数的析构函数711 第十一章 继承和派生类712 继承性是面向对象程序设计中最重要的机制。

      继承性是面向对象程序设计中最重要的机制这种机制这种机制提供了无限重复利用程序资源的一提供了无限重复利用程序资源的一种途径种途径通过C++语言中的继承机制,语言中的继承机制,可以可以扩充和完善旧的程序设计以适应新的需求扩充和完善旧的程序设计以适应新的需求这样不仅可以节省程序开发的时间和资源,这样不仅可以节省程序开发的时间和资源,并且为未来程序增添了新的资源并且为未来程序增添了新的资源713 class Student{   int num;    char name[30];    char sex; public:                                void display( )                    //对成员函数对成员函数display的定义的定义    {cout<<"num: "<

      内容即可,以减少重复的工作量 C++C++提供的继承提供的继承机制就是为了解决这个问题机制就是为了解决这个问题 在在C++中所谓中所谓“继承继承”就是在一个已存在的类的基就是在一个已存在的类的基础上建立一个新的类础上建立一个新的类已存在的类称为已存在的类称为“基类基类(base class)”或或“父类父类(father class)”新建立的新建立的类称为类称为“派生类派生类(derived class)”或或“子类子类(son class)” 716 class Student1: public Student//声明基类是声明基类是Student{private:      int age;    //新增加的数据成员新增加的数据成员    string addr;  //新增加的数据成员新增加的数据成员public:   void display_1( )  //新增加的成员函数新增加的成员函数   {  cout<<"age: "<

      为派生类AB新增加的成员数新增加的成员数据和成员函数据和成员函数718 在在C++语言中,语言中,一个派生类可以从一个基类一个派生类可以从一个基类派生,也可以从多个基类派生派生,也可以从多个基类派生从一个基类从一个基类派生的继承称为单继承;从多个基类派生的派生的继承称为单继承;从多个基类派生的继承称为多继承继承称为多继承719 通过继承机制,可以利用已有的数据类型来通过继承机制,可以利用已有的数据类型来定义新的数据类型定义新的数据类型所定义的新的数据类型所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧不仅拥有新定义的成员,而且还同时拥有旧的成员我们称已存在的用来派生新类的类我们称已存在的用来派生新类的类为基类,又称为父类为基类,又称为父类由已存在的类派生出由已存在的类派生出的新类称为派生类,又称为子类的新类称为派生类,又称为子类720 在建立派生类的过程中,基类不会做任何改在建立派生类的过程中,基类不会做任何改变,变,派生类则除了继承基类的所有可引用的派生类则除了继承基类的所有可引用的成员变量和成员函数外,还可另外定义本身成员变量和成员函数外,还可另外定义本身的成员变量和处理这些变量的函数,的成员变量和处理这些变量的函数,由于派由于派生类可继承基类的成员变量和成员函数,因生类可继承基类的成员变量和成员函数,因此在基类中定义好的数据和函数等的程序代此在基类中定义好的数据和函数等的程序代码可重复使用,这样可以提高程序的可靠性。

      码可重复使用,这样可以提高程序的可靠性721 当当从从已已有有的的类类中中派派生生出出新新的的类类时时,,可可以以对对派派生生类类做做以以下下几几种变化:种变化:1、、 可以继承基类的成员数据或成员函数可以继承基类的成员数据或成员函数2、可以增加新的成员变量可以增加新的成员变量3、可以增加新的成员函数可以增加新的成员函数4、可以重新定义已有的成员函数可以重新定义已有的成员函数5、可以改变现有的成员属性可以改变现有的成员属性在在C++中中有有二二种种继继承承::单单一一继继承承和和多多重重继继承承当当一一个个派派生生类类仅仅由由一一个个基基类类派派生生时时,,称称为为单单一一继继承承;;而而当当一一个个派派生生类类由二个或更多个基类所派生时,称为多重继承由二个或更多个基类所派生时,称为多重继承722 类类A派生类派生类B:类:类A为基类,类为基类,类B为派生类为派生类AB但派生并不是简单的扩充,有可能改变基类的性质但派生并不是简单的扩充,有可能改变基类的性质有三种派生方式:公有派生、保护派生、私有派生有三种派生方式:公有派生、保护派生、私有派生class B::public   A{...};  class B::protected   A{...};  class B::private   A{...};  默认的是私有派生。

      默认的是私有派生class B::  A {...};  A为私有派生为私有派生723 从一个基类派生一个类的一般格式为:从一个基类派生一个类的一般格式为:class  ClassName:BaseClassName {       private:          ......;; //私有成员说明私有成员说明        public:          ......;; //公有成员说明公有成员说明        protected:          ......;; //保护成员说明保护成员说明   }}派生类名派生类名基类名基类名继承方式继承方式public: 表示公有基类表示公有基类private:表示私有基类表示私有基类(默认默认)protected:表示保护基类表示保护基类派生类中新增加的成员派生类中新增加的成员724 公有派生class ClassName: public BaseClassName公有派生时,公有派生时,基类中所有成员在派生类中保持各个成员的访问权限基类中所有成员在派生类中保持各个成员的访问权限公有派生,派生类中保持基类的成员特性公有派生,派生类中保持基类的成员特性基类成员属性基类成员属性派生类中派生类中派生类外派生类外公有公有可以引用可以引用可以引用可以引用保护保护可以引用可以引用不可引用不可引用私有私有不可引用不可引用不可引用不可引用基类:基类:public:   在派生类和类外可以使用在派生类和类外可以使用protected: 在派生类中使用在派生类中使用private: 不能在派生类中使用不能在派生类中使用725 x(私有私有)y(保护保护)z(公有公有)A( )Getx()Gety()ShowA()Ax(私私有私私有)y(保护保护)z(公有公有)A( )Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()publicx在类在类B新增加的成员中不能直新增加的成员中不能直接调用接调用y在类在类B中可以调用中可以调用z在整个文件中可以调用在整个文件中可以调用对类对类B的对象初始化即是对的对象初始化即是对x,y,z,m,n等全部成员的初始化等全部成员的初始化726 class  A {   int  x;protected:   int y;public:      int z;   A(int a,int b,int c){x=a;y=b;z=c;}//基类初始化基类初始化  int  Getx(){return x;}//返回返回x  int  Gety(){return y;}//返回返回y  void ShowA(){cout<< "x="<

      可以用多个基类来派生一个类ABCD多重继承是单多重继承是单一继承的扩展一继承的扩展派生类中新定派生类中新定义的成员义的成员738 格式为:格式为:class  类名类名:类名类名1,..., 类名类名n{      private:     ...... ;;   //私有成员说明私有成员说明;      public:      ...... ;;   //公有成员说明公有成员说明;      protected:   ...... ;;   //保护的成员说明保护的成员说明;};继承方式继承方式class  D: public  A, protected B, private C {    ....//派生类中新增加成员派生类中新增加成员};739 class A{ int x1,y1;public: A(int a,int b){ x1=a; y1=b;}void ShowA(void){ cout<<"A.x="<

      派生类构造函数的调用顺序如下:派生类构造函数的调用顺序如下:基类的构造函数基类的构造函数子对象类的构造函数子对象类的构造函数派生类的构造函数派生类的构造函数741 class B:public A{         int  y;          A  a1;public:         B(int a, int b):A(a),a1(3){y=b;}         .......};当撤销派生类对象时,析当撤销派生类对象时,析构函数的调用正好相反构函数的调用正好相反基类的构造函数基类的构造函数子对象类的构造函数子对象类的构造函数派生类的构造函数派生类的构造函数742 class  Base1 { int  x;public:  Base1(int a){x=a;cout<<"调用基类调用基类1的构造函数的构造函数!\n";}~Base1( ){cout<<"调用基类调用基类1的析构函数的析构函数!\n";}};class  Base2 { int y;public: Base2(int a){ y=a;cout<<"调用基类调用基类2的构造函数的构造函数!\n";}~Base2( ){cout<<"调用基类调用基类2的析构函数的析构函数!\n";}};class Derived:public Base2, public  Base1{int z;public:  Derived(int a,int b):Base1(a),Base2(20)    {z=b;   cout<<"调用派生类的构造函数调用派生类的构造函数!\n";}~Derived( ){cout<<"调用派生类的析构函数调用派生类的析构函数!\n";}};void  main(void){Derived   c(100,200);}调用基类调用基类2的构造函数的构造函数调用基类调用基类1的构造函数的构造函数调用派生类的构造函数调用派生类的构造函数调用派生类的析构函数调用派生类的析构函数调用基类调用基类1的析构函数的析构函数调用基类调用基类2的析构函数的析构函数先说明基类先说明基类2743 class Derived:public Base2, public  Base1{int z;           Base1  b1,b2;    public:    Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b)          {z=b;   cout<<"调用派生类的构造函数调用派生类的构造函数!\n";}    ~Derived( ){cout<<"调用派生类的析构函数调用派生类的析构函数!\n";}};void  main(void){Derived   c(100,200);}基类子对象基类子对象基类成员构造基类成员构造基类子对象构造基类子对象构造基类成员构造用基类名,基类成员构造用基类名,基类子对象构造用对象名基类子对象构造用对象名744 class  Base1 { int  x;public:  Base1(int a){x=a;cout<<"调用基类调用基类1的构造函数的构造函数!\n";}~Base1( ){cout<<"调用基类调用基类1的析构函数的析构函数!\n";}};class  Base2 { int y;public: Base2(int a){ y=a;cout<<"调用基类调用基类2的构造函数的构造函数!\n";}~Base2( ){cout<<"调用基类调用基类2的析构函数的析构函数!\n";}};class Derived:public Base2, public  Base1{int z;  Base1  b1,b2; public:  Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b)    {z=b;   cout<<"调用派生类的构造函数调用派生类的构造函数!\n";}~Derived( ){cout<<"调用派生类的析构函数调用派生类的析构函数!\n";}};void  main(void){Derived   c(100,200);}745 调用基类调用基类2的构造函数的构造函数调用基类调用基类1的构造函数的构造函数调用派生类的构造函数调用派生类的构造函数调用派生类的析构函数调用派生类的析构函数调用基类调用基类1的析构函数的析构函数调用基类调用基类2的析构函数的析构函数调用基类调用基类1的构造函数的构造函数调用基类调用基类1的构造函数的构造函数调用基类调用基类1的析构函数的析构函数调用基类调用基类1的析构函数的析构函数说明基类说明基类1的对象的对象b1,b2746 class  Base1 {int  x;public:  Base1(int a);~Base1( );};class  Base2 {int y;public: Base2(int a);~Base2( );};class Derived:public Base2, public  Base1{int z;  Base1  b1,b2; public:  Derived(int a,int b);~Derived( );};xBase1()~Base1()Base1yBase2()~Base2()Base2DerivedxBase1()~Base1()yBase2()~Base2()xBase1()~Base1()b1xBase1()~Base1()b2zDerived()~Derived747 冲突冲突ABCxA()xB()xC()DA()xB()xC()xD()dD   v;v.x=5;public派生类对象派生类对象产生了冲突产生了冲突A::v.x=5;用类作用符限定用类作用符限定748 class  A{public:   int x;           void Show(){cout <<"x="<

      数的来源如:如:A::x=a;        c1.B::Show();749 支配规则支配规则AxA()DpublicxA()xD()基类成员基类成员派生类新增成员派生类新增成员D   v;v.x=5;当派生类中新增加的数据或当派生类中新增加的数据或函数与基类中原有的同名时,函数与基类中原有的同名时,若不加限制,则若不加限制,则优先调用派优先调用派生类中的成员生类中的成员5750 class  A{public: int x;void Show(){cout <<"x="<>a>>b;     Dot dot1(a,b);//调用调用Dot的构造函数的构造函数    cout<<"Input Dot2: \n"; cin>>a>>b;    Dot dot2(a,b);  Line line(dot1,dot2);   line.Showl();}用坐标初始化用坐标初始化Dot对象对象在在Line中新说明的成员中新说明的成员对成员初始化对成员初始化x,,y是继承基类的成员是继承基类的成员打印坐标打印坐标756  赋值兼容规则赋值兼容规则基类基类对象对象派生类派生类对象对象 相互之间能否赋值?相互之间能否赋值? 可以将派生类对象的值赋给基类对象。

      可以将派生类对象的值赋给基类对象反之不行反之不行Base  b;Derive  d; b = d; 只是将从基类只是将从基类继承来的成员继承来的成员赋值757 Show()Dot(&dot)Dot(x,y)yxDot的对象空间的对象空间Show()Dot(&dot)Dot(x,y)Show()Dot(&dot)Dot(x,y)yDot(&dot)Show()Dot(x.y)yxxShowl()Line()d2d1yxLine的对的对象空间象空间从基类从基类继承继承基类基类对象对象Dot   dot;Line  line;dot=line;line=dot;非法非法758 可以将一个派生类对象的地址赋给基类的指针变量可以将一个派生类对象的地址赋给基类的指针变量基类对象基类对象派生类对象派生类对象Base  b;Derive  d;Base *basep;basepbasep=&b;basepbasep = &dbasep只能引用只能引用从基类继承来从基类继承来的成员基类指针基类指针派生类对象派生类对象基类对象基类对象759 派生类对象可以初始化基类的引用派生类对象可以初始化基类的引用Derive  d;Base   basei=&d;基类对象基类对象派生类对象派生类对象Base  b;Derive  d;别名别名baseibasei只能引用只能引用从基类继承来从基类继承来的成员。

      的成员基类引用基类引用派生类对象派生类对象760 class  A{public: int x;A(int  a=0) { x=a;}};class B{public: int y;B(int a=0) { y=a;}};class C:public A,public B{    int z;public: C(int a,int b,int m):  A(a),   B(b) {  z=m;  }void Show( ){cout<<"x="<Show();}xA( )  yB( )zC( )Show( )102050a1.x=100b1.y=200x=10y=20z=50a1.x=10b1.y=20c1xA( )a1yB( )b11002001020错误!错误!761 虚基类虚基类 类类B  是类是类A的派生类的派生类xA()xA()yB()xA()zC()A类类B类类C类类dxD()xA()zC()yB()A()xD类类类类A拷贝拷贝类类C  是类是类A的派生类的派生类类类D  是类是类B和类和类C的派生类的派生类这样,类这样,类D中就有两份类中就有两份类A的拷贝的拷贝B类类C类类类类A拷贝拷贝762 这种同一个公共的基类这种同一个公共的基类在派生类中产生多个拷在派生类中产生多个拷贝,不仅多占用了存储贝,不仅多占用了存储空间,空间,而且可能会造成而且可能会造成多个拷贝中的数据不一多个拷贝中的数据不一致致 和模糊的引用和模糊的引用。

      D  d;d.x=10;    //模糊引用模糊引用dxD()xA()zC()yB()A()xD类类类类A拷贝拷贝B类类C类类类类A拷贝拷贝763 class  A{public: int x;A(int  a=0) { x=a;}};class B:public A{public: int y;B(int a=0,int b=0):A(a) { y=b;}};class C:public A{public: int z;C(int a,int c):A(a){  z=c;  }};class D:public B,public C{public: int dx;D(int a1,int b,int c,int d,int a2):B(a1,b),C(a2,c){dx=d;}};void  main(void){D d1(10,20,30,40,50);     cout<

      class B:public  virtual A{public:int y;B(int a=0, int b=0 ):A(b) { y=a;}};在派生类的定义中,只要在基类的类名前加上关键在派生类的定义中,只要在基类的类名前加上关键字字virtual,就可以将基类说明为虚基类,就可以将基类说明为虚基类765 xA()xA()yB()xA()zC()A类类B类类C类类xA()yB()zC()dxD()D类类一份拷贝,在一份拷贝,在D( )的构造函数中直的构造函数中直接调用接调用A()由虚基类派生出的对象初始由虚基类派生出的对象初始化时,化时,直接调用直接调用虚基类的构虚基类的构造函数因此,若将一个类造函数因此,若将一个类定义为虚基类,定义为虚基类,则一定有正则一定有正确的构造函数可供所有派生确的构造函数可供所有派生类调用766 class  A{public: int x;A(int  a=0) { x=a;}};class B:public  virtual A{public: int y;B(int a=0,int b=0): A(a) {y=b;}};class C:public virtual A{public: int z;C(int a=0,int c=0):A(a){z=c;  }};class D:public B,public C{public: int dx;D(int a1,int b,int c,int d,int a2):B(a1,b),C(a2,c){dx=d;}};void  main(void){D d1(10,20,30,40,50);     cout<

      且首先调用)768 第十二章第十二章        类的其它特性类的其它特性 769 友元函数友元函数类中私有和保护的成员在类外不能被访问类中私有和保护的成员在类外不能被访问友元函数是一种定义在类外部的友元函数是一种定义在类外部的普通函普通函数数,其特点是,其特点是能够访问类中私有成员和能够访问类中私有成员和保护成员保护成员,即类的访问权限的限制对其,即类的访问权限的限制对其不起作用不起作用770 友元函数需要在友元函数需要在类体内类体内进行说明,在前面加进行说明,在前面加上关键字上关键字friend一般格式为:一般格式为:friend   FuncName();friend   float Volume(A &a);关键字关键字返回值类型返回值类型函数名函数名函数参数函数参数771 友友元元函函数数不不是是成成员员函函数数,,用用法法也也与与普普通通的的函函数数完完全全一一致致,,只只不不过过它它能能访访问问类类中中所所有有的的数数据据友友元元函函数数破破坏坏了了类类的的封封装装性性和和隐隐蔽蔽性性,,使使得得非非成成员员函函数数可可以以访访问问类的私有成员类的私有成员。

      一个类的友元可以自由地用该类中的所有成员一个类的友元可以自由地用该类中的所有成员772 class A{float  x,y;public: A(float a, float b){  x=a; y=b;} float  Sum(){  return  x+y;  } friend  float Sum(A &a){     return   a.x+a.y;} };void main(void){  A   t1(4,5),t2(10,20);    cout<

      这样才能访问到对象的成员774 友元函数与一般函数的不同点在于友元函数与一般函数的不同点在于::1.友元函数必须在类的定义中说明,友元函数必须在类的定义中说明,其其函数体可在类内定义,也可在类外定函数体可在类内定义,也可在类外定义义;;2.它可以访问该类中的所有成员(公有它可以访问该类中的所有成员(公有的、私有的和保护的)的、私有的和保护的),而一般函数,而一般函数只能访问类中的公有成员只能访问类中的公有成员775 class A{float  x,y;public:   A(float a, float b){  x=a; y=b;} float  Getx(){  return x;  } float  Gety(){  return y; } float  Sum(){  return  x+y;  }  friend  float Sum(A &); };float  Sumxy(A  &a){ return a.Getx()+a.Gety();  }float Sum(A &a){  return a.x+a.y;  }void main(void){  A   t1(1,2),t2(10,20), t3(100,200);    cout<

      换换言言之之,,在在类类中中对友元函数指定访问权限是不起作用的对友元函数指定访问权限是不起作用的友元函数的作用域与一般函数的作用域相同友元函数的作用域与一般函数的作用域相同谨慎使用友元函数谨慎使用友元函数通常使用友元函数来通常使用友元函数来取取对象中的数据成员值,而对象中的数据成员值,而不不修改修改对象中的成员值,则肯定是安全的对象中的成员值,则肯定是安全的777 大大多多数数情情况况是是友友元元函函数数是是某某个个类类的的成成员员函函数数,,即即A类类中中的的某某个个成成员员函函数数是是B类类中中的的友友元元函函数数,,这这个个成成员员函函数数可可以以直直接接访访问问B类类中中的的私私有有数数据据这这就就实实现现了类与类之间的沟通了类与类之间的沟通注意:一个类的成员函数作为另一个类的友元函数时,注意:一个类的成员函数作为另一个类的友元函数时,应应先定义友元函数所在的类先定义友元函数所在的类class A{...void fun( B &);};class B{...friend void fun( B &);};既是类既是类A的成员函数的成员函数又是类又是类B的友元函数的友元函数778 class   B  ;//先定义类先定义类A,则首先对类,则首先对类B作引用性说明作引用性说明class   A{   ......//类类A的成员定义的成员定义   public:   void  fun( B & );//函数的原型说明函数的原型说明    };class  B{......    friend  void  A::fun( B & );//定义友元函数定义友元函数};;    void  A::fun ( B  &b)    //函数的完整定义函数的完整定义{     ......//函数体的定义函数体的定义}}类类A中的成员函数中的成员函数fun()是类是类B的友元函数。

      的友元函数即在即在fun()中可以直中可以直接引用类接引用类B的私有成的私有成员779 class B;//必须在此进行引用性说明,必须在此进行引用性说明,class A{float  x,y;public:   A(float a, float b){  x=a; y=b;}  float Sum(B &); //说明友元函数的函数原型,是类说明友元函数的函数原型,是类A的一成员函数的一成员函数};class B{float  m,n;public:   B(float a,float  b){  m=a;n=b;  }   friend  float A::Sum(B  &);//说明类说明类A的成员函数是类的成员函数是类B的友元函数的友元函数}float  A::Sum( B  &b)//定义该友元函数定义该友元函数{    x=b.m+b.n;   y=b.m-b.n;  }void main(void){    A   a1(3,5);     B   b1(10,20);     a1.Sum(b1); //调用该函数,调用该函数,因是类因是类A的成员函数,故用类的成员函数,故用类A的对象调用的对象调用}a1.x=30a1.y=-10直接引用类直接引用类B的私有成员的私有成员类类A中有一个函数可以直中有一个函数可以直接引用类接引用类B的私有成员的私有成员780 友元类友元类class A{    .....    friend class B;}class B{    ..... }类类B是类是类A的友元的友元类类B可以自由使用可以自由使用类类A中的成员中的成员对于类对于类B而言,类而言,类A是透明的是透明的类类B必须通过必须通过类类A的对象的对象使用类使用类A的成员的成员781 const float PI =3.1415926;class  A{float r ;float h;public: A(float a,float b){r=a; h=b;}float Getr(){return r;}float Geth(){return h;}friend class B;//定义类定义类B为类为类A的友元的友元};class B{   int number;public: B(int n=1){number=n;}void Show(A &a){ cout<

      私有成员782 不管是按哪一种方式派生,基类的私有成员不管是按哪一种方式派生,基类的私有成员在派生类中都是不可见的在派生类中都是不可见的如果在一个派生类中要访问基类中的私有成如果在一个派生类中要访问基类中的私有成员,可以将这个员,可以将这个派生类声明为基类的友元派生类声明为基类的友元class Base {    friend class  Derive;     .....}class Derive {     .....}直接使用直接使用Base中的私有成员中的私有成员783 #includeclass M{   friend class N;  //N为为M的友元,可以直接使用的友元,可以直接使用M中的私有成员中的私有成员private:    int i , j;     void show(void){cout<<"i="<

      但实现不同的功能多态性是面向对象的程序设计的关键技术多态性是面向对象的程序设计的关键技术编译时的多态性(函数重载)编译时的多态性(函数重载)运行时的多态性运行时的多态性(虚函数)(虚函数)多态性多态性运行时的多态性是指在程序执行之前,根据函数名和参数运行时的多态性是指在程序执行之前,根据函数名和参数无法确定应该调用哪一个函数,必须在程序的执行过程中,无法确定应该调用哪一个函数,必须在程序的执行过程中,根据具体的执行情况来动态地确定根据具体的执行情况来动态地确定786 可以将一个派生类对象的地址赋给基类的指针变量可以将一个派生类对象的地址赋给基类的指针变量基类对象基类对象派生类对象派生类对象Base  b;Derive  d;Base *basep;basepbasep=&b;basepbasep = &d;basep只能引用从基只能引用从基类继承来的成员类继承来的成员xShow()xShow()yShow()basep ->Show();basep->Show()基类指针基类指针派生类对象派生类对象基类对象基类对象787 class Point{float x,y;public: Point(){}Point(float i,float j){x=i;y=j;}float area(void) {return 0.0;}};const float Pi=3.14159;class Circle:public Point{//类类Point的派生类的派生类float radius;public: Circle(float r){radius=r;}float area(void) {     return Pi*radius*radius;}};void main(void){     Point *pp;     //基类指针,可以将派生类对象的地址赋给基类指针基类指针,可以将派生类对象的地址赋给基类指针      Circle c(5.4321);      pp=&c;       cout<area ()<

      在在这这种种情情况况下下,,使使用用基基类类的的指指针针时时,,只只能能访访问问从从相相应应基基类类中中继继承承来来的的成成员员,,而不允许访问在派生类中增加的成员输出为而不允许访问在派生类中增加的成员输出为  0788 基类对象基类对象派生类对象派生类对象Base  b;Derive  d;basepbasepxShow()xShow()yShow()basep->Show()Base *basep;basep=&b;basep = &d;basep ->Show();即指向派生类新增的成员函数即指向派生类新增的成员函数需要将基类中的需要将基类中的Show()说明为虚函数说明为虚函数789 若要访问派生类中相同名字的函数,必须将若要访问派生类中相同名字的函数,必须将基类中的基类中的同名函数定义为虚函数同名函数定义为虚函数,这样,将,这样,将不同的派生类对象的地址赋给基类的指针变不同的派生类对象的地址赋给基类的指针变量后,就可以量后,就可以动态地根据这种赋值语句调用动态地根据这种赋值语句调用不同类中的函数不同类中的函数790 class Point{  float x,y;public: Point(){}Point(float i,float j){x=i;y=j;}virtual  float area(void){  return 0.0;   }};const float Pi=3.14159;class Circle:public Point{//类类Point的派生类的派生类float radius;public: Circle(float r){radius=r;}float area(void) {  return Pi*radius*radius;}};void main(void){     Point *pp;     //基类指针,可以将派生类对象的地址赋给基类指针基类指针,可以将派生类对象的地址赋给基类指针      Circle c(5.4321);      pp=&c;       cout<area ()<

      使使Point类中的类中的area()与与Circle类中的类中的area()有一个统一有一个统一的接口输出:输出:92.7011声明为虚函数声明为虚函数调用虚函数调用虚函数虚函数再定义虚函数再定义791 虚函数的定义和使用虚函数的定义和使用      可可以以在在程程序序运运行行时时通通过过调调用用相相同同的的函函数数名名而而实实现不同功能的函数称为虚函数现不同功能的函数称为虚函数定义格式为:定义格式为:virtual    FuncName();一旦把基类的成员函数定义为虚函数,由基类所派一旦把基类的成员函数定义为虚函数,由基类所派生出来的所有派生类中,该函数均保持虚函数的特生出来的所有派生类中,该函数均保持虚函数的特性 在派生类中重新定义基类中的虚函数时,可以不用在派生类中重新定义基类中的虚函数时,可以不用关键字关键字virtual来修饰这个成员函数来修饰这个成员函数 792 虚函数是用关键字虚函数是用关键字virtual修饰的某基类中的修饰的某基类中的protected或或public成员函数它可以在派生成员函数它可以在派生类中重新定义,以形成不同版本。

      类中重新定义,以形成不同版本只有在程只有在程序的执行过程中,依据指针具体指向哪个类序的执行过程中,依据指针具体指向哪个类对象,或依据引用哪个类对象,才能确定激对象,或依据引用哪个类对象,才能确定激活哪一个版本,实现动态聚束活哪一个版本,实现动态聚束793 class  A{protected:int x;public: A(){x =1000;}   virtual void  print(){cout <<“x=”<print();//调用类调用类A的虚函数的虚函数    pa=&b;    pa->print();//调用类调用类B的虚函数的虚函数    pa=&c;     pa->print();}//调用类调用类C的虚函数的虚函数794 class Base {public : virtual  int  Set(int a, int b){ ..... }....};class Derive:public Base{public :   int  Set(int x, int y){ ..... }.....};class Base {public : virtual  int  Set(int a, int b){ ..... }....};class Derive:public Base{public :   int  Set(int x, int y=0){ ..... }.....};int Set(int ,int )是虚函数是虚函数两个两个Set()函数参数函数参数不一致,是重载,不一致,是重载,不是虚函数不是虚函数795 关于虚函数,说明以下几点:关于虚函数,说明以下几点:1、、当当在在基基类类中中把把成成员员函函数数定定义义为为虚虚函函数数后后,,在在其其派派生生类类中中定定义义的的虚虚函函数数必必须须与与基基类类中中的的虚虚函函数数同同名名,,参参数数的的类类型型、、顺顺序序、、参参数数的的个个数数必必须须一一一一对对应应,,函函数数的的返返回回的的类类型型也也相相同同。

      若若函函数数名名相相同同,,但但参参数数的的个个数数不不同同或或者者参参数数的的类类型型不不同同时时,,则则属属于于函函数数的的重重载载,,而而不不是是虚虚函函数数若若函函数数名名不不同同,,显显然然这这是是不不同同的的成成员函数796 2、、实现这种动态的多态性时,必须使用实现这种动态的多态性时,必须使用基类类型基类类型的指针变量的指针变量,并使该指针,并使该指针指向不同的派生类对象指向不同的派生类对象,,并通过调用指针所指向的虚函数才能实现动态的多并通过调用指针所指向的虚函数才能实现动态的多态性xShow()xShow()yShow()xShow()zShow()类类A类类B类类CShow()定义为虚函数定义为虚函数类类B与类与类C均为类均为类A的公有派生的公有派生A   *p;  B     b;C     c; p=&b ;  p->Show();p=&c ;  p->Show();即在程序运行时,即在程序运行时,通过赋值语句实通过赋值语句实现多态性现多态性797 3、、虚函数必须是类的一个成员函数,不能是虚函数必须是类的一个成员函数,不能是友元函数,也不能是静态的成员函数友元函数,也不能是静态的成员函数。

      4、在派生类中、在派生类中没有重新定义虚函数没有重新定义虚函数时,与一时,与一般的成员函数一样,当调用这种派生类对象般的成员函数一样,当调用这种派生类对象的虚函数时,的虚函数时,则调用其基类中的虚函数则调用其基类中的虚函数5、、可把析构函数定义为虚函数,但是,不能可把析构函数定义为虚函数,但是,不能将构造函数定义为虚函数将构造函数定义为虚函数798 6、、虚虚函函数数与与一一般般的的成成员员函函数数相相比比较较,,调调用用时时的的执执行行速速度度要要慢慢一一些些为为了了实实现现多多态态性性,,在在每每一一个个派派生生类类中中均均要要保保存存相相应应虚虚函函数数的的入入口口地地址址表表,,函函数数的的调调用用机机制制也也是是间间接接实实现现的的因因此此,,除除了了要要编编写写一一些些通通用用的的程程序序,,并并一一定定要要使使用用虚虚函函数数才才能能完完成成其其功功能能要要求外,通常不必使用虚函数求外,通常不必使用虚函数7、一个函数如果被定义成虚函数,则不管经历多、一个函数如果被定义成虚函数,则不管经历多少次派生,仍将保持其虚特性,以实现少次派生,仍将保持其虚特性,以实现“一个接口,一个接口,多个形态多个形态”。

      799 虚函数的访问虚函数的访问用基指针访问与用对象名访问用基指针访问与用对象名访问用基指针访问虚函数时,指向其实际派生类用基指针访问虚函数时,指向其实际派生类对象重新定义的函数实现动态聚束对象重新定义的函数实现动态聚束通过一个通过一个对象名对象名访问时,只能静态聚束即访问时,只能静态聚束即由编译器在编译的时候决定调用哪个函数由编译器在编译的时候决定调用哪个函数800 class Point{  float x,y;public: Point(){}Point(float i,float j){x=i;y=j;}virtual  float area(void){  return 0.0;   }//声明为虚函数声明为虚函数};const float Pi=3.14159;class Circle:public Point{//类类Point的派生类的派生类float radius;public: Circle(float r){radius=r;}float area(void) {  return Pi*radius*radius;}//虚函数再定义虚函数再定义};void main(void){     Point *pp;     //基类指针,可以将派生类对象的地址赋给基类指针基类指针,可以将派生类对象的地址赋给基类指针      Circle c(5.4321);      cout<

      可见,利用对象名进行调用与一般非虚函数没有区别用对象名调用用对象名调用area( )801 class base0{public: void v(void){cout<<"base0\n";}};class base1:public base0{public: virtual void v(void){  cout<<"base1\n";  }};class A1:public base1{public: void v(){cout<<"A1\n"; }};class A2:public A1{public: void v(void){cout<<"A2\n"; }};class B1:private base1{public: void v(void){cout<<"B1\n"; }};class B2:public B1{public: void v(void){cout<<"B2\n"; }};void main(void){   base0 *pb;    A1 a1;    (pb=&a1)->v();    A2 a2;     (pb=&a2)->v();     B1 b1;     (pb=&b1)->v();     B2 b2;     (pb=&b2)->v();}base0base0私有派生,在类外私有派生,在类外不能调用基类函数不能调用基类函数802 class base0{public: void v(void){cout<<"base0\n";}};class base1:public base0{public: virtual void v(void){  cout<<"base1\n";  }};class A1:public base1{public: void v(){cout<<"A1\n"; }};class A2:public A1{public: void v(void){cout<<"A2\n"; }};class B1:private base1{public: void v(void){cout<<"B1\n"; }};class B2:public B1{public: void v(void){cout<<"B2\n"; }};void main(void){   base1 *pb;    A1 a1;    (pb=&a1)->v();    A2 a2;     (pb=&a2)->v();}A1A2803 纯虚函数纯虚函数在基类中不对虚函数给出有意义的实现在基类中不对虚函数给出有意义的实现,,它只是在它只是在派生类中有具体的意义。

      这时基类中的虚函数只是派生类中有具体的意义这时基类中的虚函数只是一个入口,具体的目的地由不同的派生类中的对象一个入口,具体的目的地由不同的派生类中的对象决定这个虚函数称为决定这个虚函数称为纯虚函数纯虚函数class    <基类名基类名>{virtual <类型类型><函数名函数名>(<参数表参数表>)=0;......};804 class  A{protected:int x;public: A(){x =1000;}   virtual void  print()=0;  //定义纯虚函数定义纯虚函数};class B:public A{  //派生类派生类private:   int y;public: B(){ y=2000;}void  print(){cout <<“y=”<print(); pa=&c;    pa->print();    A  a;     pa=&a;       pa->print( );}y=2000z=3000抽象类抽象类不能定义抽象类的对象不能定义抽象类的对象805 1、、在在定定义义纯纯虚虚函函数数时时,,不不能能定定义义虚虚函函数数的的实实现部分。

      现部分2、、把把函函数数名名赋赋于于0,,本本质质上上是是将将指指向向函函数数体体的的指指针针值值赋赋为为初初值值0与与定定义义空空函函数数不不一一样样,,空空函函数数的的函函数数体体为为空空,,即即调调用用该该函函数数时时,,不不执执行行任任何何动动作作在在没没有有重重新新定定义义这这种种纯纯虚虚函函数之前,是不能调用这种函数的数之前,是不能调用这种函数的806 3、、把至少包含一个纯虚函数的类,称为抽象把至少包含一个纯虚函数的类,称为抽象类这种类只能作为派生类的基类,不能用类这种类只能作为派生类的基类,不能用来说明这种类的对象来说明这种类的对象其理由是明显的:因为虚函数没有实现部分,其理由是明显的:因为虚函数没有实现部分,所以不能产生对象但可以定义指向抽象类所以不能产生对象但可以定义指向抽象类的指针,即指向这种基类的指针当用这种的指针,即指向这种基类的指针当用这种基类指针指向其派生类的对象时,基类指针指向其派生类的对象时,必须在派必须在派生类中生类中重载重载纯虚函数,否则会产生程序的运纯虚函数,否则会产生程序的运行错误807 4、、在在以以抽抽象象类类作作为为基基类类的的派派生生类类中中必必须须有有纯纯虚虚函函数数的的实实现现部部分分,,即即必必须须有有重重载载纯纯虚虚函函数数的的函函数数体体。

      否否则则,,这这样样的的派派生生类类也也是是不不能能产生对象的产生对象的综综上上所所述述,,可可把把纯纯虚虚函函数数归归结结为为::抽抽象象类类的的唯唯一一用用途途是是为为派派生生类类提提供供基基类类,,纯纯虚虚函函数数的的作作用用是是作作为为派派生生类类中中的的成成员员函函数数的的基基础础,,并并实现动态多态性实现动态多态性808 虚基类虚基类多基派生中的多条路径具有公共基类时,在这条路径的汇合处就会多基派生中的多条路径具有公共基类时,在这条路径的汇合处就会因对公共基类产生多个拷贝而产生同名函数调用的二义性因对公共基类产生多个拷贝而产生同名函数调用的二义性解决这个问题的办法就是把解决这个问题的办法就是把公共基类定义为虚基类公共基类定义为虚基类,使由它派生的,使由它派生的多条路径的汇聚处只产生一个拷贝多条路径的汇聚处只产生一个拷贝class Base{ };class A : public Base{ };class B:  public  Base{ };class C: public A, public  B{ };类类C中继承了两个类中继承了两个类Base,,即有两个类即有两个类Base的实现部分,的实现部分,在调用时产生了二义性。

      在调用时产生了二义性809 用虚基类进行多重派生时,用虚基类进行多重派生时,若虚基类没有缺若虚基类没有缺省的构造函数省的构造函数,则在每一个派生类的构造函,则在每一个派生类的构造函数中数中都必须有对虚基类构造函数的调用都必须有对虚基类构造函数的调用 (且(且首先调用)首先调用)由虚基类派生出的对象初始化时,由虚基类派生出的对象初始化时,直接调用直接调用虚基类的构造函数因此,若将一个类定义虚基类的构造函数因此,若将一个类定义为虚基类,则一定有正确的构造函数可供所为虚基类,则一定有正确的构造函数可供所有派生类调用有派生类调用810 class base{public:virtual void a(){ cout<<"a() in base\n";}virtual void b(){ cout<<"b() in base\n";}virtual void c(){ cout<<"c() in base\n";}virtual void d(){ cout<<"d() in base\n";}virtual void e(){ cout<<"e() in base\n";}virtual void f(){ cout<<"f() in base\n";}};class A:public base{public:virtual void a(){ cout<<"a() in A\n";}virtual void b(){ cout<<"b() in A\n";}virtual void f(){ cout<<"f() in A\n";}};class B:public base{public:virtual void a(){ cout<<"a() in B\n";}virtual void b(){ cout<<"b() in B\n";}virtual void c(){ cout<<"c() in B\n";}};class C:public A,public B{public:virtual void a(){ cout<<"a() in C\n";}virtual void d(){ cout<<"d() in C\n";}};void main(void){      C cc;      base *pbase=&cc;//错误错误      A *pa=&cc;      pa->a();      pa->b();      pa->c();      pa->d();      pa->e();      pa->f();}将类将类C的地址赋的地址赋值时产生歧义值时产生歧义811 a( )b( )c( )d( )e( )f( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )b( )c( )d( )e( )f( )a( )c( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )b( )c( )d( )e( )f( )a( )c( )baseABCa( )d( )AB812 class base{public:virtual void a(){ cout<<"a() in base\n";}virtual void b(){ cout<<"b() in base\n";}virtual void c(){ cout<<"c() in base\n";}virtual void d(){ cout<<"d() in base\n";}virtual void e(){ cout<<"e() in base\n";}virtual void f(){ cout<<"f() in base\n";}};class A:public base{public:virtual void a(){ cout<<"a() in A\n";}virtual void b(){ cout<<"b() in A\n";}virtual void f(){ cout<<"f() in A\n";}};class B:public base{public:virtual void a(){ cout<<"a() in B\n";}virtual void b(){ cout<<"b() in B\n";}virtual void c(){ cout<<"c() in B\n";}};class C:public A,public B{public:virtual void a(){ cout<<"a() in C\n";}virtual void d(){ cout<<"d() in C\n";}};void main(void){      C cc;      base *pbase=&cc;//错误错误      A *pa=&cc;      pa->a();      pa->b();      pa->c();      pa->d();      pa->e();      pa->f();}将类将类C的地址赋的地址赋值时产生歧义值时产生歧义类类C中有两个中有两个base,只有一个,只有一个Aa() in Cb() in Ac() in based() in Ce() in basef() in A为避免这种情况,将为避免这种情况,将base定义定义为虚基类。

      为虚基类813 class base{public:virtual void a(){ cout<<"a() in base\n";}virtual void b(){ cout<<"b() in base\n";}virtual void c(){ cout<<"c() in base\n";}virtual void d(){ cout<<"d() in base\n";}virtual void e(){ cout<<"e() in base\n";}virtual void f(){ cout<<"f() in base\n";}};class A:virtual public base{public:virtual void a(){ cout<<"a() in A\n";}virtual void b(){ cout<<"b() in A\n";}virtual void f(){ cout<<"f() in A\n";}};class B:virtual  public base{public:virtual void a(){ cout<<"a() in B\n";}virtual void c(){ cout<<"c() in B\n";}};class C:public A,public B{public:virtual void a(){ cout<<"a() in C\n";}virtual void d(){ cout<<"d() in C\n";}};void main(void){      C cc;      base *pa=&cc;      pa->a();      pa->b();      pa->c();      pa->d();      pa->e();      pa->f();}814 a( )b( )c( )d( )e( )f( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )b( )c( )d( )e( )f( )a( )c( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )c( )baseABCa( )d( )AB815 class base{public:virtual void a(){ cout<<"a() in base\n";}virtual void b(){ cout<<"b() in base\n";}virtual void c(){ cout<<"c() in base\n";}virtual void d(){ cout<<"d() in base\n";}virtual void e(){ cout<<"e() in base\n";}virtual void f(){ cout<<"f() in base\n";}};class A:virtual public base{public:virtual void a(){ cout<<"a() in A\n";}virtual void b(){ cout<<"b() in A\n";}virtual void f(){ cout<<"f() in A\n";}};class B:virtual  public base{public:virtual void a(){ cout<<"a() in B\n";}virtual void c(){ cout<<"c() in B\n";}};class C:public A,public B{public:virtual void a(){ cout<<"a() in C\n";}virtual void d(){ cout<<"d() in C\n";}};void main(void){      C cc;      base *pa=&cc;      pa->a();      pa->b();      pa->c();      pa->d();      pa->e();      pa->f();}类类C中只有一个中只有一个basea() in Cb() in Ac() in Bd() in Ce() in basef() in A816 class base{public:void a(){cout<<"a() in base\n";}void b(){cout<<"b() in base\n";}void c(){cout<<"c() in base\n";}void d(){cout<<"d() in base\n";}void e(){cout<<"e() in base\n";}void f(){cout<<"f() in base\n";}};class A:virtual public base{public:void a(){cout<<"a() in A\n";}void b(){cout<<"b() in A\n";}void f(){cout<<"f() in A\n";}};class B:virtual  public base{public:void a(){cout<<"a() in B\n";}void c(){cout<<"c() in B\n";}};class C:public A,public B{public:void a(){cout<<"a() in C\n";}void d(){cout<<"d() in C\n";}};void main(void){      C cc;      base *pa=&cc;      pa->a();      pa->b();      pa->c();      pa->d();      pa->e();      pa->f();}类类C中只有一个中只有一个basea() in baseb() in basec() in based() in basee() in basef() in base817 下面程序的输出是下面程序的输出是          。

      class  A{protected:int x;public:A(){x =1000;}virtual void  p(){cout <<"x="<p();pa=&c;pa->p();}818          通通常常,,每每当当说说明明一一个个对对象象时时,,把把该该类类中中的的有有关关成成员员数数据据拷拷贝贝到到该该对对象象中中,,即即同同一一类类的的不不同同对对象象,,其其成成员员数数据据之间是互相独立的之间是互相独立的静态成员静态成员 class A{       int x,y;    public:       void Setxy(int a, int b)    {  x=a;   y=b;}};A   a1,  a2;a1.xa1.ya2.xa2.y......x=a ;y=b ;......a1. Setxy()a2. Setxy()a1.Setxy(1,2);a2.Setxy(3,4);this->x=a;this->y=b;819 当我们将类的某一个当我们将类的某一个数据成员的存储类型指定为静态类型数据成员的存储类型指定为静态类型时时,则由该类所产生的所有对象,其静态成员均共享,则由该类所产生的所有对象,其静态成员均共享一个一个存储空间存储空间,,这个空间是在编译的时候分配的这个空间是在编译的时候分配的。

      换言之,在换言之,在说明对象时,并不为静态类型的成员分配空间说明对象时,并不为静态类型的成员分配空间          在类定义中,用关键字在类定义中,用关键字static修饰的数据成员称为静修饰的数据成员称为静态数据成员态数据成员class A{     int x,y;  static  int z;    public:       void Setxy(int a, int b)    {  x=a;   y=b;}};A   a1,  a2;a1.xa1.ya2.xa2.yza1. za2. z不同对象,同一空间不同对象,同一空间820 有关静态数据成员的使用,说明以下几点:有关静态数据成员的使用,说明以下几点:1、、类类的的静静态态数数据据成成员员是是静静态态分分配配存存储储空空间间的的,,而而其其它它成成员员是是动动态态分分配配存存储储空空间间的的((全全局局变变量量除除外外))当当类类中中没没有有定定义义静静态态数数据据成成员员时时,,在在程程序序执执行行期期间间遇遇到到说说明明类类的的对对象象时时,,才才为为对对象象的的所所有有成成员员依依次次分分配配存存储储空空间间,,这这种种存存储储空空间间的的分分配配是是动动态态的的;;而而当当类类中中定定义义了了静静态态数数据据成成员员时时,,在在编编译译时时,,就就要要为为类类的的静态数据成员分配存储空间静态数据成员分配存储空间。

      821 2、、必须在文件作用域中,对静态数据成员作必须在文件作用域中,对静态数据成员作一次且只能作一次定义性说明一次且只能作一次定义性说明因为静态数因为静态数据成员在定义性说明时已分配了存储空间,据成员在定义性说明时已分配了存储空间,所以通过静态数据成员名前加上所以通过静态数据成员名前加上类名和作用类名和作用域运算符域运算符,可直接引用静态数据成员在,可直接引用静态数据成员在C++中,静态变量缺省的初值为中,静态变量缺省的初值为0,所以静态,所以静态数据成员总有唯一的初值当然,数据成员总有唯一的初值当然,在对静态在对静态数据成员作定义性的说明时,数据成员作定义性的说明时,也可以指定一也可以指定一个初值822 class  A{int  i,j;static int x,y;//定义静态成员定义静态成员public: A(int a=0,int b=0,int c=0, int d=0){i=a;j=b;x=c;y=d;}void Show(){cout << "i="<

      静态数据成员与全局变量一样都是静态分配特性静态数据成员与全局变量一样都是静态分配存储空间的,存储空间的,但全局变量在程序中的任何位置都可但全局变量在程序中的任何位置都可以访问它,而静态数据成员受到访问权限的约束以访问它,而静态数据成员受到访问权限的约束必须是必须是public权限时,才可能在类外进行访问权限时,才可能在类外进行访问4、为了保持静态数据成员取值的一致性,通常在、为了保持静态数据成员取值的一致性,通常在构造函数中不给静态数据成员置初值,构造函数中不给静态数据成员置初值,而是在对静而是在对静态数据成员的定义性说明时指定初值态数据成员的定义性说明时指定初值 825 class  A{int  i;static int count;public:A(int a=0){    i=a; count++;  cout <<"Number of Objects="<

      即使可以将类的成员函数定义为静态的成员函数即使用关键字用关键字static来修饰成员函数来修饰成员函数 class A {    float x, y;public :     A( ){  }     static   void sum(void)  { ..... }};827 对静态成员函数的用法说明以下几点:对静态成员函数的用法说明以下几点:1、、与静态数据成员一样,在类外的程序代码中,与静态数据成员一样,在类外的程序代码中,通过类名加上作用域操作符,可直接调用静态成员通过类名加上作用域操作符,可直接调用静态成员函数函数 2、、静态成员函数只能直接使用本类的静态数据成静态成员函数只能直接使用本类的静态数据成员或静态成员函数员或静态成员函数,,但不能直接使用非静态的数据但不能直接使用非静态的数据成员成员 (可以引用使用)这是因为静态成员函数(可以引用使用)这是因为静态成员函数可被其它程序代码直接调用,所以,可被其它程序代码直接调用,所以,它不包含对象它不包含对象地址的地址的this指针指针 828 class Tc {private:int A;static int B;//静态数据成员静态数据成员public:Tc(int a){A=a;  B+=a;}static void display(Tc  c)//Tc的对象为形参的对象为形参{        cout<<"A="<

      这这是是由由于于关关键键字字static不不是是数数据据类类型型的的组组成成部部分分,因因此此,,在在类类外外定定义义静静态态成员函数的实现部分时成员函数的实现部分时,不能使用这个关键字不能使用这个关键字4、、不不能能把把静静态态成成员员函函数数定定义义为为虚虚函函数数静静态态成成员员函函数数也也是是在在编编译译时时分分配配存存储储空空间间,,所所以以在在程程序序的的执执行过程中不能提供多态性行过程中不能提供多态性5、、可可将将静静态态成成员员函函数数定定义义为为内内联联的的((inline)),,其其定义方法与非静态成员函数完全相同定义方法与非静态成员函数完全相同830 class Tc {private:int A;static int B;//静态数据成员静态数据成员public:Tc(int a){A=a;  B+=a;}static void display(Tc  c);;//Tc的对象为形参的对象为形参};void  Tc::display(Tc  c)//不用不用static修饰修饰        {        cout<<"A="<

       #includeclass Sample{public:Sample(){ cout<<"Constructor"<

      C++通过重新定义运算符,使它通过重新定义运算符,使它能够用于特定类的对象执行特定的功能能够用于特定类的对象执行特定的功能846 运算符的重载从另一个方面体现了运算符的重载从另一个方面体现了OOP技术的多技术的多态性,态性,且同一运算符根据不同的运算对象可以完且同一运算符根据不同的运算对象可以完成不同的操作成不同的操作        为了重载运算符,必须定义一个函数,并告为了重载运算符,必须定义一个函数,并告诉编译器,诉编译器,遇到这个重载运算符就调用该函数,遇到这个重载运算符就调用该函数,由这个函数来完成该运算符应该完成的操作由这个函数来完成该运算符应该完成的操作这这种函数称为运算符重载函数,它通常是种函数称为运算符重载函数,它通常是类的成员类的成员函数或者是友元函数函数或者是友元函数运算符的操作数通常也应运算符的操作数通常也应该是类的对象该是类的对象847 重载为类的重载为类的成员函数成员函数格式如下:格式如下:<类名类名>  operator<运算符运算符>(<参数表参数表>){函数体函数体}A  operator +  (A &);//重载了类重载了类A的的“+”运算运算符符其中:其中:operator是定义运算符重载函数的关键字,是定义运算符重载函数的关键字,它与其后的运算符一起构成函数名。

      它与其后的运算符一起构成函数名返回类型返回类型运算的对象运算的对象关键字关键字函数名函数名运算的对象运算的对象848 class A{int i;public:A(int a=0){ i=a; }void Show(void){cout<<"i="<

      最后将函数返回值赋给最后将函数返回值赋给运算结果的对象运算结果的对象852 class A{int i;public:A(int a=0){ i=a;}void Show(void){cout<<"i="<

      对对于于只只有有一一个个操操作作数数的的运运算算符符(如如++),,在在重重载载这这种种运运算算符符时时,,通通常常不不能能有有参参数数;;而而对对于于有有二二个个操操作作数数的的运运算算符符,,只只能能带带有有一一个个参参数数这这参参数数可可以以是是对对象象,,对对象象的的引引用用,,或或其其它它类类型型的的参参数数在在C++中中不不允许重载有三个操作数的运算符允许重载有三个操作数的运算符854 2、、在在C++中中,允允许许重重载载的的运运算算符符列列于于表表13.1中3、在、在C++中不允许重载的运算符列于中不允许重载的运算符列于表表13.24、、只只能能对对C++中中已已定定义义了了的的运运算算符符进进行行重重载载,,而而且且,,当当重重载载一一个个运运算算符符时时,,该该运运算算符符的的优优先级和结合律是不能改变的先级和结合律是不能改变的855 class room{float Length;float Wide;public: room(float a=0.0,float b=0.0){   Length=a;    Wide=b; }   void Show(void){cout<<"Length="<

      格式为:格式为:<函数类型函数类型>   ::operator=(<参数表参数表>)赋值运算符必须重载为成员函数赋值运算符必须重载为成员函数A  A:: operator = (A  &a)函数返回值类型函数返回值类型成员函数作用域成员函数作用域函数名函数名函数参数函数参数b=a;b.operator=(a);左操作符调左操作符调用右操作符用右操作符881 class Sample{int x;public: Sample(int i=0){x=i;}void disp(void){  cout<<“x=“<

      返回同种类型的引用适合于连等s3=s2=s1;884 class  A{char *ps;public: A( ){ ps=0;}A(char *s ){ps =new char [strlen(s)+1];strcpy(ps,s);}~A( ){ if (ps) delete ps;}char *GetS( ) {return ps;}A &   operator  = (  A  &b);//重载赋值运算符重载赋值运算符};A &A::operator  = (  A  &b)//重载赋值运算符重载赋值运算符{    if  ( ps )  delete  [ ] ps;      if  ( b.ps) {ps = new  char [ strlen(b.ps)+1];strcpy( ps, b.ps);}      else  ps =0;     return *this;}void  main(void ){A s1("China!"),s2("Computer!");s2=s1;cout <<"s1= "<< s1.GetS()<<'\t';cout <<"s2= "<< s2.GetS()<<'\n';}s2.ps重新开辟内存,存放重新开辟内存,存放“China”重新开辟内存重新开辟内存885 一个字符串类一个字符串类在在C++中中,,系系统统提提供供的的字字符符串串处处理理能能力力比比较较弱弱,,都都是是通通过过字字符符处处理理函函数数来来实实现现的的,,并并且且不不能能直直接接对对字字符符串串进进行行加加法法、、减减法法,,字字符符串串的的拼拼接接,,字字符符串串之之间间的的相相互互赋赋值值等等操操作作。

      可可以以通通过过应应用用C++提提供供的的运运算算符符重重载载机机制制,,可可以以提提供供字字符符串串的的直直接接操操作作能能力力,,使使得得字字符符串串的操作与一般的数据一样方便的操作与一般的数据一样方便886 class String{     int Length;//字符串长度字符串长度      char *Sp;  //字符串在内存中的首地址字符串在内存中的首地址 public:       .....}可见,字符串类只定义了指针,并没有开辟具体的可见,字符串类只定义了指针,并没有开辟具体的空间以存放字符串的内容,所以,无论是构造、析空间以存放字符串的内容,所以,无论是构造、析构还是加减等,构还是加减等,均需要考虑动态开辟空间的问题均需要考虑动态开辟空间的问题,,这也是字符串类的难点这也是字符串类的难点887 class  String{int Length;//字符串的长度字符串的长度 char  *Sp;//指向字符串的指针指向字符串的指针public: String(){Sp=0;Length=0;}//缺省的构造函数缺省的构造函数String( char *s)//以一个字符串常量作为参数以一个字符串常量作为参数{Length = strlen(s);Sp=new char[Length+1];strcpy(Sp,s);}~String(){  if(Sp) delete [  ] Sp;  }friend String operator +(String &,String &);//友元函数重载+友元函数重载+String & operator =(String &);//成员函数重载赋值=成员函数重载赋值=              String  (String &s);  //拷贝的构造函数拷贝的构造函数(必须有必须有)};void main(void){String str1("China");String str2("CCTV");String str3;str3=str1+str2;str2=str1;cout<

      员函数原则:每个对象都有自己的独立空间原则:每个对象都有自己的独立空间890 第十四章第十四章       输入输入/输出流类库输出流类库 891 编译系统已经以编译系统已经以运算符或函数运算符或函数的形式做好了对标准的形式做好了对标准外设外设(键盘、屏幕、打印机、(键盘、屏幕、打印机、文件文件))的接口,使用的接口,使用时只需按照要求的格式调用即可时只需按照要求的格式调用即可cin>>x;   cout<

      数据类型的转换对于输入流,要将输入的对于输入流,要将输入的字符序列形式的数据变换成计算机内部形式字符序列形式的数据变换成计算机内部形式的数据(二进制或的数据(二进制或ASCII)后,再赋给变量,)后,再赋给变量,变换后的格式由变量的类型确定变换后的格式由变量的类型确定对于输出对于输出流,将要输出的数据变换成字符串形式后,流,将要输出的数据变换成字符串形式后,送到输出流(文件)中送到输出流(文件)中 894 重载输入重载输入(提取提取)和输出和输出(插入插入)运算符运算符class A{ float x, y;public:   A(float a=0, float b=0){  x=a;  y=b;  }   void Set(float a, float b){ x=a; y=b; }   void  Show(void){  cout<>a;cout<>”,,实实现现对对象象的的输输入入和和输输出出。

      重重载载这这二二个个运运算算符符时时,,在在对对象象所所在在的的类类中中,,将将重重载载这这二二个个运运算算符符的的函函数数说说明明该该类的类的友元函数友元函数重载提取运算符的一般格式为:重载提取运算符的一般格式为:友元函数友元函数friend  istream &  operater >>(istream &, ClassName &);返回值类型返回值类型函数名函数名左操作数左操作数右操作数右操作数cin>>a;operator>>(cin,  a)896 友元函数友元函数friend  istream &  operater >>(istream &, ClassName &);返回值类型返回值类型函数名函数名左操作数左操作数右操作数右操作数cin>>a;operator>>(cin,  a)返回值类型:返回值类型:类类istream的引用,的引用,cin中可以连续使用运算中可以连续使用运算符符“>>”cin>>a>>b;第一个参数:是第一个参数:是“>>”的左操作数的左操作数cin类型类型,类类istream的引的引用用第二个参数:是第二个参数:是“>>”的右操作数的右操作数,即欲输入的对象的引即欲输入的对象的引用用.istream &  operater >>(istream &is, ClassName &f);897 class A{    float x, y;  public:     ..... };    .....      A  a;   cin>>a;     ....friend  istream &  operater >>(istream &, A &);istream &  operater >>(istream &is, A &a){    cout<<“ Input a:”<>a.x>>a.y;        return  is;}重新定义输入流重新定义输入流在类中原型说明在类中原型说明在类外定义函数在类外定义函数返回输入流返回输入流898 class incount{int c1,c2;public:incount(int a=0,int b=0){c1=a; c2=b; }   void show(void){cout<<"c1="<>(istream &,incount &);};istream & operator>>(istream &is,  incount &cc){is>>cc.c1>>cc.c2;return is;}void main(void){incount x1,x2;x1.show ();x2.show ();cin>>x1;cin>>x2;x1.show ();x2.show ();}重载输入函数原型说明重载输入函数原型说明重载输入函数定义重载输入函数定义899 友元函数友元函数friend  ostream &  operater <<(ostream &, ClassName &);返回值类型返回值类型函数名函数名左操作数左操作数右操作数右操作数cout<>(istream &, ClassName &);将输入流改为输出流。

      将输入流改为输出流900 class A{    float x, y;  public:     ..... };    .....      A  a(2,3);   cout<>filename1;cout<<"Input destination:  ";cin>>filename2;ifstream infile(filename1);ofstream outfile(filename2);char ch;while(infile.get(ch))outfile.put(ch);infile.close();outfile.close();}输入文件输入文件(源文件源文件)名名输出文件输出文件(目的文件目的文件)名名用构造函数打开文件用构造函数打开文件从源文件中读取一个字从源文件中读取一个字符,至文件尾停止循环符,至文件尾停止循环将该字符输出至目的文件将该字符输出至目的文件关闭文件关闭文件919 void main(void){char filename1[256],filename2[256];char buf[300];cout<<"Input source file name:  ";cin>>filename1;cout<<"Input destination:  ";cin>>filename2;fstream infile,outfile;infile.open(filename1,ios::in);outfile.open(filename2,ios::out);while(infile.getline(buf,300))outfile<

      fstream   infile,outfile;infile.open(“inf1.dat”,  ios::in| ios::binary);outfile.open(“outf1.dat”,  ios::out| ios::binary); 文件名文件名 输入方式打开输入方式打开 二进制文件二进制文件 文件名文件名 输出方式打开输出方式打开 二进制文件二进制文件921 输入函数:输入函数:infile.read( char  *,   int )输入文件输入文件对象名对象名 数据进入的内存地址数据进入的内存地址 一次读入的字节数一次读入的字节数文件文件内存内存int  a[10];infile.read((char *)a,  10*sizeof(int));//从文件中输入十个整型数到从文件中输入十个整型数到aint  i;infile.read((char *)&i, sizeof(int));//从文件中输入一个整型数到从文件中输入一个整型数到i由于二进制文件中的数据不是由于二进制文件中的数据不是ASCII码,故不能直接对码,故不能直接对其读写,其读写,必须要通过特定的函数予以转换。

      必须要通过特定的函数予以转换读入读入地址要强制转换成字符型地址要强制转换成字符型922 输出函数:输出函数:outfile.write( char  *,   int )输出文件输出文件对象名对象名 要输出的数据在内存中的地址要输出的数据在内存中的地址 一次输出的字节数一次输出的字节数文件文件内存内存int  a[10]={0,1,2,3,4,5,6,7,8,9};outfile.write((char *)a,  10*sizeof(int));//向文件输出一个整型数组向文件输出一个整型数组aint  i=4;outfile.write((char *)&i, sizeof(int));//向文件输出一个整型数向文件输出一个整型数i写出写出地址要强制转换成字符型地址要强制转换成字符型923 判断二进制文件是否读到文件尾?判断二进制文件是否读到文件尾?infile.eof( )    当到达文件结束位置时,该函数返回一个非零值;当到达文件结束位置时,该函数返回一个非零值;否则否则返回零fstream   infile;infile.open(“data1.dat”,ios::in|ios::binary);if(!infile){   cout<<“Open Error!\n”;  exit(1);  }char  str[300];while(!infile.eof())     infile.read(str, 300); 判断打开是否出错判断打开是否出错 判断是否读到文件尾判断是否读到文件尾924 void  main(void ){char  filename1[256],filename2[256];char  buff[4096];cout <<”输入源文件名输入源文件名:”;   cin  >>filename1;cout <<”输入目的文件名输入目的文件名:”;  cin  >>filename2;fstream  infile,outfile;infile.open(filename1,ios::in | ios::binary);outfile.open(filename2,ios::out | ios::binary);int n;while (!infile.eof()){//文件不结束,继续循环文件不结束,继续循环infile.read(buff,4096);//一次读一次读4096个字节个字节n=infile.gcount();//取实际读的字节数取实际读的字节数outfile.write(buff,n);//按实际读的字节数写入文件按实际读的字节数写入文件}infile.close();outfile.close();} 925 文件指针文件指针文件内容文件内容文件指针文件指针当一打开文件,文件指针位于文件头,并随着读写当一打开文件,文件指针位于文件头,并随着读写字节数的多少顺序移动。

      字节数的多少顺序移动可以利用成员函数随机移动文件指针可以利用成员函数随机移动文件指针926 随机读取二进制文件随机读取二进制文件infile.seekg(int);//将文件指针移动到由参数指定的字节处将文件指针移动到由参数指定的字节处infile.seekg(100);//将文件指针移动到距离文件头将文件指针移动到距离文件头100个字个字节处节处infile.seekg(int, ios::_dir); 移动的字节数移动的字节数 相对位置相对位置infile.seekg(100, ios::beg);//移动到距文件头移动到距文件头100个字节个字节_dir:    beg:  文件头文件头cur:  当前位置当前位置end:  文件尾文件尾infile.seekg(-100, ios::cur);//移动到距当前位置前移动到距当前位置前100个字节个字节infile.seekg(-500, ios::end);//移动到距文件尾前移动到距文件尾前500个字节个字节927 void  main(void ){  ofstream  outfile(“data1.dat”,ios::out| ios::binary);     int  i;    for(i=5;i< 1000;i+=2 )outfile.write((char*)&i,sizeof(int));//将奇数写入文件将奇数写入文件     outfile.close();//关闭文件关闭文件     ifstream  f1(“data.dat”,ios::in| ios::binary);          int x;   f1.seekg(20*sizeof(int));//将文件指针移到第将文件指针移到第20个整数的位置个整数的位置   for(i=0;i<10;i++)   {f1.read((char *)&x,sizeof(int)); //依次读出第依次读出第20~29个奇数到个奇数到x               cout<< x<< ‘\t’;    }    f1.close();}以读的方式打开原文件以读的方式打开原文件928    设在缺省目录下有文件设在缺省目录下有文件file1.txt,文件中内容为:,文件中内容为:123456执行下述程序后,程序的输出是执行下述程序后,程序的输出是__________。

      void main(void){fstream f1;int tmp, sum=0;f1.open(“file1.txt”,ios::in);while(f1>>tmp)sum+=tmp;f1.close( );cout<

      点击阅读更多内容
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.