CVC实验C课件19章

上传人:壹****1 文档编号:578349504 上传时间:2024-08-24 格式:PPT 页数:739 大小:2.94MB
返回 下载 相关 举报
CVC实验C课件19章_第1页
第1页 / 共739页
CVC实验C课件19章_第2页
第2页 / 共739页
CVC实验C课件19章_第3页
第3页 / 共739页
CVC实验C课件19章_第4页
第4页 / 共739页
CVC实验C课件19章_第5页
第5页 / 共739页
点击查看更多>>
资源描述

《CVC实验C课件19章》由会员分享,可在线阅读,更多相关《CVC实验C课件19章(739页珍藏版)》请在金锄头文库上搜索。

1、程序设计的思想与方法程序设计的思想与方法张冬茉张冬茉Email:zhangdm程序设计 cs.sjtu 2005.9程序设计-2课前的话课前的话v本课程的重要性本课程的重要性v程序设计学习要点程序设计学习要点实践性强实践性强按照计算机的方式去思维按照计算机的方式去思维v大学的学习生活大学的学习生活程序设计 cs.sjtu 2005.9程序设计-3课程内容课程内容v计算科学导论计算科学导论v结构化的程序设计结构化的程序设计v成绩组成:成绩组成:实践教学实践教学30%期末考试期末考试70%程序设计 cs.sjtu 2005.9程序设计-4实践教学实践教学v在电院机房。地址:电信群楼在电院机房。地址

2、:电信群楼4号楼号楼311v内容:每次完成一个程序内容:每次完成一个程序程序设计 cs.sjtu 2005.9程序设计-5作业的相关规定及本卷须知作业的相关规定及本卷须知v本学期将布置本学期将布置5个作业,在课后独立完成个作业,在课后独立完成v助教每周有两个晚上在机房答疑助教每周有两个晚上在机房答疑v作业要求:作业要求:v必须独立、按时地完成每次上机作业必须独立、按时地完成每次上机作业v每次上机作业的具体要求参见每次作业的文档说每次上机作业的具体要求参见每次作业的文档说明明v上传的作业必须符合下述的上传的作业必须符合下述的“上传作业命名规那上传作业命名规那么么v作业上传地址:作业上传地址:v用

3、户码用户码/密码:密码:sjtu/sjtu程序设计 cs.sjtu 2005.9程序设计-6作业命名规那么作业命名规那么1.使用使用WinRAR软件将上机作业包括工程文件、资源文件、源文件和软件将上机作业包括工程文件、资源文件、源文件和头文件等的多个文件直接压缩为一个压缩文件,该压缩文件必须命名头文件等的多个文件直接压缩为一个压缩文件,该压缩文件必须命名为:为:学号学号_作业号作业号.rar。2.假设一次作业中包含多个小题,那么每个小题应分别放入一个单独文件假设一次作业中包含多个小题,那么每个小题应分别放入一个单独文件夹,多个文件夹直接压缩为一个压缩文件。其中,每个小题的文件夹应夹,多个文件夹

4、直接压缩为一个压缩文件。其中,每个小题的文件夹应命名为:命名为:学号学号_作业号作业号_题号;题号;3.上传的作业中应该不包括上传的作业中应该不包括Debug文件夹以及某些声音、图像文件文件夹以及某些声音、图像文件4.命名规那么例如:命名规那么例如:5.以学号为以学号为5030309999,上传第四次作业第四次作业中含有两个独立的,上传第四次作业第四次作业中含有两个独立的小作业为例:小作业为例:6.两个小作业的文件夹名字应为:两个小作业的文件夹名字应为:5030309999_4_1和和5030309999_4_27.压缩文件名应为:压缩文件名应为:程序设计 cs.sjtu 2005.9程序设计

5、-7评分标准评分标准u“完成截止日期后、完成截止日期后、“上传截止日期前仍可上传截止日期前仍可上传作业,但视为上传作业,但视为“迟交,迟交的作业将被扣迟交,迟交的作业将被扣除一定的分数。除一定的分数。在在“上传截止日期后,将停止该次作业批改。上传截止日期后,将停止该次作业批改。u一经发现作业抄袭情况,无论任何原因,抄袭一经发现作业抄袭情况,无论任何原因,抄袭者与被抄袭者的当次作业一律记为者与被抄袭者的当次作业一律记为0分分程序设计 cs.sjtu 2005.9程序设计-8教材参考教材教材参考教材vC+程序设计思想与方法程序设计思想与方法v人民邮电出版社人民邮电出版社翁惠玉翁惠玉vC程序设计第程

6、序设计第3版版谭浩强谭浩强v程序设计根底第程序设计根底第2版版吴文虎吴文虎清华大学出版社清华大学出版社vC语言的科学和艺术语言的科学和艺术EricS.Roberts机械工业出机械工业出版社版社v计算机科学概论计算机科学概论NellDale等等机械工业出版社机械工业出版社程序设计 cs.sjtu 2005.9程序设计-9第1章 计算机简介v计算机的组成计算机的组成v计算机的开展计算机的开展v信息的表示信息的表示v程序设计程序设计vC C和和C+C+v上机准备上机准备程序设计 cs.sjtu 2005.9程序设计-10计算机的组成计算机的组成v硬件:计算机的躯壳硬件:计算机的躯壳v软件:计算机的灵

7、魂软件:计算机的灵魂计算机,也被称之为计算机,也被称之为“电脑,是一种能够按照事先电脑,是一种能够按照事先存储的程序自动、高效地对数据进行输入、处理、存存储的程序自动、高效地对数据进行输入、处理、存储和输出的系统储和输出的系统程序设计 cs.sjtu 2005.9程序设计-11计算机硬件存储器存储器输入设备输入设备输出设备输出设备控制器控制器运算器运算器CPU程序设计 cs.sjtu 2005.9程序设计-12存储器v保存正在运行的程序代码和数据保存正在运行的程序代码和数据v内存的最小单元是内存的最小单元是bitbit,一个,一个bitbit存储一个二进存储一个二进制位。一般制位。一般8 8个

8、个bitbit组成一个组成一个bytebyte,假设干个,假设干个bytebyte组成一个组成一个wordwordv在一般的机器中,内存按字节编址,内存大小在一般的机器中,内存按字节编址,内存大小也是按字节计量也是按字节计量v关机后,内存的数据全部丧失关机后,内存的数据全部丧失程序设计 cs.sjtu 2005.9程序设计-13CPUCPU(CentralProcessingUnit)有两个有两个部件组成:部件组成:ALUArithmeticLogicUnit运算器运算器Controlunit控制器控制器程序设计 cs.sjtu 2005.9程序设计-14控制器v控制器控制计算机的其余局部如何

9、完成控制器控制计算机的其余局部如何完成程序的指令程序的指令v指挥内存和其它部件之间的信息的传送指挥内存和其它部件之间的信息的传送包括信息和指令包括信息和指令v指挥指挥CPU和输入输出设备之间的控制信和输入输出设备之间的控制信息的传送息的传送程序设计 cs.sjtu 2005.9程序设计-15控制器中的信息存储v控制器中有两个存放器:控制器中有两个存放器:v指令存放器指令存放器(IR):保存当前正在执行的:保存当前正在执行的指令指令v程序计数器程序计数器(PC):保存下一条要执行:保存下一条要执行的指令地址的指令地址程序设计 cs.sjtu 2005.9程序设计-16控制器的工作v取下一条指令:

10、按取下一条指令:按PCPC指定的地址到内存指定的地址到内存中取出下一条指令,存入中取出下一条指令,存入IRIR。v解码指令:将指令解码成一系列的控制解码指令:将指令解码成一系列的控制信号信号v执行指令:将控制信号发送给相关部件,执行指令:将控制信号发送给相关部件,执行相应的运算执行相应的运算程序设计 cs.sjtu 2005.9程序设计-17运算器的组成v逻辑电路:执行控制器发出的控制信号逻辑电路:执行控制器发出的控制信号v一组存放正在运算的数据的存放器一组存放正在运算的数据的存放器程序设计 cs.sjtu 2005.9程序设计-18输入输出设备输入输出设备v输入设备将人能理解的符号转换成计算

11、输入设备将人能理解的符号转换成计算机能处理的符号。常用的输入设备有:机能处理的符号。常用的输入设备有:键盘、鼠标、光笔等键盘、鼠标、光笔等v输出设备将计算机的输出转换成人能理输出设备将计算机的输出转换成人能理解的输出。常用的输出设备有:显示器、解的输出。常用的输出设备有:显示器、打印机、音响设备等打印机、音响设备等程序设计 cs.sjtu 2005.9程序设计-19计算机的组成计算机的组成计算机,也被称之为计算机,也被称之为“电脑,是一种能够按照事先电脑,是一种能够按照事先存储的程序自动、高效地对数据进行输入、处理、存存储的程序自动、高效地对数据进行输入、处理、存储和输出的系统储和输出的系统v

12、硬件:计算机的躯壳硬件:计算机的躯壳v软件:计算机的灵魂软件:计算机的灵魂程序设计 cs.sjtu 2005.9程序设计-20计算机软件计算机软件v软件可以分为系统软件和应用软件。软件可以分为系统软件和应用软件。v系统软件居于计算机系统中最靠硬件的局部,系统软件居于计算机系统中最靠硬件的局部,它将计算机的用户与硬件隔离。系统软件与具它将计算机的用户与硬件隔离。系统软件与具体的应用无关,但其他的软件要通过系统软件体的应用无关,但其他的软件要通过系统软件才能发挥作用。常用的系统软件有操作系统、才能发挥作用。常用的系统软件有操作系统、编译器、网络软件等。编译器、网络软件等。v应用软件是为了支持某一应

13、用而开发的软件。应用软件是为了支持某一应用而开发的软件。如字处理软件、财务软件等。如字处理软件、财务软件等。程序设计 cs.sjtu 2005.9程序设计-21第1章 计算机简介v计算机的组成计算机的组成v计算机的开展计算机的开展v信息的表示信息的表示v程序设计程序设计vC C和和C+C+v上机准备上机准备程序设计 cs.sjtu 2005.9程序设计-22计算机的开展计算机的开展u1946ENIAC:第一台全电子的计算机,由第一台全电子的计算机,由JohnMauchly和和JohnEckert设计设计uENIAC的特点:的特点:u真空管真空管u无程序存储无程序存储u采用十进制采用十进制程序设

14、计 cs.sjtu 2005.9程序设计-23Von Neumann和EDVACv1946VonNeumann对对ENIAC进行了改进,进行了改进,设计了设计了EDVACvEDVAC的主要特征的主要特征:v采用二进制技术采用二进制技术v存储指令存储指令程序设计 cs.sjtu 2005.9程序设计-24第一代计算机1950v基于真空管技术基于真空管技术v典型产品有典型产品有1951生产生产的的UNIVACI,由,由MauchlyandEckert设计设计v第一代机的特点:第一代机的特点:无操作系统无操作系统采用机器指令或汇编采用机器指令或汇编语言语言程序设计 cs.sjtu 2005.9程序设

15、计-25第二代计算机50末到60初v采用真空管技术采用真空管技术v特点:特点:v更可靠、更廉价更可靠、更廉价v出现了程序设计语言出现了程序设计语言v出现了简单的操作系统:批处理系统出现了简单的操作系统:批处理系统vIBM7000series,DECPDP8程序设计 cs.sjtu 2005.9程序设计-26第三代计算机60末到80初v采用集成电路技术采用集成电路技术v特点:特点:v价格更廉价价格更廉价v高集成度高集成度v出现了分时系统出现了分时系统vIBM360series(1964)程序设计 cs.sjtu 2005.9程序设计-27第四代计算机v采用采用LSI/VLSI技术技术v特点:特点

16、:体积更小、价格更低、内存扩大体积更小、价格更低、内存扩大有完善的操作系统有完善的操作系统程序设计 cs.sjtu 2005.9程序设计-28第1章 计算机简介v计算机的组成计算机的组成v计算机的开展计算机的开展v信息的表示信息的表示v程序设计程序设计vC C和和C+C+v上机准备上机准备程序设计 cs.sjtu 2005.9程序设计-29以二进制表示数据v文本信息文本信息v声音声音v图象图象v整型数整型数v实型数实型数程序设计 cs.sjtu 2005.9程序设计-30英文文本信息的表示英文文本信息的表示vASCIIAmericanStandardCodeforInformationInte

17、rchange.常用于微型机中。常用于微型机中。vEBCDICExtendedBinaryCodedDecimalInterchangeCode.常用于某些大型机中。常用于某些大型机中。vUnicode16bitcodedesignedtosupportinternationallanguageslikeChineseandJapanese.将每一个符号用一个二进制比特串来表示将每一个符号用一个二进制比特串来表示程序设计 cs.sjtu 2005.9程序设计-31英文字符的输入输出v由于英文是小字符集,可以将每一个字由于英文是小字符集,可以将每一个字符做成键盘上的一个键,也可以将每一符做成键盘

18、上的一个键,也可以将每一个字符的形状存储在输出设备上。个字符的形状存储在输出设备上。程序设计 cs.sjtu 2005.9程序设计-32英文字符的输入程序设计 cs.sjtu 2005.9程序设计-33英文字符的输出v每个字符内码对应了一个表示该字母的每个字符内码对应了一个表示该字母的点阵。当显示器收到此内码时,就输出点阵。当显示器收到此内码时,就输出相应的点阵相应的点阵程序设计 cs.sjtu 2005.9程序设计-34汉字编码汉字编码v汉字输入码:有输入设备产生的汉字编汉字输入码:有输入设备产生的汉字编码。如拼音、五笔等。码。如拼音、五笔等。v汉字内码:常用的是国标码,用两个汉字内码:常用

19、的是国标码,用两个7 7位位的二进制数表示,用的二进制数表示,用2 2个字节表示。个字节表示。v汉字字型码:确定一个汉字字型点阵的汉字字型码:确定一个汉字字型点阵的编码,用于输出或打印编码,用于输出或打印汉字属于大字符集,不能采用每键一字的方法。汉字属于大字符集,不能采用每键一字的方法。只能利用现有的小键盘。只能利用现有的小键盘。程序设计 cs.sjtu 2005.9程序设计-35以二进制表示数据v文本信息文本信息v声音声音v图象图象v整型数整型数v实型数实型数程序设计 cs.sjtu 2005.9程序设计-36数字音频v音频是一维的声波,属于模拟数据音频是一维的声波,属于模拟数据v音频数字化

20、:采样、量化、编码音频数字化:采样、量化、编码程序设计 cs.sjtu 2005.9程序设计-37采样、量化和编码ABCDEFGHt256192128640ABCDEFGH188244240144807212220010111100 11110100 11110000 10010000 01010000 01001000 01111100 11001000程序设计 cs.sjtu 2005.9程序设计-38音频CD 每秒每秒 44100 44100 次采样,每个采样值量次采样,每个采样值量化为化为 16 16 位,因此每秒钟非立体声需位,因此每秒钟非立体声需要要705.6 Kbit705.6

21、Kbit的存储空间,立体声需的存储空间,立体声需要要 1.411 Mbit1.411 Mbit的存储空间的存储空间程序设计 cs.sjtu 2005.9程序设计-39以二进制表示数据v文本信息文本信息v声音声音v图象图象v整型数整型数v实型数实型数程序设计 cs.sjtu 2005.9程序设计-40图像和图形v数字图像的表示:用像素数字图像的表示:用像素(pixel)(pixel)表示,表示,像素越多,质量越好。黑白图像的像素需像素越多,质量越好。黑白图像的像素需要一个要一个bitbit表示。如表示。如1 1表示白,表示白,0 0表示黑。表示黑。如需要表示灰度和彩色,那么需要多于如需要表示灰度

22、和彩色,那么需要多于1 1个个bitbit。每个像素占用的。每个像素占用的bitbit越多,图像质越多,图像质量越好。量越好。v分辨率:图象中的像素数分辨率:图象中的像素数程序设计 cs.sjtu 2005.9程序设计-41数字视频v由一系列帧组成,每个帧由像素组成。由一系列帧组成,每个帧由像素组成。v连续的视频至少用每秒连续的视频至少用每秒 25 25 帧表示帧表示v每秒的信息量每秒的信息量 = = 每秒的帧数每秒的帧数 * * 每帧的每帧的bitbit数数 = 25= 25帧帧 * * 1024 * 768 * 24bit 1024 * 768 * 24bit =472Mbps =472M

23、bps程序设计 cs.sjtu 2005.9程序设计-42以二进制表示数据v文本信息文本信息v声音声音v图象图象v整型数整型数v实型数实型数程序设计 cs.sjtu 2005.9程序设计-43整型数的表示整型数的表示码制码制v讨论如何将符号位数字化。讨论如何将符号位数字化。0 0表示正数,表示正数,1 1表示负数。数字的三种编码方式为:表示负数。数字的三种编码方式为: 原码原码 反码反码 补码补码程序设计 cs.sjtu 2005.9程序设计-44原码原码v用符号位和数值表示带符号数。正数的用符号位和数值表示带符号数。正数的符号位为符号位为0 0,负数的符号位为,负数的符号位为1 1。数值局。

24、数值局部用二进制表示。如用一个字节表示数部用二进制表示。如用一个字节表示数值:值:v 62 62原原=0 0111110=0 0111110v -62 -62原原=1 0111110=1 0111110程序设计 cs.sjtu 2005.9程序设计-45反码反码v正数的反码与原码相同,负数的反码为正数的反码与原码相同,负数的反码为该数的绝对值的原码取反。如:该数的绝对值的原码取反。如: 6262反反=0 0111110=0 0111110 -62 -62反反=1 1000001=1 1000001程序设计 cs.sjtu 2005.9程序设计-46补码补码v正数的补码与原码相同,负数的补码为正

25、数的补码与原码相同,负数的补码为该数的反码加该数的反码加1 1。如:。如: 6262补补=0 0111110=0 0111110 -62 -62补补=1 1000010=1 1000010v大多数计算机系统都用补码表示整数大多数计算机系统都用补码表示整数程序设计 cs.sjtu 2005.9程序设计-47以二进制表示数据v文本信息文本信息v声音声音v图象图象v整型数整型数v实型数实型数程序设计 cs.sjtu 2005.9程序设计-48实型数的表示实型数的表示v定点表示:小数点的位置固定不变定点表示:小数点的位置固定不变v浮点表示:小数点位置不固定。一个浮点数浮点表示:小数点位置不固定。一个浮

26、点数分成尾数和阶码两局部。阶码表示小数点在分成尾数和阶码两局部。阶码表示小数点在该数中的位数,尾数表示数的有效数值。如该数中的位数,尾数表示数的有效数值。如十进制数,其浮点表示可为:十进制数,其浮点表示可为:v N = 246135 * 10-3 = 2461350 * 10-4 N = 246135 * 10-3 = 2461350 * 10-4v = 0.246135 * 103 = 0.0246135 = 0.246135 * 103 = 0.0246135 * 104* 104程序设计 cs.sjtu 2005.9程序设计-49浮点数的存储浮点数的存储v阶码一般采用补码形式的二进制表示

27、。尾阶码一般采用补码形式的二进制表示。尾数通常采用原码形式的二进制表示。数通常采用原码形式的二进制表示。v当字长一定时,分配给阶码的位数越多,当字长一定时,分配给阶码的位数越多,表示数的范围越大,但分配给尾数的位数表示数的范围越大,但分配给尾数的位数将减少,从而降低数的精度。将减少,从而降低数的精度。符号位阶码尾数程序设计 cs.sjtu 2005.9程序设计-50浮点数的存储浮点数的存储v如用一个字节表示浮点数:如用一个字节表示浮点数:1 1位符号位,位符号位,3 3位阶码,位阶码,4 4位尾数。表示二进制数为:位尾数。表示二进制数为:01101011符号符号阶码,用阶码,用补码表示补码表示

28、尾数尾数程序设计 cs.sjtu 2005.9程序设计-51截断误差v由于尾数局部位数不够,使数值局部丧由于尾数局部位数不够,使数值局部丧失,有时一个十进制转化成二进制数时失,有时一个十进制转化成二进制数时小数点后会无限循环,因此尾数无法精小数点后会无限循环,因此尾数无法精确表示,这称为截断误差确表示,这称为截断误差v实型数在计算机中不能精确表示,只是实型数在计算机中不能精确表示,只是一个近似值。因此,最好不要判两个实一个近似值。因此,最好不要判两个实型数相等型数相等程序设计 cs.sjtu 2005.9程序设计-52第1章 计算机简介v计算机的组成计算机的组成v计算机的开展计算机的开展v信息

29、的表示信息的表示v程序设计程序设计vC C和和C+C+v上机准备上机准备程序设计 cs.sjtu 2005.9程序设计-53程序设计程序设计v程序设计语言程序设计语言v程序设计方法程序设计方法v程序设计过程程序设计过程v程序的执行程序的执行程序设计 cs.sjtu 2005.9程序设计-54程序设计语言v概述概述v程序设计语言的根本组成程序设计语言的根本组成v过程单元过程单元程序设计 cs.sjtu 2005.9程序设计-55程序设计语言的开展v第一代:机器语言第一代:机器语言v第二代:汇编语言第二代:汇编语言v第三代:过程化语言第三代:过程化语言v第四代:非过程化语言第四代:非过程化语言v第

30、五代:自然语言第五代:自然语言低级语言低级语言高级语言高级语言程序设计 cs.sjtu 2005.9程序设计-56机器语言v一组二进制数表示的指令一组二进制数表示的指令v每种计算机都有自己的机器语言每种计算机都有自己的机器语言v用机器语言写程序是非常困难的,读机用机器语言写程序是非常困难的,读机器语言写的程序也是非常困难的器语言写的程序也是非常困难的程序设计 cs.sjtu 2005.9程序设计-57汇编语言v用缩写和助记符代替用缩写和助记符代替0和和1的比特串的比特串v和机器语言一样,不同类的机器有不同和机器语言一样,不同类的机器有不同的汇编语言的汇编语言v汇编程序:将汇编语言写的程序翻译成

31、汇编程序:将汇编语言写的程序翻译成机器语言的程序机器语言的程序程序设计 cs.sjtu 2005.9程序设计-58过程化语言v类似于英语的语言类似于英语的语言v编译器:将过程化语言写的程序源代码编译器:将过程化语言写的程序源代码翻译成机器语言的程序目标代码翻译成机器语言的程序目标代码v解释器:逐句解释源程序并执行,不保存解释器:逐句解释源程序并执行,不保存目标代码。目标代码。程序设计 cs.sjtu 2005.9程序设计-59第三代语言的特点v具备了一定的机器独立性,使用户可以具备了一定的机器独立性,使用户可以专注于解决问题的方法。但某些方面还专注于解决问题的方法。但某些方面还是受到机器的限制

32、是受到机器的限制v为了解决移植性问题,为了解决移植性问题,ANSIANSI制订了一系制订了一系列的标准列的标准程序设计 cs.sjtu 2005.9程序设计-60主要的过程化语言vFORTRAN:FORmulaTRANslatorvBASIC/VisualBASICvCOBOL:COmmonBusinessOrientedLanguagevADAvPASCALvC/C+vJAVA程序设计 cs.sjtu 2005.9程序设计-61非过程化语言v也称为面向问题的语言也称为面向问题的语言v用于解决特定问题用于解决特定问题v如:如:SQL语言语言程序设计 cs.sjtu 2005.9程序设计-62自

33、然语言v人类的语言人类的语言v还在研究之中还在研究之中程序设计 cs.sjtu 2005.9程序设计-63程序设计语言v概述概述v程序设计语言的根本组成程序设计语言的根本组成v过程单元过程单元程序设计 cs.sjtu 2005.9程序设计-64变量和数据类型v变量变量(variable)(variable):为存储器中的地址取一:为存储器中的地址取一个名字。变量的命名应符合标准。个名字。变量的命名应符合标准。v数据类型数据类型(data type)(data type):数据的编码方式、:数据的编码方式、值域和可执行的操作值域和可执行的操作v整型整型(integer)(integer):以补码

34、形式存储,可执行:以补码形式存储,可执行传统的算术运算和比较运算传统的算术运算和比较运算v实型实型(real)(real):以浮点表示,操作类似于整:以浮点表示,操作类似于整型型v字符型字符型(char)(char):用编码表示。可执行比较、:用编码表示。可执行比较、连接等运算连接等运算v布尔型布尔型(boolean)(boolean):只有:只有“真、真、“假两假两个值。可执行判断运算个值。可执行判断运算程序设计 cs.sjtu 2005.9程序设计-65组合类型v数组:一组同质数据数组:一组同质数据v记录:一组异质数据,在记录:一组异质数据,在C C语言中称为结语言中称为结构体构体程序设计

35、 cs.sjtu 2005.9程序设计-66常量和符号常量v常量:值的直接表示。如常量:值的直接表示。如1 1、3 3、A A等等v符号常量:为值指定一个描述性的文字,符号常量:为值指定一个描述性的文字,增加程序的可读性。在增加程序的可读性。在C+C+语言中,语言中,#define#define和和constconst都能实现这个目的都能实现这个目的程序设计 cs.sjtu 2005.9程序设计-67赋值语句v把一个值赋给一个变量。如把一个值赋给一个变量。如x = y + z;x = y + z;v赋值语句的左边是变量,右边是表达式赋值语句的左边是变量,右边是表达式程序设计 cs.sjtu 2

36、005.9程序设计-68控制语句v改变程序中语句的执行次序改变程序中语句的执行次序v控制语句的类型控制语句的类型分支语句分支语句l两个分支两个分支l多个分支多个分支循环语句循环语句lFor For 语句语句lWhileWhile语句语句Goto Goto 语句:会破坏程序的结构语句:会破坏程序的结构程序设计 cs.sjtu 2005.9程序设计-69注释v注释是写给人看的,而不是写给机器看的。注释是写给人看的,而不是写给机器看的。它不影响程序的执行它不影响程序的执行v每个程序单元的开头都应该有注释,一些每个程序单元的开头都应该有注释,一些重要的程序段、变量声明也应该有注释重要的程序段、变量声明

37、也应该有注释v给程序添加注释是一种良好的程序设计习给程序添加注释是一种良好的程序设计习惯惯程序设计 cs.sjtu 2005.9程序设计-70程序设计语言v概述概述v程序设计语言的根本组成程序设计语言的根本组成v过程单元过程单元程序设计 cs.sjtu 2005.9程序设计-71过程单元v过程单元是程序的根本单位。过程单元是程序的根本单位。v解决某一问题的过程描述。解决某一问题的过程描述。v过程单元分为过程单元分为v过程过程(procedure):无返回值:无返回值v函数函数(function):有返回值:有返回值程序设计 cs.sjtu 2005.9程序设计-72过程单元v执行过程单元称为调

38、用执行过程单元称为调用(calling)(calling),过程单,过程单元执行完后返回到调用者元执行完后返回到调用者v过程单元的组成过程单元的组成名字名字参数参数 (parameter (parameter 或或 argument)argument)l形式参数形式参数l实际参数实际参数局部变量局部变量 (local variable)(local variable)全局变量全局变量 (global variable)(global variable)语句语句程序设计 cs.sjtu 2005.9程序设计-73参数传递v实际参数和形式参数之间的数据传递实际参数和形式参数之间的数据传递v参数传递

39、方式参数传递方式值传递值传递引用传递引用传递程序设计 cs.sjtu 2005.9程序设计-74程序设计程序设计v程序设计语言程序设计语言v程序设计方法程序设计方法v程序设计过程程序设计过程v程序的执行程序的执行程序设计 cs.sjtu 2005.9程序设计-75程序设计方法程序设计方法v早期的程序设计方法早期的程序设计方法v结构化程序设计方法结构化程序设计方法v面向对象程序设计方法面向对象程序设计方法程序设计就是教会计算机解决某个问题程序设计就是教会计算机解决某个问题程序设计 cs.sjtu 2005.9程序设计-76早期的程序设计方法早期的程序设计方法v早期的程序设计方法追求程序的高效率,

40、编程早期的程序设计方法追求程序的高效率,编程过份依赖技巧,而不注重所编写程序的结构,过份依赖技巧,而不注重所编写程序的结构,也就是没有固定程序设计方法的时期。程序的也就是没有固定程序设计方法的时期。程序的可读性、可重用性都很差。其中一个典型问题可读性、可重用性都很差。其中一个典型问题是频繁使用是频繁使用gotogoto语句。语句。v虽然这种方法存在很多问题,但对于单人完成虽然这种方法存在很多问题,但对于单人完成较为简单的任务,事实上还是经常被采用的。较为简单的任务,事实上还是经常被采用的。程序设计 cs.sjtu 2005.9程序设计-77结构化程序设计方法结构化程序设计方法v结构化程序设计方

41、法从程序要实现的功能的角结构化程序设计方法从程序要实现的功能的角度出发,一般按照自顶向下、逐步求精的方式,度出发,一般按照自顶向下、逐步求精的方式,将程序分解成一个个能够直接用程序设计语言将程序分解成一个个能够直接用程序设计语言写出来的功能模块,然后象搭积木一样搭起来。写出来的功能模块,然后象搭积木一样搭起来。v所谓的功能可以理解为对数据的操作。在程序所谓的功能可以理解为对数据的操作。在程序实现中,特定的功能或功能模块一般用函数来实现中,特定的功能或功能模块一般用函数来实现,它们要对特定的数据进行操作。实现,它们要对特定的数据进行操作。v该方法出现在上个世纪该方法出现在上个世纪7070年代。年

42、代。程序设计 cs.sjtu 2005.9程序设计-78结构化设计方法的特点结构化设计方法的特点v主要技术:自顶向下、逐步求精,采用单主要技术:自顶向下、逐步求精,采用单入口、单出口的控制结构。入口、单出口的控制结构。v自顶向下:是一种分解问题的技术,逐步自顶向下:是一种分解问题的技术,逐步求精指结构化程序的连续分解,最终成为求精指结构化程序的连续分解,最终成为下面三种根本控制结构的组合下面三种根本控制结构的组合v三种根本控制结构:顺序、分支、循环。三种根本控制结构:顺序、分支、循环。容易保证程序的正确性。容易保证程序的正确性。程序设计 cs.sjtu 2005.9程序设计-79分支结构语句1

43、语句2语句3条件语句2语句1语句1语句2顺序结构循环结构程序设计 cs.sjtu 2005.9程序设计-80面向对象程序设计面向对象程序设计v面向对象的程序设计在解决问题时首先考虑需面向对象的程序设计在解决问题时首先考虑需要哪些工具,以及如何用这些工具解决问题。要哪些工具,以及如何用这些工具解决问题。v如果所需要的工具不存在,程序员可以自己创如果所需要的工具不存在,程序员可以自己创立这个工具。立这个工具。v所谓的工具就是一种数据类型。所谓的工具就是一种数据类型。v对象是某种程序员自己定义的类型的变量。对象是某种程序员自己定义的类型的变量。程序设计 cs.sjtu 2005.9程序设计-81面向

44、对象方法的主要特点v封装封装v代码重用代码重用v继承:类的层次关系继承:类的层次关系v多态:对不同的对象发出同一个指令多态:对不同的对象发出同一个指令有不同的行为有不同的行为程序设计 cs.sjtu 2005.9程序设计-82程序设计程序设计v程序设计语言程序设计语言v程序设计方法程序设计方法v程序设计过程程序设计过程v程序的执行程序的执行程序设计 cs.sjtu 2005.9程序设计-83程序设计程序设计v算法设计:设想计算机是如何一步一步完成这个任务算法设计:设想计算机是如何一步一步完成这个任务v编码:用计算机认识的语言,如编码:用计算机认识的语言,如C+语言,描述这个语言,描述这个完成任

45、务的过程完成任务的过程v编译与调试:检验程序是否正确,到达预期的目标编译与调试:检验程序是否正确,到达预期的目标程序设计就是教会计算机去完成某一特定的任务,程序设计就是教会计算机去完成某一特定的任务,即设计出完成某个任务的程序即设计出完成某个任务的程序 。程序设计包括以。程序设计包括以下几个阶段:下几个阶段:程序设计 cs.sjtu 2005.9程序设计-84算法算法v计算机解决问题的步骤,算法的每一步都是都计算机解决问题的步骤,算法的每一步都是都是程序设计语言能够完成的根本功能。是程序设计语言能够完成的根本功能。v算法必须是:算法必须是:v表述清楚、明确,无二义性。表述清楚、明确,无二义性。

46、v有效性。即每一步骤都切实可行。有效性。即每一步骤都切实可行。v有限性,即可在有限步骤后得到结果。有限性,即可在有限步骤后得到结果。v算法的表示算法的表示:有自然语言、传统的流程图、:有自然语言、传统的流程图、结构化流程图、伪代码和结构化流程图、伪代码和PAD图等方法图等方法程序设计 cs.sjtu 2005.9程序设计-85编码编码v用某种程序设计语言表示算法用某种程序设计语言表示算法程序设计 cs.sjtu 2005.9程序设计-86程序设计程序设计v程序设计语言程序设计语言v程序设计方法程序设计方法v程序设计过程程序设计过程v程序的执行程序的执行程序设计 cs.sjtu 2005.9程序

47、设计-87语言的翻译v将高级语言的程序翻译成机器语言将高级语言的程序翻译成机器语言解释执行解释执行编译执行编译执行程序设计 cs.sjtu 2005.9程序设计-88编译执行编译执行main()inti,s;i=1;s=0;Ccompiler0110001011101001SourceprogramObjectprogram将程序全部翻译成机器语言的程序,然后再执行。将程序全部翻译成机器语言的程序,然后再执行。程序设计 cs.sjtu 2005.9程序设计-89编译程序的结构词法分析词法分析语法分析语法分析中间代码生成中间代码生成优化优化目标代码生成目标代码生成源程序源程序目标程序目标程序单词

48、单词语法单位语法单位中间代码中间代码优化后的中间代码优化后的中间代码识别一个个单词,并转化为机内形式识别一个个单词,并转化为机内形式按语法规那么识别语法单位,如表达式、按语法规那么识别语法单位,如表达式、语句等语句等如四元组、三元组和逆波兰表达式如四元组、三元组和逆波兰表达式对运行速度、存储空间方面进行优化对运行速度、存储空间方面进行优化中间代码转换为目标程序中间代码转换为目标程序程序设计 cs.sjtu 2005.9程序设计-90解释执行源程序源程序解释系统解释系统(逐句解释、执行)(逐句解释、执行)原始数据原始数据结果结果程序设计 cs.sjtu 2005.9程序设计-91连接与加载v连接

49、连接(link)(link):将目标程序与已有的其它:将目标程序与已有的其它目标程序连接起来,产生一个可执行的目标程序连接起来,产生一个可执行的程序程序v加载加载(load)(load):为程序在内存中定位:为程序在内存中定位程序设计 cs.sjtu 2005.9程序设计-92程序执行过程程序设计 cs.sjtu 2005.9程序设计-93程序的调试程序的调试v语法错误和词法错误语法错误和词法错误:由编译器检查,:由编译器检查,指出错误。程序员根据编译器输出的信指出错误。程序员根据编译器输出的信息修改程序息修改程序v逻辑错误逻辑错误bug:通过分段观察程序的阶:通过分段观察程序的阶段性结果来找

50、出错误的位置和原因。段性结果来找出错误的位置和原因。v程序的调试及测试只能发现程序中的错程序的调试及测试只能发现程序中的错误,而不能证明程序是正确的误,而不能证明程序是正确的!程序设计 cs.sjtu 2005.9程序设计-94第1章 计算机简介v计算机的组成计算机的组成v计算机的开展计算机的开展v信息的表示信息的表示v程序设计程序设计vC C和和C+C+v上机准备上机准备程序设计 cs.sjtu 2005.9程序设计-95C和和C+vC+是从是从C开展而来,而开展而来,而C又是从又是从B语言开展而来语言开展而来vC语言是由贝尔实验室在语言是由贝尔实验室在B语言的根底上开发的,语言的根底上开发

51、的,并有美国国家标准组织和国际标准化组织进行了并有美国国家标准组织和国际标准化组织进行了标准化标准化vC+是是C的扩展,主要是提供了面向对象的功能的扩展,主要是提供了面向对象的功能v本学期介绍本学期介绍C的局部和过程化程序设计的局部和过程化程序设计程序设计 cs.sjtu 2005.9程序设计-96第1章 计算机简介v计算机的组成计算机的组成v计算机的开展计算机的开展v信息的表示信息的表示v程序设计语言程序设计语言vC C和和C+C+v上机准备上机准备程序设计 cs.sjtu 2005.9程序设计-97的使用的使用简单情况简单情况v创立源文件:创立源文件:.在工具栏里面最左面的一个按钮是用在工

52、具栏里面最左面的一个按钮是用来创立一个空白文件的。来创立一个空白文件的。v输入源程序:现在屏幕的中右部出现了一个空白编辑输入源程序:现在屏幕的中右部出现了一个空白编辑环境,是用来编辑我们的程序的。环境,是用来编辑我们的程序的。v保存源文件:按一下保存源文件:按一下Ctrl+S即可,此时系统会让你输即可,此时系统会让你输入文件名字。注意一定要写扩展名入文件名字。注意一定要写扩展名“.cpp。v编译链接程序:在菜单里面找到编译链接程序:在菜单里面找到Build然后单击里面的然后单击里面的Build菜单项,接下来系统会弹出几个对话框,你直接菜单项,接下来系统会弹出几个对话框,你直接点击点击“确定即可

53、。确定即可。v运行程序:第运行程序:第4步执行完后没有错误,现在就可以运步执行完后没有错误,现在就可以运行你的程序了。运行方法是点击工具条右后部的行你的程序了。运行方法是点击工具条右后部的“!或者直接按或者直接按Ctrl+F5。你的程序如果正常执行的话,。你的程序如果正常执行的话,屏幕上回显示出一个屏幕上回显示出一个DOS窗口输出你的运行结果。窗口输出你的运行结果。程序设计 cs.sjtu 2005.9程序设计-98的使用的使用一般情况一般情况v建立工程:在建立工程:在file菜单下选择菜单下选择new一个一个projectv建立源文件建立源文件v将源文件参加工程:在将源文件参加工程:在pro

54、ject菜单中选菜单中选择择“insertfileintoprojectv编译链接编译链接v执行程序执行程序程序设计 cs.sjtu 2005.9程序设计-99程序的调试程序的调试v程序中的错误程序中的错误语法错误:由编译器找出这些错误语法错误:由编译器找出这些错误逻辑错误:可以利用调试工具逻辑错误:可以利用调试工具vVC支持各种调试工具,包括支持各种调试工具,包括断点设置断点设置单步执行单步执行变量跟踪变量跟踪程序设计 cs.sjtu 2005.9程序设计-100第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表

55、达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-101C+程序的根本组成程序的根本组成v根本的根本的C+程序结构程序结构/thisprogramprintsthemessage/“helloeveryoneonthescreen#includeintmain()std:cout“helloeveryonestd:endl;return0;程序注释程序注释预处理命令预处理命令主程序主程序程序设计 cs.sjtu 2005.9程序设计-102注释注释vC+的注释

56、是从的注释是从/开始到本行结束开始到本行结束,也可以采,也可以采用用C风格的注释,即从风格的注释,即从/*与与*/之间所有的文字之间所有的文字都是注释,可以是连续的几行。都是注释,可以是连续的几行。v注释是写给人看的,而不是写给计算机的。注释是写给人看的,而不是写给计算机的。v程序注释程序注释:从整体描述程序操作过程:从整体描述程序操作过程v注释也可以出现在主程序中,解释主程序中一注释也可以出现在主程序中,解释主程序中一些比较难理解的局部。些比较难理解的局部。v给程序添加注释是良好的程序设计风格给程序添加注释是良好的程序设计风格程序设计 cs.sjtu 2005.9程序设计-103C程序的根本

57、组成程序的根本组成v根本的根本的C程序结构程序结构/thisprogramprintsthemessage/“helloeveryoneonthescreen#includeintmain()std:cout“helloeveryonestd:endl;return0;程序注释程序注释预处理命令预处理命令主程序主程序程序设计 cs.sjtu 2005.9程序设计-104编译预处理编译预处理vC+的编译分成两个阶段:预编译和编译的编译分成两个阶段:预编译和编译v预编译处理程序中的预编译命令,即那些以预编译处理程序中的预编译命令,即那些以#开头的指令开头的指令v编译预处理主要有:编译预处理主要有:

58、库包含:用库包含:用#include实现,表示程序使用了某个库实现,表示程序使用了某个库宏定义宏定义:用:用#define实现。实现。程序设计 cs.sjtu 2005.9程序设计-105库包含的格式库包含的格式v库是预先做好的一些工具程序。库是预先做好的一些工具程序。v每个库要提供一个接口,告诉库的用户如何使用每个库要提供一个接口,告诉库的用户如何使用库提供的工具。库提供的工具。v库包含就是把库的接口文件放入源文件,以便库包含就是把库的接口文件放入源文件,以便编译器检查程序中对工具的调用是否正确。编译器检查程序中对工具的调用是否正确。v库包含格式:库包含格式:v#include:包含了一个系

59、统库:包含了一个系统库v#include“filename:包含了一个用户自定义:包含了一个用户自定义的库的库程序设计 cs.sjtu 2005.9程序设计-106宏定义宏定义v宏定义有两类:宏定义有两类:不带参数的宏不带参数的宏带参数的宏带参数的宏程序设计 cs.sjtu 2005.9程序设计-107不带参数的宏定义不带参数的宏定义v不带参数的宏定义通常用于为程序中的常量取一个不带参数的宏定义通常用于为程序中的常量取一个名字,称为符号常量。格式:名字,称为符号常量。格式:#define标识符标识符替换文本替换文本如:如:#defineRADIUS5#defineAREAPI*RADIUS*R

60、ADIUSv用用define定义符号常量是定义符号常量是C语言的习惯,在语言的习惯,在C+中中有更好的解决方案有更好的解决方案程序设计 cs.sjtu 2005.9程序设计-108使用符号常量的好处使用符号常量的好处v含义清楚,提高了程序的可读性。含义清楚,提高了程序的可读性。v在需要改变一个常量时能做到在需要改变一个常量时能做到“一改一改全改全改程序设计 cs.sjtu 2005.9程序设计-109带参数的宏定义带参数的宏定义v带参数的宏用于定义一些较为复杂的操作带参数的宏用于定义一些较为复杂的操作v格式:格式:v#define宏名参数表宏名参数表替换文本替换文本v如:如:#defineCI

61、RCLE_AREA(x)(PI(x)*(x)v当程序中出现语句当程序中出现语句area=CIRCLE_AREA(4),v就会被替换成就会被替换成area=3.14159*4*4v带参数的宏是带参数的宏是C语言的习惯,它有很多缺陷,在语言的习惯,它有很多缺陷,在C+中有更好的解决方案中有更好的解决方案程序设计 cs.sjtu 2005.9程序设计-110C程序的根本组成程序的根本组成v根本的根本的C程序结构程序结构/thisprogramprintsthemessage/“helloeveryoneonthescreen#includeintmain()std:cout“helloeveryon

62、estd:endl;return0;程序注释程序注释预处理命令预处理命令主程序主程序程序设计 cs.sjtu 2005.9程序设计-111主程序主程序v主程序由一个或多个函数组成主程序由一个或多个函数组成v函数是一系列独立的程序步骤,把这些函数是一系列独立的程序步骤,把这些程序步骤集合在一起,并赋予一个名字。程序步骤集合在一起,并赋予一个名字。v每个程序都必须有一个名为每个程序都必须有一个名为main的函数,的函数,它是程序执行的入口。它是程序执行的入口。程序设计 cs.sjtu 2005.9程序设计-112函数的构成函数的构成intmain()函数头函数头std:cout“helloever

63、yonestd:endl;return0;函数体程序设计 cs.sjtu 2005.9程序设计-113函数头函数头v说明函数和外界的交流说明函数和外界的交流v形式:形式:v返回类型返回类型函数名参数表函数名参数表v返回类型:是函数的输出值的类型返回类型:是函数的输出值的类型v函数名:是函数的名字。程序可以通过函数名函数名:是函数的名字。程序可以通过函数名执行函数体的语句执行函数体的语句v参数表:是函数的输入参数表:是函数的输入v可以把函数想象成数学中的函数。参数表是一可以把函数想象成数学中的函数。参数表是一组自变量,返回类型是函数值的类型组自变量,返回类型是函数值的类型程序设计 cs.sjtu

64、 2005.9程序设计-114函数体函数体v函数如何完成预定功能的过程。它说明函数如何完成预定功能的过程。它说明了如何从输入参数得到输出的返了如何从输入参数得到输出的返回值的过程。回值的过程。v可以把它想象成数学中的函数表达式可以把它想象成数学中的函数表达式程序设计 cs.sjtu 2005.9程序设计-115输出流对象输出流对象std:coutv“流指的是设备之间传递的数据流流指的是设备之间传递的数据流v输出流是传给输出设备的数据流输出流是传给输出设备的数据流vcout代表显示器,代表显示器,std是名字空间名是名字空间名v格式格式v将将hello显示在屏幕上:显示在屏幕上:std:cout

65、“hellovstd:cout“hello,everyonestd:endlvstd:endl表示换行表示换行程序设计 cs.sjtu 2005.9程序设计-116名字空间名字空间v在大型的程序时,每个源文件可能由不同的开发者开发。在大型的程序时,每个源文件可能由不同的开发者开发。不同的源文件中可能有同样的名字。当这些源文件连接起不同的源文件中可能有同样的名字。当这些源文件连接起来形成一个可执行文件时,就会造成重名。来形成一个可执行文件时,就会造成重名。v名字空间是把一组程序实体组合在一起,构成的一个作用名字空间是把一组程序实体组合在一起,构成的一个作用域。域。v一个名字空间中不能有重名,不同

66、的名字空间中可以定义一个名字空间中不能有重名,不同的名字空间中可以定义相同的实体名。当引用某个实体时,需要加上名字空间的相同的实体名。当引用某个实体时,需要加上名字空间的限定限定v程序中的程序中的std是是C+中所有标准库的名字空间名。中所有标准库的名字空间名。程序设计 cs.sjtu 2005.9程序设计-117使用名字空间的指令使用名字空间的指令v格式:格式:usingnamespace名字空间名;名字空间名;v一旦用了使用名字空间的指令,该名字一旦用了使用名字空间的指令,该名字空间中的所有的实体在引用时就不需要空间中的所有的实体在引用时就不需要再加名字空间的限定了。再加名字空间的限定了。

67、v第一个程序可以改写为:第一个程序可以改写为:程序设计 cs.sjtu 2005.9程序设计-118/Thisprogramprintsthemessage“Helloworld./Onthescreen#includeusingnamespacestd;intmain()cout“Helloworld.endl;return0;返回函数执行的结果返回函数执行的结果程序设计 cs.sjtu 2005.9程序设计-119第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符

68、自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-120计算园的面积和周长计算园的面积和周长/该程序用于计算园的面积和周长该程序用于计算园的面积和周长#definePI3.14159/定义符号常量定义符号常量#includeusingnamespacestd;intmain()doubleradius,area,circum;coutradius;area=PI*radius*radius;circum=2*PI*radius;coutendl;cout园的面积为:园的面积为:areaendl;cout园的

69、周长为:园的周长为:circumendl;return0;变量定义变量定义输入阶段输入阶段计算阶段计算阶段输出阶段输出阶段程序设计 cs.sjtu 2005.9程序设计-121程序的组成程序的组成v变量定义:为一些在程序编写时值未知的数据预约变量定义:为一些在程序编写时值未知的数据预约它们的存放处它们的存放处v输入阶段输入阶段:获取执行时才能确定的用户数据。输入:获取执行时才能确定的用户数据。输入过程一般包括两步过程一般包括两步:显示提示信息显示提示信息读取数据读取数据v计算阶段计算阶段:由输入推导出输出的过程。通常通过各:由输入推导出输出的过程。通常通过各种计算得到。种计算得到。v输出阶段:

70、显示程序执行的结果输出阶段:显示程序执行的结果v各阶段之间一般用空行分开各阶段之间一般用空行分开程序设计 cs.sjtu 2005.9程序设计-122第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-123变量定义变量定义v变量,也称为对象,是数据的存放之处变量,也称为对象,是数据的存放之处v变量有三个重要属性:名称、值、类型变量有

71、三个重要属性:名称、值、类型。变量定义就是。变量定义就是告诉编译器变量的名字及该变量中可以存放哪一类数据告诉编译器变量的名字及该变量中可以存放哪一类数据类型的值类型的值vC语言中变量定义的格式语言中变量定义的格式:类型名类型名变量名变量名1,变量名,变量名2,变量名,变量名n;v如:如:intnum1,num2;doublearea;v在在C语言中,每个变量在使用前必须被定义,以便编译语言中,每个变量在使用前必须被定义,以便编译器检查变量使用的合法性。器检查变量使用的合法性。程序设计 cs.sjtu 2005.9程序设计-124变量命名变量命名v名字必须以字母或下划线开头。名字必须以字母或下划

72、线开头。C语言中,名字中出现的语言中,名字中出现的大写和小写字母被看作是不同的字符,因此大写和小写字母被看作是不同的字符,因此ABC,Abc,abc是三个独立的变量名。是三个独立的变量名。v名字中的其它字符必须是字母、数字或下划线,不得使用名字中的其它字符必须是字母、数字或下划线,不得使用空格和其它特殊符号空格和其它特殊符号v名字不可以是系统的保存词,如:名字不可以是系统的保存词,如:int,double,for,return等,等,它们在它们在C语言中有特殊用途语言中有特殊用途vC语言没有规定过名字的长度,但各个编译系统都有自己语言没有规定过名字的长度,但各个编译系统都有自己规定。规定。v名

73、字应使读者易于明白其存储的值是什么,做到名字应使读者易于明白其存储的值是什么,做到“见名知见名知意。意。程序设计 cs.sjtu 2005.9程序设计-125第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-126数据类型数据类型v数据类型包括两个方面:数据类型包括两个方面:v数据的取值范围数据的取值范围v可用的操作可用的操作vC/

74、C+中的数据类型分为两大类:中的数据类型分为两大类:v根本数据类型:整型、浮点型、字符型和布尔根本数据类型:整型、浮点型、字符型和布尔型型v构造数据类型:数组、结构、联合和枚举构造数据类型:数组、结构、联合和枚举程序设计 cs.sjtu 2005.9程序设计-127数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序设计-128数据类型数据类型整整型型v整型数的表示范围:由各个编译器指定。整型数有整型数的表示范围:由各个编译器指定

75、。整型数有三种存储方式,在三种存储方式,在VC中占用的空间如下所示中占用的空间如下所示v根本型根本型:int4byte(PC)2312311v长整型:长整型:long/longint4byte(PC)v2312311v短整型:短整型:short/shortint:2byte(PC)v2152151)v允许的操作:算术运算、比较大小等允许的操作:算术运算、比较大小等程序设计 cs.sjtu 2005.9程序设计-129整数的内部表示整数的内部表示v整数在计算机内部通常用补码表示,在整数在计算机内部通常用补码表示,在VC中中也是如此。也是如此。v应用整数运算时要注意数据的表示范围。如整应用整数运算

76、时要注意数据的表示范围。如整数用两个字节表示时,正整数数用两个字节表示时,正整数32767加加1的的结果为结果为32768。这称为整数运算的溢出。这称为整数运算的溢出。v系统不检查整数溢出错误,程序员必须自己保系统不检查整数溢出错误,程序员必须自己保证程序中不出现这样的错误。证程序中不出现这样的错误。程序设计 cs.sjtu 2005.9程序设计-130无符号整数无符号整数v在某些应用中,不可能出现负数,那么整型数中有一半在某些应用中,不可能出现负数,那么整型数中有一半的数值范围是被浪费的。因此在的数值范围是被浪费的。因此在C/C+C/C+中可以将最高位中可以将最高位看成是数字而不是符号,称为

77、无符号数。看成是数字而不是符号,称为无符号数。v无符号数的定义:在各种整数类型前加上关键词无符号数的定义:在各种整数类型前加上关键词unsignedunsigned,变成,变成unsigned int, unsigned short, unsigned int, unsigned short, unsigned longunsigned longunsignedint02321unsignedshort065535unsignedlong02321程序设计 cs.sjtu 2005.9程序设计-131整型常量整型常量v整型常量可用十进制、八进制和十六进制表示整型常量可用十进制、八进制和十六进制

78、表示十进制:十进制:123,234八进制:八进制:0123十六进制:十六进制:0x123,0x3a2fv一旦定义了一个整型变量,可以将一个整型常一旦定义了一个整型变量,可以将一个整型常量赋给该整型变量。如量赋给该整型变量。如inta;a=123;或或a=0x123;都是正确的都是正确的程序设计 cs.sjtu 2005.9程序设计-132数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序设计-133数据类型数据类型浮点数浮点数v

79、C语言中的实型数以浮点形式表示语言中的实型数以浮点形式表示v浮点类型的分类浮点类型的分类单精度单精度float:占用占用4字节,字节,3字节尾数,字节尾数,1字节指数字节指数, , 精确度精确度7位位, ,范围范围10381038双精度双精度double:占用占用8字节字节, , 5字节尾数字节尾数, , 3字节指数字节指数, , 精确度精确度1516位位, ,范围范围1030710308v浮点数无法精确表示浮点数无法精确表示程序设计 cs.sjtu 2005.9程序设计-134浮点数常量浮点数常量v浮点数常量有两种表示法:浮点数常量有两种表示法:十进制表示:十进制表示:科学计数法:科学计数法

80、:尾数尾数* *1010指数指数 尾数尾数e指数指数 注意:尾数不能为空注意:尾数不能为空 e31e3 指数必须为整数指数必须为整数 是非法的是非法的程序设计 cs.sjtu 2005.9程序设计-135数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序设计-136数据类型数据类型字符类型字符类型v字符类型:存放一个字母或符号,字符类型:存放一个字母或符号,占一个字节,存放的是字符的内码。占一个字节,存放的是字符的内码。v字符类

81、型名:字符类型名:char程序设计 cs.sjtu 2005.9程序设计-137字符的机内表示字符的机内表示v字符的机内表示字符的机内表示用字符编码表示。常用的有用字符编码表示。常用的有ASCII,BCD,EBCDIC等。等。PC机中都用机中都用ASCII.vASCII码的重要特性码的重要特性数字数字0到到9是顺序存放的是顺序存放的字母被分成二段:大写的和小写的。大写字字母被分成二段:大写的和小写的。大写字母是连续的,小写字母也是连续的母是连续的,小写字母也是连续的程序设计 cs.sjtu 2005.9程序设计-138可打印字符和非打印字符可打印字符和非打印字符v可打印字符:小写字母、大写字母

82、、数可打印字符:小写字母、大写字母、数字、标点符号、空格等字、标点符号、空格等v非打印字符:换行和报警字符或响铃非打印字符:换行和报警字符或响铃等等控制字符控制字符程序设计 cs.sjtu 2005.9程序设计-139可打印字符的使用可打印字符的使用v字符常量字符常量a,S,2等用一对单引号括起来的数等用一对单引号括起来的数据称为字符常量据称为字符常量程序设计 cs.sjtu 2005.9程序设计-140可打印字符的使用可打印字符的使用v赋值赋值vcharc1,c2;vc1=a;c2=b;vc1=97;c2=98;v比较比较c=9和和c=9?v运算运算v如:如:c1=a;c1=c1+2;c1的

83、值应为?的值应为?v如如c中存放的是小写字母,那么中存放的是小写字母,那么ca+1表示表示什么?什么?v如如c中存放的是数字中存放的是数字09,那么,那么c0表示什么?表示什么?v如如c1,c2存放的是小写字母,那么存放的是小写字母,那么c2c1表示表示什么什么?程序设计 cs.sjtu 2005.9程序设计-141转义字符转义字符v非打印字符需要用转义序列表示非打印字符需要用转义序列表示v换行符写为换行符写为n,虽然它由两个字符和,虽然它由两个字符和n来描来描述,但它表示一个述,但它表示一个ASCII字符。反斜杠符号字符。反斜杠符号称为转称为转义字符。义字符。v双引号和单引号的转义双引号和单

84、引号的转义v如果在一个串中把双引号用作一个字符或表示如果在一个串中把双引号用作一个字符或表示字符常量单引号,必须要对它转义,否那么它会终结字符常量单引号,必须要对它转义,否那么它会终结该字符串。该字符串。vcout“abc;输出输出“abcv双引号的单字符表示:可以写双引号的单字符表示:可以写,也可以写,也可以写。v八进制数转义序列八进制数转义序列v警告字符警告字符a可以表示成可以表示成:007,07,7程序设计 cs.sjtu 2005.9程序设计-142字符形式字符形式含义含义n换行换行t水平制表水平制表b退一格退一格r回车回车f换页换页”“ddd1到到3位八进制数代表的字符位八进制数代表

85、的字符xhh1到到2位十六进制数代表的字符位十六进制数代表的字符常用的转义字符常用的转义字符程序设计 cs.sjtu 2005.9程序设计-143数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序设计-144数据类型数据类型布尔类型布尔类型v布尔型布尔型bool:标准:标准C中没有布尔型数据,中没有布尔型数据,这是这是C+中新增的数据类型。占一个字节。它中新增的数据类型。占一个字节。它的值为:的值为:true,falsev布尔型

86、数据可以进行逻辑运算布尔型数据可以进行逻辑运算v布尔型数据的内部表示:布尔型数据的内部表示:true为为1,false为为0程序设计 cs.sjtu 2005.9程序设计-145数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序设计-146枚举类型枚举类型v有时在设计程序时会用到一些特殊的对象,这些有时在设计程序时会用到一些特殊的对象,这些对象的取值范围是有限可数的。如在一个生成日对象的取值范围是有限可数的。如在一个生成日历的程

87、序中很可能用到一个表示一个星期中的每历的程序中很可能用到一个表示一个星期中的每一天的对象。该对象可能取值的范围就是星期日一天的对象。该对象可能取值的范围就是星期日到星期六。到星期六。v解决方法解决方法采用编码采用编码:假设:假设0表示星期日,表示星期日,1表示星期一,表示星期一,6表示星期六。然后用一个整型变量如表示星期六。然后用一个整型变量如weekday表示这表示这个对象。缺点是可读性差。个对象。缺点是可读性差。符号常量:用符号常量:用#define功能将这些数字定义为符号常量功能将这些数字定义为符号常量定义一个新类型定义一个新类型程序设计 cs.sjtu 2005.9程序设计-147定义

88、新的枚举类型定义新的枚举类型v格式:格式:enum枚举类型名枚举类型名元素表元素表;v定义一个表示一周中每天的名字的枚举类型:定义一个表示一周中每天的名字的枚举类型:venumweekdayTSunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;v枚举类型变量的定义:枚举类型变量的定义:vweekdayTweekday;v枚举类型变量的使用:枚举类型变量的使用:v赋值:赋值:weekday=Friday;v比较:比较:MondayFriday比较这两个值的内部表比较这两个值的内部表示示v枚举类型不能直接输入输出枚举类型不能直接输入输出

89、程序设计 cs.sjtu 2005.9程序设计-148枚举类型的内部表示枚举类型的内部表示v在内部,枚举类型采用编码表示。当定义在内部,枚举类型采用编码表示。当定义enumweekdayTSunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;时,默认用时,默认用0代表代表Sunday,1代表代表Monday,6表示表示SaturdayvC语言的编译器也允许明确指出枚举类型的元素的内部表示。例如,希语言的编译器也允许明确指出枚举类型的元素的内部表示。例如,希望从望从1而不是而不是0开始编号,可以这样定义开始编号,可以这样定义enumwe

90、ekdayTSunday=1,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;v也可以从中间某一个开始重新指定,如也可以从中间某一个开始重新指定,如enumweekdayTSunday,Monday,Tuesday=5,Wednesday,Thursday,Friday,Saturday;程序设计 cs.sjtu 2005.9程序设计-149数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2

91、005.9程序设计-150用用typedef重新命名类型名重新命名类型名v格式:格式:typedef已有类型名已有类型名新类型名;新类型名;v如一旦执行了:如一旦执行了:typedefintINTEGER;那么,要定义一个整型变量那么,要定义一个整型变量a,除了可以,除了可以用用inta;之外,也可以用之外,也可以用INTEGERa;程序设计 cs.sjtu 2005.9程序设计-151数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005

92、.9程序设计-152定义新的类型定义新的类型vC+通过类通过类(class)来定义新的数据类型来定义新的数据类型v类定义包括:类定义包括:v该类型的对象包含的数据,称为类的数据成员该类型的对象包含的数据,称为类的数据成员v该类型的对象可以执行的操作,称为类的成员函该类型的对象可以执行的操作,称为类的成员函数数v类的设计类的设计v接口接口interface:类包括那些数据成员和成员函类包括那些数据成员和成员函数数v实现实现implementation:成员函数是如何实现:成员函数是如何实现的的v定义新类型是定义新类型是C+和和C的质的变化,我们将在下的质的变化,我们将在下学期详细介绍学期详细介绍

93、程序设计 cs.sjtu 2005.9程序设计-153数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序设计-154变量赋初值变量赋初值v在在C语言中,变量定义只是给变量分配相应的空间语言中,变量定义只是给变量分配相应的空间vC语言允许在定义变量的同时给变量赋初值语言允许在定义变量的同时给变量赋初值v格式:格式:v类型名类型名变量名变量名=初值;初值;v类型名类型名变量名初值;变量名初值;v如:如:intcount=0;或或in

94、tcount(0);都是定义整都是定义整型变量型变量count,并为它赋初值,并为它赋初值0。v可以给被定义的变量中的一局部变量赋初值,如:可以给被定义的变量中的一局部变量赋初值,如:vintsum=0,count=0,num;定义变量时没有赋初值,然后直接引用该变量是危险的!定义变量时没有赋初值,然后直接引用该变量是危险的!程序设计 cs.sjtu 2005.9程序设计-155数据类型数据类型整型整型实型实型字符型字符型布尔型布尔型枚举类型枚举类型重新命名类型名重新命名类型名定义新的类型定义新的类型变量赋初值变量赋初值了解占用的内存量了解占用的内存量程序设计 cs.sjtu 2005.9程序

95、设计-156了解占用的内存量了解占用的内存量vsizeof运算符用来了解某一类型或某一表达式运算符用来了解某一类型或某一表达式占用的内存量。占用的内存量。vsizeof运算符的用法:运算符的用法:sizeof(类型名类型名)或或sizeof(表达式表达式)v如:如:sizeof(float):float类型的变量占用的内存量类型的变量占用的内存量sizeof(a+15):表达式:表达式a+15的计算结果的计算结果所占的内存量所占的内存量程序设计 cs.sjtu 2005.9程序设计-157第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类

96、型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-158符号常量符号常量v用用#define定义符号常量的问题定义符号常量的问题所定义的符号常量无法进行类型检查所定义的符号常量无法进行类型检查#define的处理只是简单的字符串的替换,的处理只是简单的字符串的替换,可能会引起一些意想不到的错误可能会引起一些意想不到的错误vC+建议用建议用const定义符号常量定义符号常量const=;如:如:constdoublePI=3.141592

97、6;程序设计 cs.sjtu 2005.9程序设计-159第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-160算术表达式算术表达式v计算是计算机提供的最根本的功能,算术表达式计算是计算机提供的最根本的功能,算术表达式是完成此功能的工具是完成此功能的工具v算术表达式由运算符和运算对象组成算术表达式由运算符和运算对象组成v算术运算符

98、:算术运算符:+*/%v出出“外,所有的算术运算符都是二元运算符。外,所有的算术运算符都是二元运算符。“可为二元运算,也可为一元运算可为二元运算,也可为一元运算v优先级:高优先级:高*/%,低,低+v结合性:左结合结合性:左结合v运算对象可以是整型、浮点型、字符型和布尔型运算对象可以是整型、浮点型、字符型和布尔型程序设计 cs.sjtu 2005.9程序设计-161应用算术表达式的本卷须知应用算术表达式的本卷须知v乘号不能省略乘号不能省略v出现除法时注意括号的应用。如出现除法时注意括号的应用。如应写为应写为:(a+b)/(c*d)或或(a+b)/c/d但不能写成但不能写成:(a+b)/c*d或

99、或a+b/c*dv在写算术表达式时,为使表达式更加清晰,一般在写算术表达式时,为使表达式更加清晰,一般在运算符前后各插一个空格在运算符前后各插一个空格程序设计 cs.sjtu 2005.9程序设计-162各种类型的数据的混合运算各种类型的数据的混合运算v整型与整型数运算,结果为整型,如整型与整型数运算,结果为整型,如5/2=2v整型与浮点数运算,结果为浮点数,如整型与浮点数运算,结果为浮点数,如5/2.0=2.5v字符或布尔型与整型数运算,结果为整型。字符或布尔型与整型数运算,结果为整型。v字符或布尔型与浮点数运算,结果为浮点数。字符或布尔型与浮点数运算,结果为浮点数。v浮点数与浮点数运算,结

100、果为浮点数。浮点数与浮点数运算,结果为浮点数。程序设计 cs.sjtu 2005.9程序设计-163各类数值型数据间的混合运算各类数值型数据间的混合运算 3.5*2+a b /4自动类型转换规那么:自动类型转换规那么: 程序设计 cs.sjtu 2005.9程序设计-164数学函数库数学函数库v在在C+语言中,其他的数学运算都是通过函数语言中,其他的数学运算都是通过函数的形式来实现。所有的数学函数都在的形式来实现。所有的数学函数都在cmath中。中。v要使用这些数学函数,必须在程序头上写上编要使用这些数学函数,必须在程序头上写上编译预处理命令:译预处理命令:#includeusingnames

101、pacestd;程序设计 cs.sjtu 2005.9程序设计-165cmath的主要内容的主要内容绝对值函数绝对值函数intabs(intx);doublefabs(doublex)exdoubleexp(doublex)xydoublepow(doublex,doubley)doublesqrt(doublex)lnxdoublelog(doublex)log10xdoublelog10(doublex)三角函数三角函数doublesin(doublex)doublecos(doublex)doubletan(doublex)反三角函数反三角函数doubleasin(doublex)dou

102、bleacos(doublex)doubleatan(doublex)程序设计 cs.sjtu 2005.9程序设计-166第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-167变量赋值变量赋值v变量赋值是通过赋值表达式实现,赋值表达式格式变量赋值是通过赋值表达式实现,赋值表达式格式=作用:将右边的表达式的值存入左边的变量,整个赋

103、值表作用:将右边的表达式的值存入左边的变量,整个赋值表达式的值是右边的表达式的结果。达式的值是右边的表达式的结果。注意:注意:x=x+2是正确的表达式是正确的表达式赋值运算符是右结合的赋值运算符是右结合的v左值左值(lvalue):在:在C+中,能出现在赋值运算符左边中,能出现在赋值运算符左边的表达式称为左值的表达式称为左值v赋值语句:赋值表达式后面加上分号。赋值语句:赋值表达式后面加上分号。程序设计 cs.sjtu 2005.9程序设计-168赋值时的自动类型转换赋值时的自动类型转换v当表达式的结果类型和变量类型不一致时,系统会将右当表达式的结果类型和变量类型不一致时,系统会将右边的表达式的

104、结果转换成左边的变量的类型,再赋给左边的表达式的结果转换成左边的变量的类型,再赋给左边的变量。边的变量。v转换规那么:转换规那么:v实型数实型数整型:舍弃小数局部。整型:舍弃小数局部。v整型数整型数实型数:数值不变,但以浮点的形式保存在相实型数:数值不变,但以浮点的形式保存在相应的变量中应的变量中vDoublefloat:截取前面七位有效数字存放到:截取前面七位有效数字存放到float变量变量中中vFloatdouble:将有效位扩展到:将有效位扩展到16位位v字符型字符型整型变量:将字符型数据放入整型变量的最后整型变量:将字符型数据放入整型变量的最后一个字节。如果所用系统将字符处理成无符号量

105、,那么一个字节。如果所用系统将字符处理成无符号量,那么前面补前面补0。如果所用系统将字符处理成有符号量,那么扩。如果所用系统将字符处理成有符号量,那么扩展符号。展符号。v整型整型字符类型:直接将整型数据的最低八位赋给字符字符类型:直接将整型数据的最低八位赋给字符变量。变量。程序设计 cs.sjtu 2005.9程序设计-169赋值的嵌套赋值的嵌套v将赋值表达式作为更大的表达式的一局将赋值表达式作为更大的表达式的一局部部。如:。如:a=(x=6)+(y=7)等价于分等价于分别将别将x和和y的值设为的值设为6和和7,并将,并将6和和7相相加,结果存于变量加,结果存于变量av赋值运算符赋值运算符=的

106、优先级比算术运算符低的优先级比算术运算符低程序设计 cs.sjtu 2005.9程序设计-170多重赋值多重赋值a=b=c=5给给a,b,c均赋值均赋值5当用到多重赋值时,要保证所有的变量都是同类当用到多重赋值时,要保证所有的变量都是同类型的,以防止在自动类型转换时出现与预期不相型的,以防止在自动类型转换时出现与预期不相符的结果的可能性。如变量符的结果的可能性。如变量d d定义为定义为double,double,变量变量i i定义为定义为intint,语句,语句 d = i = 1.5; d = i = 1.5;的结果是:的结果是:i i等于等于1 1,d d等于等于 程序设计 cs.sjtu

107、 2005.9程序设计-171复合赋值运算复合赋值运算v其他运算符与赋值运算符结合的运算符称为复其他运算符与赋值运算符结合的运算符称为复合赋值运算符合赋值运算符v常用的复合赋值运算符有:常用的复合赋值运算符有:+=,=,*=,/=,%=v变量变量op=表达式表达式;等价于:变量等价于:变量=变量变量op表达式表达式;v如:如:balance+=deposit;balance=surcharge;x/=10;salary*=2;程序设计 cs.sjtu 2005.9程序设计-172第二章第二章通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量

108、符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-173自增、自减运算符自增、自减运算符v自增、自减运算符:自增、自减运算符:+,相当于相当于+=1和和=1,它有前缀和后缀两种用法它有前缀和后缀两种用法+k,k+,k,k,但含义有所不同。如:但含义有所不同。如:i=3j=i+i=4j=3j=+ii=4j=4j=ii=2j=3j=ii=2j=2程序设计 cs.sjtu 2005.9程序设计-174第二章第二章通过例子学习通过例子学习第一个程序第一个

109、程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-175强制类型转换强制类型转换v赋值和算术运算时会执行自动类型转换赋值和算术运算时会执行自动类型转换v如要想使如要想使4/5的结果是,而不是的结果是,而不是0,该怎么,该怎么办?可以将其中一个写成浮点数。例如:办?可以将其中一个写成浮点数。例如:4.0/5或或vintx=4,y=5;要想使要想使x/y的结果为而不是的结果为而不是0,该

110、怎么办?,该怎么办?v答案是:用强制类型转换答案是:用强制类型转换程序设计 cs.sjtu 2005.9程序设计-176强制类型转换强制类型转换v强制类型转换格式:强制类型转换格式:v类型名表达式类型名表达式v类型名类型名表达式表达式v例如,要想使两个整型变量例如,要想使两个整型变量x和和y出的结出的结果为果为double型,可以用以下语句型,可以用以下语句doublez;z=(double)x/y; 考虑:如果写为考虑:如果写为z=(double)(x/y)的结果如何?的结果如何?程序设计 cs.sjtu 2005.9程序设计-177转换类型转换类型v强制类型转换在强制类型转换在C+类型系统

111、中引入了一个漏洞类型系统中引入了一个漏洞v为了方便查找这些错误,为了方便查找这些错误,C+提供了在强制类型提供了在强制类型转换时指明转换的性质。转换时指明转换的性质。v转换的性质有四种:转换的性质有四种:静态转换静态转换(static_cast):用于编译器隐式执行的任何类:用于编译器隐式执行的任何类型转换型转换重解释转换重解释转换(reinterpret_cast)常量转换常量转换(const_cast)动态转换动态转换(dynamic_cast)v格式格式转换类型转换类型(表达式表达式)z=static_cast(x)/y;程序设计 cs.sjtu 2005.9程序设计-178第二章第二章

112、通过例子学习通过例子学习第一个程序第一个程序第二个程序第二个程序变量定义变量定义数据类型数据类型符号常量符号常量算术表达式算术表达式赋值表达式赋值表达式自增自减运算符自增自减运算符强制类型转换强制类型转换数据的输入输出数据的输入输出构思一个程序构思一个程序程序设计 cs.sjtu 2005.9程序设计-179输入流对象输入流对象cinv键盘流入的数据流,将键盘输入的数据键盘流入的数据流,将键盘输入的数据存入变量存入变量v格式:格式:cin变量变量cin变量变量1变量变量2变量变量n程序设计 cs.sjtu 2005.9程序设计-180用户的响应用户的响应v当程序执行到这个语句时会停下来等待用户

113、的输入当程序执行到这个语句时会停下来等待用户的输入v用户可以输入数据,用回车用户可以输入数据,用回车 结束。结束。v当有多个输入数据时,一般用空白字符空格、制表当有多个输入数据时,一般用空白字符空格、制表符和回车分隔。符和回车分隔。v如:如:a为整型,为整型,d为为double,那么对应于,那么对应于vcinad,用户的输入可以为,用户的输入可以为v1213.2 v12tab键键13.2 v12 13.2 33程序设计 cs.sjtu 2005.9程序设计-181cin.getv作用:从键盘接受一个字符作用:从键盘接受一个字符v用法:用法:ch;或;或ch=cin.get(),都是从,都是从键

114、盘输入一个字符并存放到变量键盘输入一个字符并存放到变量ch中中v对应的用户输入:对应的用户输入:cin.get()可以接收任意可以接收任意的字符,包括空白字符。的字符,包括空白字符。程序设计 cs.sjtu 2005.9程序设计-182如如a,b,c为字符型变量,对应语句为字符型变量,对应语句a=();b=();c=();如果输入如果输入abc ,那么,那么a的值是的值是a,b的值是空格,的值是空格,c的值是的值是b。如果将这个输入用于语句:如果将这个输入用于语句:cinabc,那么变量那么变量a、b、c的内容分别为的内容分别为a、b、c,因为空,因为空格被作为输入值之间的分隔符。格被作为输入

115、值之间的分隔符。程序设计 cs.sjtu 2005.9程序设计-183输出流对象输出流对象coutv将变量或表达式的内容显示在显示器上将变量或表达式的内容显示在显示器上v格式格式v输出一个变量的值:输出一个变量的值:couta;v输出多个变量的值:输出多个变量的值:coutabc;v输出表达式的结果:输出表达式的结果:cout“Helloworldv上述情况的组合:上述情况的组合:vcouta+b=a+b, =, =, =, , =, =, =, , != v 优先级:高于赋值运算符,低于算术运算符。优先级:高于赋值运算符,低于算术运算符。v 关系运算符内部:关系运算符内部:=和和 != =较

116、低较低v 结合性:左结合结合性:左结合v关系表达式关系表达式 v 用关系运算符将二个表达式连接起来称为关系表达用关系运算符将二个表达式连接起来称为关系表达式式 v 关系表达式的结果是:关系表达式的结果是: true true 或或 false falseeg.xya b = c d a b = c d 都是合法的关系表达式都是合法的关系表达式注意:注意:-2 -1 0 -2 -1 62(5+3)(62)程序设计 cs.sjtu 2005.9程序设计-194第第3章章逻辑思维及分支程序设计逻辑思维及分支程序设计关系表达式关系表达式逻辑表达式逻辑表达式If语句语句Switch语句语句程序设计 cs

117、.sjtu 2005.9程序设计-195逻辑表达式逻辑表达式v逻辑表达是用于实现更复杂的判断逻辑表达是用于实现更复杂的判断v逻辑运算符逻辑运算符v&(and)|(or)!(not)v优先级:优先级:!关系运算符关系运算符&|v逻辑表达式逻辑表达式v由逻辑运算符连接起来的表达式由逻辑运算符连接起来的表达式,其结果为其结果为“真真(true)或或“假假(false)程序设计 cs.sjtu 2005.9程序设计-196eg.写出以下问题的写出以下问题的C语言表达式语言表达式1检查字符变量检查字符变量a的内容是否为字母。的内容是否为字母。a=a&a=A&a=Z2整型变量整型变量m的内容是否为偶数的内

118、容是否为偶数m%2=0注意,不能写成注意,不能写成a a = a = = a = z z | | A A = a = = a 3 & 2 | 8 3 & 2 | 8 b)&(n=cd)a=1,b=2,c=2,d=4,m=1,n=1.问执行后问执行后m,n的值分别为多少?的值分别为多少?m=0,n=1程序设计 cs.sjtu 2005.9程序设计-199逻辑运算常见错误逻辑运算常见错误v当采用逻辑操作符当采用逻辑操作符时时,必须要细心,防止必须要细心,防止一些常见错误。例如:如果要想表达一些常见错误。例如:如果要想表达x即即不等于不等于2也不等于也不等于3,假设写成:,假设写成:vif(x!=2

119、|x!=3)/错误!错误!v正确形式为:正确形式为:vif(!(x=2|x=3)ORvif(x!=2&x!=3)程序设计 cs.sjtu 2005.9程序设计-200将关系写成表达式将关系写成表达式A A:洞庭最大,洪泽最小,鄱阳第三:洞庭最大,洪泽最小,鄱阳第三B B:洪泽最大,洞庭最小,鄱阳第二,太湖第三:洪泽最大,洞庭最小,鄱阳第二,太湖第三C C:洪泽最小,洞庭第三:洪泽最小,洞庭第三D D:鄱阳最大,太湖最小,洪泽第二,洞庭第三:鄱阳最大,太湖最小,洪泽第二,洞庭第三用用a,b,c,da,b,c,d分别表示四个湖的排序。分别表示四个湖的排序。A A表示洞庭,表示洞庭,b b表示洪表示

120、洪泽,泽,c c表示鄱阳,表示鄱阳,d d表示太湖。表示太湖。A A学生的答复可表示为:学生的答复可表示为:a=1 & b=4 & c=3a=1 & b=4 & c=3B B学生的答复可表示为:学生的答复可表示为:a=4 & b=1 & c=2 & d=3a=4 & b=1 & c=2 & d=3C C学生的答复可表示为:学生的答复可表示为:a=3 & b=4a=3 & b=4D D学生的答复可表示为:学生的答复可表示为:a=3 & b=2 & c=1 & d=4a=3 & b=2 & c=1 & d=4程序设计 cs.sjtu 2005.9程序设计-201vC+的一个重要的特点是可以将各种类

121、型的数据的一个重要的特点是可以将各种类型的数据混合使用。可以把一个逻辑类型的值用于算术表混合使用。可以把一个逻辑类型的值用于算术表达式。此时,达式。此时,true代表代表1,false代表代表0。v由于每位学生都只说对了一个,即每位同学的假由于每位学生都只说对了一个,即每位同学的假设干个关系表达式中只有一个为真,其余都为假。设干个关系表达式中只有一个为真,其余都为假。因此,因此,v对对A同学:同学:(a=1)+(b=4)+(c=3)=1v对对B同学:同学:(a=4)+(b=1)+(c=2)+(d=3)=1v对对C同学:同学:(a=3)+(b=4)=1v对对D同学:同学:(a=3)+(b=2)+

122、(c=1)+(d=4)=1v此题的答案就是找同时满足上面四个条件的答案此题的答案就是找同时满足上面四个条件的答案程序设计 cs.sjtu 2005.9程序设计-202第第3章章逻辑思维及分支程序设计逻辑思维及分支程序设计关系表达式关系表达式逻辑表达式逻辑表达式If语句语句Switch语句语句程序设计 cs.sjtu 2005.9程序设计-203条件检查与条件检查与if语句语句vif语句的格式语句的格式vif条件测试条件测试语句语句vif条件测试条件测试语句语句1else语句语句2v条件测试为条件测试为true时所执行的程序块叫做时所执行的程序块叫做then子子句,条件为句,条件为false时执

123、行的语句叫做时执行的语句叫做else子句。子句。veg.if(grade=60)vcout=60)vcout“passed;velsevcout“failed;程序设计 cs.sjtu 2005.9程序设计-204条件语句使用注意条件语句使用注意v条件的结果值应该是条件的结果值应该是 true true 或或 false false,它们是,它们是C+C+中中boolbool类型的值类型的值v事实上,条件可为任意表达式,不一定是关系事实上,条件可为任意表达式,不一定是关系表达式。表达式。0 0 为为falsefalse,非,非 0 0 为为truetrue。v常见的错误:条件测试是比较相等时,

124、用一个常见的错误:条件测试是比较相等时,用一个等号等号v合理的缩排,使程序结构更加清晰合理的缩排,使程序结构更加清晰程序设计 cs.sjtu 2005.9程序设计-205编一程序解一元二次方程编一程序解一元二次方程intmain()floata,b,c,x1,x2,dlt;cout“input3parameters:;couta;coutb;coutc;dlt=b*b4*a*c;if(dlt=0)x1=(-b+sqrt(dlt)/2/a;x2=(-b-sqrt(dlt)/2/a;coutx1x2;elsecout“noroot;return0;程序设计 cs.sjtu 2005.9程序设计-2

125、06判断闰年的程序判断闰年的程序#includeusingnamespacestd;intmain()intyear;boolresult;coutyear;result=(year%4=0&year%100!=0)|year%400=0;if(result)coutyear是闰年是闰年endl;elsecoutyear不是闰年不是闰年endl;return0;程序设计 cs.sjtu 2005.9程序设计-207if语句的嵌套语句的嵌套vIf语句的语句的then子句或子句或else子句是子句是if语句时,语句时,称为称为if语句的嵌套语句的嵌套v歧义性:歧义性:if语句可以没有语句可以没有e

126、lse子句,如子句,如vif(x100)if(x90)语句语句1elseif(x80)语句语句2else语句语句3else语句语句4;v配对原那么:每个配对原那么:每个else子句是和在它之前子句是和在它之前最近的一个没有最近的一个没有else子句的子句的if语句配对。语句配对。程序设计 cs.sjtu 2005.9程序设计-208缩进对齐缩进对齐v可以清晰地表示出层次可以清晰地表示出层次,便于程序员阅读,便于程序员阅读if (x 100) if (x 90) 语句1 else if (xy)?x:y;v?:运算符用于输出。例如,想输出一个布尔变量?:运算符用于输出。例如,想输出一个布尔变量f

127、lag的值,的值,如果直接用如果直接用coutflag;v那么当那么当flag为为“真时,输出为真时,输出为1;当;当flag为为“假时,输假时,输出为出为0。v如果我们想让如果我们想让flag为为“真时输出真时输出true,为,为“假时输出假时输出false,可以用,可以用if语句语句vif(flag)cout“true;velsecout“false;v看上去太罗嗦。但如果用?:运算符只需要一行看上去太罗嗦。但如果用?:运算符只需要一行vcout(a?true:flase)=90A90score=80 B80score=70 C70score=60 Dscore=90:cout=80:co

128、ut=70:cout=60:coutD;break;default:cout=90A90score=80 B80score=70 C70score=60 Dscore60E表达式表达式=成绩成绩/10switch(score/10)case10:case9:coutA;break;case8:coutB;break;case7:coutC;break;case6:coutD;break;default:coutE;程序设计 cs.sjtu 2005.9程序设计-217计算机自动出四那么运算计算计算机自动出四那么运算计算题题生成题目生成题目Switch(题目类型题目类型)case加法:显示题目,

129、输入和的值,判断正确与否加法:显示题目,输入和的值,判断正确与否case减法:显示题目,输入差的值,判断正确与否减法:显示题目,输入差的值,判断正确与否case乘法:显示题目,输入积的值,判断正确与否乘法:显示题目,输入积的值,判断正确与否case除法:显示题目,输入商和余数的值,判断正确与否除法:显示题目,输入商和余数的值,判断正确与否要求自动出要求自动出0 - 90 - 9之间的四那么运算题,并批改结果之间的四那么运算题,并批改结果程序设计 cs.sjtu 2005.9程序设计-218关键问题关键问题v如何让程序每次执行的时候都出不同的题目?如何让程序每次执行的时候都出不同的题目?v随机数

130、生成器随机数生成器rand():能随机生成:能随机生成0到到RAND_MAX之间的整型数之间的整型数v将生成的随机数映射到将生成的随机数映射到09之间:之间:rand()*10/(RAND_MAX+1)。v运算符的生成:用编码运算符的生成:用编码03表示四个运算符。因表示四个运算符。因此题目的生成就是生成此题目的生成就是生成03之间的随机数。之间的随机数。程序设计 cs.sjtu 2005.9程序设计-219随机数的种子随机数的种子v计算机产生的随机数称为计算机产生的随机数称为伪伪随机数,它是根据一随机数,它是根据一个算法计算出来的。个算法计算出来的。v系统为每个程序、每次执行指定的随机数的种

131、子系统为每个程序、每次执行指定的随机数的种子都是相同的,因此程序每次执行生成的随机数序都是相同的,因此程序每次执行生成的随机数序列都是相同的。列都是相同的。rand()种子种子1234812348程序设计 cs.sjtu 2005.9程序设计-220改变随机数的种子改变随机数的种子v设置种子的函数设置种子的函数srand:srand种子种子v如何让程序每次执行时选择的种子都不一如何让程序每次执行时选择的种子都不一样呢样呢?v选择系统时间为种子:选择系统时间为种子:time(NULL)取当取当前的系统时间。前的系统时间。程序设计 cs.sjtu 2005.9程序设计-221#include/包含

132、伪随机数生成函数包含伪随机数生成函数#include/包含取系统时间的函数包含取系统时间的函数#includeusingnamespacestd;intmain()intnum1,num2,op,result1,result2;/num1,num2:操作数,操作数,op:运算符,运算符,result1,result2:结果结果srand(time(NULL);/随机数种子初始化随机数种子初始化num1=rand()*10/(RAND_MAX+1);/生成运算数生成运算数num2=rand()*10/(RAND_MAX+1);/生成运算数生成运算数op=rand()*4/(RAND_MAX+1)

133、;/生成运算符生成运算符0+,1,2*,3/自动出题程序程序设计 cs.sjtu 2005.9程序设计-222switch(op)case0:coutnum1+num2result1;if(num1+num2=result1)coutyouarerightn;elsecoutyouarewrongn;break;case1:coutnum1-num2result1;if(num1-num2=result1)coutyouarerightn;elsecoutyouarewrongn;break;case2:coutnum1*num2result1;if(num1*num2=result1)cou

134、tyouarerightn;elsecoutyouarewrongn;break;程序设计 cs.sjtu 2005.9程序设计-223case3:coutnum1/num2result1;coutresult2;if(num1/num2=result1)&(num1%num2=result2)coutyouarerightn;elsecoutyouarewrongn;break;return0;程序设计 cs.sjtu 2005.9程序设计-224该程序的缺陷该程序的缺陷v每次执行只能出一道题每次执行只能出一道题v减法可能出现负值减法可能出现负值v除法可能出现除除法可能出现除0v结果太单调结

135、果太单调程序设计 cs.sjtu 2005.9程序设计-225小结小结v本章主要介绍了计算机实现逻辑思维的机制。本章主要介绍了计算机实现逻辑思维的机制。主要包括两个方面:主要包括两个方面:如何表示一个逻辑判断如何表示一个逻辑判断如何根据逻辑判断的结果执行不同的处理如何根据逻辑判断的结果执行不同的处理v逻辑判断逻辑判断关系表达式实现关系表达式实现逻辑表达式逻辑表达式v根据逻辑判断执行不同的处理根据逻辑判断执行不同的处理if语句语句switch语句语句程序设计 cs.sjtu 2005.9程序设计-226第第4章章循环控制循环控制重复重复N次循环次循环While循环循环Dowhile循环循环循环的

136、中途退出循环的中途退出枚举法枚举法贪婪法贪婪法程序设计 cs.sjtu 2005.9程序设计-227重复重复N次操作次操作v某一组语句要重复执行某一组语句要重复执行N次次v“重复重复n次循环通常用次循环通常用for语句实现,语句实现,如将如将1到到100十个数相加可写为:十个数相加可写为:vs=0;vfor(i=1;i=100;+i)s+=i;i称为循环变量称为循环变量循环条件每次循环后循环变量的变化程序设计 cs.sjtu 2005.9程序设计-228for循环语句循环语句v格式:格式:vforfor表达式表达式1 1;表达式;表达式2 2;表达式;表达式3 3v 语句语句v执行过程:执行过

137、程:v1.1.执行表达式执行表达式1 1v2.2.执行表达式执行表达式2 2v3.3.如果表达式如果表达式2 2的结果为的结果为“true“true,那么执行,那么执行循环体和表达式循环体和表达式3 3,然后回到,然后回到2 2,否那么,否那么forfor语语句执行结束句执行结束循环体循环体循环控制行循环控制行程序设计 cs.sjtu 2005.9程序设计-229for循环语句循环语句续续续续v作为计数循环,可以理解为作为计数循环,可以理解为for(for(循环变量赋初值;循环条件;循环变量增值循环变量赋初值;循环条件;循环变量增值) ) 符合循环条件时的执行语句符合循环条件时的执行语句v循环

138、体所有语句的一次完全执行称为一个循环循环体所有语句的一次完全执行称为一个循环周期周期v循环体可以是复合语句或空语句循环体可以是复合语句或空语句程序设计 cs.sjtu 2005.9程序设计-230空语句和复合语句空语句和复合语句v单个分号组成的语句成为空语句单个分号组成的语句成为空语句v用用括起来的一组语句称为复合语句。括起来的一组语句称为复合语句。在逻辑上看成一个语句。在逻辑上看成一个语句。v复合语句可以放在任何单语句出现的地复合语句可以放在任何单语句出现的地方方v在复合语句中可以定义变量在复合语句中可以定义变量程序设计 cs.sjtu 2005.9程序设计-231For循环实例循环实例v某

139、班级有某班级有100个学生,设计一程序统计该班个学生,设计一程序统计该班级某门考试成绩中的最高分、最低分和平级某门考试成绩中的最高分、最低分和平均分。均分。v方案一:先输入方案一:先输入100个整型数,保存在各自个整型数,保存在各自的变量中。然后依次检查这的变量中。然后依次检查这100个数,找出个数,找出最大的和最小的。在找的过程中顺便可以最大的和最小的。在找的过程中顺便可以把所有的数都加起来。最后将总和除把所有的数都加起来。最后将总和除100就就得到了平均值。得到了平均值。程序设计 cs.sjtu 2005.9程序设计-232方案一的缺陷方案一的缺陷v需要定义需要定义100个变量个变量v需要

140、输入需要输入100个变量的值个变量的值v从从100个变量中找出最大者,需要个变量中找出最大者,需要100个个if语句语句v从从100个变量中找出最小者,需要个变量中找出最小者,需要100个个if语句语句v将这将这100个变量加起来需要一个长长的算个变量加起来需要一个长长的算术表达式术表达式程序设计 cs.sjtu 2005.9程序设计-233方案二方案二v每个学生的分数在处理过后就没用了,每个学生的分数在处理过后就没用了,为此,可以用一个变量保存当前正在处为此,可以用一个变量保存当前正在处理的分数理的分数v每次输入分数的同时将它们加起来:每次输入分数的同时将它们加起来:70加加40等于等于11

141、0,110加加80等于等于190。并。并记住最低分的和最高分的值。上述过程记住最低分的和最高分的值。上述过程重复重复100次。次。程序设计 cs.sjtu 2005.9程序设计-234方案二的实现方案二的实现v定义:定义:intvalue,total,max,min;v当输入每个数值时必须执行下面的步骤,这可当输入每个数值时必须执行下面的步骤,这可以用以用for循环实现循环实现v请求用户输入一个整数值,将它存储在变量请求用户输入一个整数值,将它存储在变量value中。中。v将将value参加到保存当前和的变量参加到保存当前和的变量total中。中。v如果如果value大于大于max,将,将va

142、lue存于存于max。v如果如果value小于小于min,将,将value存于存于min。程序设计 cs.sjtu 2005.9程序设计-235#includeusingnamespacestd;intmain()intvalue,total,max,min,i;/value:当前输入数据,:当前输入数据,i为循环变量为循环变量total=0;max=0;min=100;/变量的初始化变量的初始化for(i=1;i=100;+i)coutn请输入第请输入第ivalue;total+=value;if(valuemax)max=value;if(valuemin)min=value;coutn最

143、高分最高分:maxendl;cout最低分最低分:minendl;cout平均分平均分:total/100endl;return0;注注意意缩缩进进程序设计 cs.sjtu 2005.9程序设计-236For循环的进一步讨论循环的进一步讨论vFor循环的三个表达式可以是任意表达式循环的三个表达式可以是任意表达式v三个表达式都是可选的。三个表达式都是可选的。v如果循环不需要任何初始化工作,那么表如果循环不需要任何初始化工作,那么表达式达式1可以缺省。如循环前需要做多个初可以缺省。如循环前需要做多个初始化工作,可以将多个初始化工作组合成始化工作,可以将多个初始化工作组合成一个逗号表达式,作为表达式

144、一个逗号表达式,作为表达式1。程序设计 cs.sjtu 2005.9程序设计-237逗号表达式逗号表达式v格式:表达式格式:表达式1,表达式,表达式2,,表达式表达式nv执行过程:先执行表达式执行过程:先执行表达式1,再执行表达式,再执行表达式2,再执行表达式,再执行表达式n,整个表达式的计算结果,整个表达式的计算结果为最后一个表达式的值为最后一个表达式的值v逗号运算符的优先级是所有运算符中最低的逗号运算符的优先级是所有运算符中最低的v如如a的初值为的初值为0,那么表达式,那么表达式va+=1,a+=2,a+=3,a+=4,a+=5v的结果为的结果为15程序设计 cs.sjtu 2005.9程

145、序设计-238v有了逗号表达式,从有了逗号表达式,从1加到加到100的问题就的问题就可以只用一个语句:可以只用一个语句:for(i=1,s=0;i=100;+i)s+=i;或将所有的初始化都放在循环外,即或将所有的初始化都放在循环外,即i=1;s=0;for(;i=100;+i)s+=i;v建议还是用建议还是用 s=0;s=0; for (i=1; i=100; +i) s+=i; for (i=1; i=100; +i) s+=i;程序设计 cs.sjtu 2005.9程序设计-239For循环的进一步讨论循环的进一步讨论续续v表达式表达式2也不一定是关系表达式。它可以是逻辑也不一定是关系表

146、达式。它可以是逻辑表达式,甚至可以是算术表达式。当表达式表达式,甚至可以是算术表达式。当表达式2是是算术表达式时,只要表达式的值为非算术表达式时,只要表达式的值为非0,就执行,就执行循环体,表达式的值为循环体,表达式的值为0时退出循环。时退出循环。v如果表达式如果表达式2省略,即不判断循环条件,循环将省略,即不判断循环条件,循环将无终止地进行下去。无终止地进行下去。v无终止的循环称为无终止的循环称为“死循环死循环v最简单的死循环是最简单的死循环是for(;);v要结束一个无限循环,必须从键盘上输入特殊的要结束一个无限循环,必须从键盘上输入特殊的命令以中断程序执行并强制退出命令以中断程序执行并强

147、制退出程序设计 cs.sjtu 2005.9程序设计-240For循环的进一步讨论循环的进一步讨论续续v表达式表达式3也可以是任何表达式,一般为赋值表也可以是任何表达式,一般为赋值表达式或逗号表达式。表达式达式或逗号表达式。表达式3是在每个循环周是在每个循环周期结束后对循环变量的修正。表达式期结束后对循环变量的修正。表达式3也可以也可以省略,此时做完循环体后直接执行表达式省略,此时做完循环体后直接执行表达式2。v如从如从1加到加到100,可以写为,可以写为s=0;for(i=1;i=100;)s+=i,i+;或或s=0;for(i=1;i=100;s+=i,i+);程序设计 cs.sjtu 2

148、005.9程序设计-241循环的嵌套循环的嵌套v将一个将一个for循环嵌入到另一个循环嵌入到另一个for循环中循环中v内层的内层的for循环在外层循环的每一个周期循环在外层循环的每一个周期中都将执行它的所有的周期中都将执行它的所有的周期v每个每个for循环都要有一个自己的循环变量循环都要有一个自己的循环变量以防止循环变量间的互相干扰以防止循环变量间的互相干扰程序设计 cs.sjtu 2005.9程序设计-242打印九九乘法表打印九九乘法表#includeusingnamespacestd;voidmain()inti,j;for(i=1;i=9;+i)for(j=1;j=9;+j)couti*

149、jt;coutendl;程序设计 cs.sjtu 2005.9程序设计-243第第4章章循环控制循环控制重复重复N次循环次循环While循环循环Dowhile循环循环循环的中途退出循环的中途退出枚举法枚举法贪婪法贪婪法程序设计 cs.sjtu 2005.9程序设计-244While循环循环v如何对不同人数的班级完成分数统计任务如何对不同人数的班级完成分数统计任务?v方法一:在程序的开始局部请求用户输入数据方法一:在程序的开始局部请求用户输入数据个数,并将之存放在某个变量中,以此来替换个数,并将之存放在某个变量中,以此来替换for语句控制行中使用的常量语句控制行中使用的常量100v方法二:定义一

150、个特殊的输入数据,用户可以方法二:定义一个特殊的输入数据,用户可以通过输入该数据来标识输入序列的结束通过输入该数据来标识输入序列的结束v方法二需要另外一种的循环控制结构方法二需要另外一种的循环控制结构程序设计 cs.sjtu 2005.9程序设计-245While循环语句循环语句v格式:格式:while表达式表达式语句语句v执行过程:先计算出条件表达式的值。如果是执行过程:先计算出条件表达式的值。如果是false,循环终止,并接着执行在整个,循环终止,并接着执行在整个while循循环之后的语句。如果是环之后的语句。如果是true,整个循环体将被,整个循环体将被执行,而后又回到执行,而后又回到w

151、hile语句的第一行,再次语句的第一行,再次对条件进行检查。对条件进行检查。v用途:用于循环次数不定的循环。循环是否结用途:用于循环次数不定的循环。循环是否结束取决于某一个条件是否成立束取决于某一个条件是否成立程序设计 cs.sjtu 2005.9程序设计-246While语句实例语句实例v设计一个程序,统计某个班级某门考试设计一个程序,统计某个班级某门考试成绩中的最高分、最低分和平均分。当成绩中的最高分、最低分和平均分。当输入的分数为输入的分数为1时,输入结束时,输入结束程序设计 cs.sjtu 2005.9程序设计-247intmain()intvalue,total,max,min,no

152、OfInput;/total总分,总分,noOfInput人数人数total=0;max=0;min=100;noOfInput=0;/置初值置初值coutvalue;while(value!=-1)+noOfInput;total+=value;if(valuemax)max=value;if(valuemin)min=value;coutn请输入第请输入第noOfInput+1value;coutn最高分:最高分:maxendl;cout最低分:最低分:minendl;cout平均分:平均分:total/noOfInput0.000001) while (p0.000001) ex +=

153、p; ex += p; 计算新的计算新的p p; 问题:如何计算p?计算第i个p,需要两个i次的循环。第一个循环计算xi,第二个循环计算i!解决方案:从前一项计算后一项。如果p是第i项的值,那么第 i+1 项的值为 p * x / ( i + 1) 程序设计 cs.sjtu 2005.9程序设计-249int main()int main()double ex, x, p;/exdouble ex, x, p;/ex存储存储e ex x的值,的值,p p保存当前项的值保存当前项的值 int i;int i; cout cout x; cin x; ex=0; p=1; i=0; ex=0; p

154、=1; i=0; while (p 1e-6) while (p 1e-6) ex += p; ex += p; +i; +i; p = p * x / i; p = p * x / i; cout e cout e的的 x x 次方等于次方等于: ex endl; ex endl; return 0;return 0;程序设计 cs.sjtu 2005.9程序设计-250例子:将输入句子中的字符全部例子:将输入句子中的字符全部输出为大写输出为大写/Capitalizelowercaselettersintmain()charc;coutc;while(c!=.)if(a=c&c=z)cout

155、c+Aa;elsecoutc;return0;程序设计 cs.sjtu 2005.9程序设计-251第第4章章循环控制循环控制重复重复N次循环次循环While循环循环Dowhile循环循环循环的中途退出循环的中途退出枚举法枚举法贪婪法贪婪法程序设计 cs.sjtu 2005.9程序设计-252DoWhile循环语句循环语句v格式:格式: do do 语句语句 while ( while (表达式表达式) ) v执行过程:先执行循环体,然后判断循环条件。如条执行过程:先执行循环体,然后判断循环条件。如条件成立,继续循环,直到条件为假件成立,继续循环,直到条件为假v如将假设干个输入数相加,直到输入

156、如将假设干个输入数相加,直到输入0 0为止。为止。v total = 0; total = 0;v do dov cout “ ? “; cout value ; cin value ;v total += value; total += value;v while (value != 0); while (value != 0);程序设计 cs.sjtu 2005.9程序设计-253第第4章章循环控制循环控制重复重复N次循环次循环While循环循环Dowhile循环循环循环的中途退出循环的中途退出枚举法枚举法贪婪法贪婪法程序设计 cs.sjtu 2005.9程序设计-254循环的中途退出循环

157、的中途退出v考虑一个读入数据直到读到标志值的问题。如考虑一个读入数据直到读到标志值的问题。如用自然语言描述,基于标志的循环的结构由以用自然语言描述,基于标志的循环的结构由以下步骤组成:下步骤组成:v读入一个值读入一个值v如果读入值与标志值相等,那么退出循环如果读入值与标志值相等,那么退出循环v执行在读入那个特定值情况下需要执行的语句执行在读入那个特定值情况下需要执行的语句v当一个循环中有一些操作必须在条件测试之前当一个循环中有一些操作必须在条件测试之前执行时,称为循环的中途退出问题。执行时,称为循环的中途退出问题。程序设计 cs.sjtu 2005.9程序设计-255问题问题v由于循环语句是先

158、判断条件再决定是否执行循环由于循环语句是先判断条件再决定是否执行循环体,循环的中途退出将使得循环体中的某些语句体,循环的中途退出将使得循环体中的某些语句必须重复出现。必须重复出现。v基于标志的循环结构被改为:基于标志的循环结构被改为:v读入一个值读入一个值vWhile读入值与标志值不相等读入值与标志值不相等v执行在读入那个特定值情况下需要执行的语执行在读入那个特定值情况下需要执行的语句句v读入一个值读入一个值v程序设计 cs.sjtu 2005.9程序设计-256解决方案解决方案vbreak语句:跳出循环语句:跳出循环v上述问题可以用以下方案解决:上述问题可以用以下方案解决:vwhile(tr

159、ue)v提示用户并读入数据提示用户并读入数据vif(value=标志标志)break;v根据数据作出处理根据数据作出处理vvcontinue语句:跳出当前循环周期语句:跳出当前循环周期程序设计 cs.sjtu 2005.9程序设计-257第第4章章循环控制循环控制重复重复N次循环次循环While循环循环Dowhile循环循环循环的中途退出循环的中途退出枚举法枚举法贪婪法贪婪法程序设计 cs.sjtu 2005.9程序设计-258枚举法枚举法v对所有可能的情况一种一种去尝试,直对所有可能的情况一种一种去尝试,直到找到正确的答案。到找到正确的答案。v枚举法的实现根底是循环。枚举法的实现根底是循环。

160、程序设计 cs.sjtu 2005.9程序设计-259枚举法实例一枚举法实例一v用用50元钱买了三种水果。各种水果加起来一共元钱买了三种水果。各种水果加起来一共100个。西个。西瓜瓜5元一个,苹果元一个,苹果1元一个,桔子元一个,桔子1元元3个,设计一程序输出个,设计一程序输出每种水果各买了几个每种水果各买了几个v它有两个约束条件:它有两个约束条件:第一是三种水果一共第一是三种水果一共100个;个;第二是三种水果一共花了第二是三种水果一共花了50元元v可以按一个约束条件列出所有可行的情况,然后对每个可可以按一个约束条件列出所有可行的情况,然后对每个可能解检查它是否满足第二个约束条件能解检查它是

161、否满足第二个约束条件。也可以用第二个。也可以用第二个约束条件列出所有情况,然后对每个可能解检查它是否满约束条件列出所有情况,然后对每个可能解检查它是否满足第一个约束条件足第一个约束条件。程序设计 cs.sjtu 2005.9程序设计-260#includeusingnamespacestd;intmain()intmellon,apple,orange;/分别表示西瓜数、苹果数和桔子数分别表示西瓜数、苹果数和桔子数for(mellon=1;mellon10;+mellon)/对每种可能的西瓜数对每种可能的西瓜数for(apple=1;apple50-5*mellon;+apple)/ 当西瓜数

162、给定后可能的苹果数当西瓜数给定后可能的苹果数orange=3*(50-5*mellon-apple);/剩下的钱全买了桔子剩下的钱全买了桔子if(mellon+apple+orange=100)/三种水果数之和是否为三种水果数之和是否为100coutmellon:mellon;coutapple:apple;coutorange:orangeendl;return0;程序设计 cs.sjtu 2005.9程序设计-261执行结果执行结果Mellon:1apple:18orange:81Mellon:2apple:11orange:87Mellon:3apple:4orange:93程序设计 c

163、s.sjtu 2005.9程序设计-262实例二实例二四大湖问题四大湖问题上地理课时,四个学生答复我国四大湖的大小时分别说:上地理课时,四个学生答复我国四大湖的大小时分别说:甲:洞庭最大,洪泽最小,鄱阳第三甲:洞庭最大,洪泽最小,鄱阳第三乙:洪泽最大,洞庭最小,鄱阳第二,太湖第三乙:洪泽最大,洞庭最小,鄱阳第二,太湖第三丙:洪泽最小,洞庭第三丙:洪泽最小,洞庭第三丁:鄱阳最大,太湖最小,洪泽第二,洞庭第三丁:鄱阳最大,太湖最小,洪泽第二,洞庭第三对于每个湖的大小,每个人仅答对一个,设计一程序让对于每个湖的大小,每个人仅答对一个,设计一程序让计算机通过这些信息去判别四个湖的大小。计算机通过这些信

164、息去判别四个湖的大小。程序设计 cs.sjtu 2005.9程序设计-263解题思路解题思路v如果如果用用a,b,c,d分别表示四个湖的排序。分别表示四个湖的排序。a表示洞庭湖,表示洞庭湖,b表示洪泽湖,表示洪泽湖,c表示鄱阳湖,表示鄱阳湖,d表示太湖。我们可以表示太湖。我们可以假设:假设:洞庭最大,洪泽第二,鄱阳第三,太湖第四,洞庭最大,洪泽第二,鄱阳第三,太湖第四,然后检查每位同学是否都讲对了一个。如果不是,再然后检查每位同学是否都讲对了一个。如果不是,再尝试下一种情况:洞庭最大,洪泽第二,鄱阳第四,尝试下一种情况:洞庭最大,洪泽第二,鄱阳第四,太湖第三,再检查每位同学是否都讲对了一个。尝

165、试太湖第三,再检查每位同学是否都讲对了一个。尝试所有可能的情况,直到满足每位同学都讲对一个为止。所有可能的情况,直到满足每位同学都讲对一个为止。程序设计 cs.sjtu 2005.9程序设计-264枚举法枚举法续续续续v为了尝试所有情况,我们需要假设洞庭为了尝试所有情况,我们需要假设洞庭湖可能是最大,也可能是第二、第三或湖可能是最大,也可能是第二、第三或第四。因此,第四。因此,a的值可能从的值可能从1变到变到4。同样,。同样,b,c,d的值也都可能从的值也都可能从1变到变到4。为此,。为此,我们需要一个控制结构,使我们需要一个控制结构,使a,b,c,d的的值能自动从值能自动从1变到变到4。这种

166、结构就是循环。这种结构就是循环结构。结构。程序设计 cs.sjtu 2005.9程序设计-265四大湖排列问题的解四大湖排列问题的解main()inta,b,c,d;for(a=1;a=4;+a)for(b=1;b=4;+b)if(a=b)continue;elsefor(c=1;c=4;+c)if(c=a|c=b)continue;elsed=10abc;if(a=1)+(b=4)+(c=3)=1&(b=1)+(a=4)+(c=2)+(d=3)=1&(b=4)+(a=3)=1&(c=1)+(d=4)+(b=2)+(a=3)=1)coutabcd;问题:效率差解决方法:一旦找到答案就应该结束程

167、序设计 cs.sjtu 2005.9程序设计-266main()inta,b,c,d;boolflag=false;for(a=1;a=4;+a)for(b=1;b=4;+b)if(a=b)continue;elsefor(c=1;c=4;+c)if(c=a|c=b)continue;elsed=10abc;if(a=1)+(b=4)+(c=3)=1&(b=1)+(a=4)+(c=2)+(d=3)=1&(b=4)+(a=3)=1&(c=1)+(d=4)+(b=2)+(a=3)=1)coutabcd;flag=true;break;if(flag)break;if(flag)break;改进版1

168、:程序不够简练程序设计 cs.sjtu 2005.9程序设计-267main()inta,b,c,d;boolflag=false;for(a=1;a=4&!flag;+a)for(b=1;b=4&!flag;+b)if(a=b)continue;elsefor(c=1;c=4;+c)if(c=a|c=b)continue;elsed=10abc;if(a=1)+(b=4)+(c=3)=1&(b=1)+(a=4)+(c=2)+(d=3)=1&(b=4)+(a=3)=1&(c=1)+(d=4)+(b=2)+(a=3)=1)coutabcd;flag=true;break;改进版2程序设计 cs.

169、sjtu 2005.9程序设计-268列出列出ABC三个字母的全排列三个字母的全排列v解题思路:解题思路:让第一个位置的值从让第一个位置的值从A依次变到依次变到C让第一个位置的值从让第一个位置的值从A依次变到依次变到C让第一个位置的值从让第一个位置的值从A依次变到依次变到C注意三个位置的值不能相同注意三个位置的值不能相同v可以用一个三层的嵌套循环实现,循环变量是可以用一个三层的嵌套循环实现,循环变量是字符类型字符类型程序设计 cs.sjtu 2005.9程序设计-269intmain()charc1,c2,c3;for(c1=A;c1=C;+c1)for(c2=A;c2=C;+c2)if(c1

170、=c2)continue;elsefor(c3=A;c3=C;+c3)if(c3=a1|c3=c2)continue;elsecoutc1c2c3endl;程序设计 cs.sjtu 2005.9程序设计-270第第4章章循环控制循环控制重复重复N次循环次循环While循环循环Dowhile循环循环循环的中途退出循环的中途退出枚举法枚举法贪婪法贪婪法程序设计 cs.sjtu 2005.9程序设计-271贪婪法的根本思想贪婪法的根本思想v在求解过程的每一步都选取一个局部最优在求解过程的每一步都选取一个局部最优的策略,把问题规模缩小,最后把每一步的策略,把问题规模缩小,最后把每一步的结果合并起来形成

171、一个全局解。的结果合并起来形成一个全局解。v根本步骤:根本步骤:v从某个初始解出发从某个初始解出发v采用迭代的过程,当可以向目标前进一步采用迭代的过程,当可以向目标前进一步时,就根据局最优策略,得到一个局部解,时,就根据局最优策略,得到一个局部解,缩小问题规模。缩小问题规模。v将所有解综合起来将所有解综合起来程序设计 cs.sjtu 2005.9程序设计-272硬币找零问题硬币找零问题v对于一种货币,有面值为对于一种货币,有面值为1分分,2分分,5分和分和1角的硬币,最少需要多少个硬币来找出角的硬币,最少需要多少个硬币来找出K分钱的零钱。分钱的零钱。程序设计 cs.sjtu 2005.9程序设

172、计-273贪婪法解题思想贪婪法解题思想v不断地使用面值最大的硬币。如要找零不断地使用面值最大的硬币。如要找零的值小于最大的硬币值,那么尝试第二的值小于最大的硬币值,那么尝试第二大的硬币。依此类推。大的硬币。依此类推。v不断尝试的过程就是循环不断尝试的过程就是循环程序设计 cs.sjtu 2005.9程序设计-274#includeusingnamespacestd;#defineONEFEN1#defineTWOFEN2#defineFIVEFEN5#defineONEJIAO10intmain()intmoney;intonefen=0,twofen=0,fivefen=0,onejiao=

173、0;coutmoney;程序设计 cs.sjtu 2005.9程序设计-275/不断尝试每一种硬币不断尝试每一种硬币while(money=ONEJIAO)onejiao+;money-=ONEJIAO;while(money=FIVEFEN)fivefen+;money-=FIVEFEN;while(money=TWOFEN)twofen+;money-=TWOFEN;while(money=ONEFEN)onefen+;money-=ONEFEN;/输出结果输出结果cout1角硬币数:角硬币数:onejiaoendl;cout5分硬币数:分硬币数:fivefenendl;cout2分硬币数

174、:分硬币数:twofenendl;cout1分硬币数:分硬币数:onefenendl;return0;程序设计 cs.sjtu 2005.9程序设计-276小结小结v计算机的强项是不厌其烦地做同样的操作,这计算机的强项是不厌其烦地做同样的操作,这是通过循环语句实现的是通过循环语句实现的v循环语句:循环语句:while、do.while和和forv基于循环的算法:基于循环的算法:枚举法:对某些问题,在寻找它的解时需要检查枚举法:对某些问题,在寻找它的解时需要检查所有的可能的方案,从中找出可行解。所有的可能的方案,从中找出可行解。贪婪法:可用于求问题的最优解。但不一定对所贪婪法:可用于求问题的最优

175、解。但不一定对所有问题都能得到最优解。有问题都能得到最优解。程序设计 cs.sjtu 2005.9程序设计-277第第5章章批量数据处理批量数据处理数组数组v一维数组一维数组v排序和查找排序和查找v二维数组二维数组v字符串字符串程序设计 cs.sjtu 2005.9程序设计-278一维数组一维数组v有时,我们需要存储一批同类型的数据,有时,我们需要存储一批同类型的数据,如有十只羊,主人要保存每只羊的重量,如有十只羊,主人要保存每只羊的重量,并从中挑选一只最肥的羊。并从中挑选一只最肥的羊。v解决方案:可以定义十个解决方案:可以定义十个double型的变量型的变量sheep1,sheep10,然后

176、比较十个值,找,然后比较十个值,找出一个最大值。出一个最大值。v缺点:缺点:v定义了十个变量。要是有定义了十个变量。要是有100只羊就要定义只羊就要定义100个变量个变量v程序只能用顺序结构程序只能用顺序结构v如果羊群规模发生变化,程序就得重写如果羊群规模发生变化,程序就得重写程序设计 cs.sjtu 2005.9程序设计-279数组数组v数组是保存一组同类元素的数据类型,它有两数组是保存一组同类元素的数据类型,它有两个特征:个特征:v数组元素是有序的数组元素是有序的v数组元素是同类的数组元素是同类的v定义数组要定义三个根本内容:定义数组要定义三个根本内容:v数组名字数组名字v数组元素的类型数

177、组元素的类型v数组的大小数组的大小程序设计 cs.sjtu 2005.9程序设计-280数组的定义数组的定义v格式:格式:类型类型数组名数组名元素个数元素个数;其中,元素个数必须是常量。如:其中,元素个数必须是常量。如:intintarray10;但但intn=10;intintarrayn;是错的是错的v常用的方法是将元素个数定义为一个常量。如:常用的方法是将元素个数定义为一个常量。如:#defineNumOfElement10intintarrayNumOfElement;相当于相当于intintarray10;程序设计 cs.sjtu 2005.9程序设计-281初始化初始化v定义数组时

178、可以对数组初始化定义数组时可以对数组初始化vfloatx5=1.1,0.2,33.0,4.4,5.05;v初始化表的长度短于要被初始化的数组元初始化表的长度短于要被初始化的数组元素数目,那么剩余元素被初始化为素数目,那么剩余元素被初始化为0。v带有初始化的数组可以不定义数组规模,带有初始化的数组可以不定义数组规模,编译器根据初值的个数决定数组的大小编译器根据初值的个数决定数组的大小vinta=1,2,3,4,5;那么默认数组大小那么默认数组大小为为5初始化表初始化表程序设计 cs.sjtu 2005.9程序设计-282数组元素数组元素v数组元素的使用是通过数组名及元素的序数组元素的使用是通过数

179、组名及元素的序号来指定,如号来指定,如intarray2。当数组的大小为。当数组的大小为n时,元素的序号为时,元素的序号为0n1。v元素的序号称为下标。程序中,下标可为元素的序号称为下标。程序中,下标可为整数、整型变量或结果为整型的任意表达整数、整型变量或结果为整型的任意表达式。正是这一特性,使得数组的应用非常式。正是这一特性,使得数组的应用非常灵活。灵活。程序设计 cs.sjtu 2005.9程序设计-283数组在内存中数组在内存中v定义数组就是定义了一块连续的空间,定义数组就是定义了一块连续的空间,空间的大小等于元素数空间的大小等于元素数*每个元素所占的每个元素所占的空间大小。空间大小。v

180、数组元素按序存放在这块空间中。数组元素按序存放在这块空间中。程序设计 cs.sjtu 2005.9程序设计-284为数组分配空间为数组分配空间v如:如:intintarray5;占用了占用了20个字节,因为每个字节,因为每个整型数占四个字节。如给个整型数占四个字节。如给intarray3赋值为赋值为3,如果这块空间的起始地址为,如果这块空间的起始地址为100,那么在内,那么在内存中的情况是:存中的情况是:v当你引用变量当你引用变量intarrayidx时,系统计算它的时,系统计算它的地址地址100+idx*4,对该地址的内容进行操作。,对该地址的内容进行操作。随机值随机值随机值随机值随机值随机

181、值3随机值随机值100103104107108111112115116119程序设计 cs.sjtu 2005.9程序设计-285数组下标超界问题数组下标超界问题vC/C+语言不检查数组下标的超界。如定义数语言不检查数组下标的超界。如定义数组组intintarray10;合法的下标范围是合法的下标范围是09,但如果你引用但如果你引用intarray10,系统不会报错。,系统不会报错。如数组如数组intarray的起始地址是的起始地址是1000,当引用,当引用intarray10时,系统对时,系统对1040号内存进行操作。号内存进行操作。而而1040可能是另一个变量的地址可能是另一个变量的地址v

182、解决方法:由程序员自己控制。在对下标变量解决方法:由程序员自己控制。在对下标变量进行操作前,先检查下标的合法性。进行操作前,先检查下标的合法性。程序设计 cs.sjtu 2005.9程序设计-286数组的操作数组的操作v数组的操作主要是数组元素的操作。数组的操作主要是数组元素的操作。v不能直接对数组名进行赋值。如:不能直接对数组名进行赋值。如:intarray=30是是错的。事实上,数组名中存放的是该数组的起始错的。事实上,数组名中存放的是该数组的起始地址。地址。veg.数组的输入输出数组的输入输出intmain()intintarray10,idx;for(idx=0;idxintarray

183、idx;coutendl;for(idx=0;idx=9;+idx)coutintarrayidx;程序设计 cs.sjtu 2005.9程序设计-287数组应用数组应用羊群问题羊群问题intmain()doublesheep10,max=0;inti,maxNum;for(i=0;i10;+i)cout“请输入第请输入第isheepi;for(i=0;imax)max=sheepi;maxNum=i;cout“最重的羊是第最重的羊是第maxNum“只只endl;cout“它的重量是它的重量是maxendl;return0;程序设计 cs.sjtu 2005.9程序设计-288使羊群问题的程序

184、更通用使羊群问题的程序更通用v方案一:可以将羊的个数定义成一个符方案一:可以将羊的个数定义成一个符号常量。需要时,可以修改这个符号常号常量。需要时,可以修改这个符号常量的值量的值v方案二:定义一个足够大的数组存放羊方案二:定义一个足够大的数组存放羊群的信息,定义一个输入结束标志,用群的信息,定义一个输入结束标志,用while循环解决这个问题。可参照分数统循环解决这个问题。可参照分数统计程序计程序程序设计 cs.sjtu 2005.9程序设计-289方案一方案一#defineNUM10intmain()doublesheepNUM,max=0;inti,maxNum;for(i=0;iNUM;+

185、i)cout“请输入第请输入第isheepi;for(i=0;imax)max=sheepi;maxNum=i;cout“最重的羊是第最重的羊是第maxNum“只只endl;cout“它的重量是它的重量是maxendl;return0;程序设计 cs.sjtu 2005.9程序设计-290数组应用数组应用v从终端输入一串字符,统计字符串中个字母出现的从终端输入一串字符,统计字符串中个字母出现的次数。次数。v解决方法:解决方法:方法一:用方法一:用26个整型变量计数个整型变量计数26个字母,对输入字符串中个字母,对输入字符串中的每一字符用的每一字符用switch语句分别计数。语句分别计数。方法二

186、:用一个方法二:用一个26个元素的数组,如个元素的数组,如num26,表示计数。表示计数。num0存放存放a的个数的个数,num1存放存放b的个数的个数。这样对每一。这样对每一个字符不必用个字符不必用switch,而只需用一个简单的计算:,而只需用一个简单的计算:+numtoupper(ch)A;就可以了。就可以了。程序设计 cs.sjtu 2005.9程序设计-291#include#includeusingnamespacestd;intmain()intcount26=0,i;charch;ch=toupper(cin.get();while(ch=A&ch=Z)+countch-A;c

187、h=toupper(cin.get();for(i=0;i26;+i)coutcountit;return0;程序设计 cs.sjtu 2005.9程序设计-292第第5章章批量数据处理批量数据处理数组数组v一维数组一维数组v排序和查找排序和查找v二维数组二维数组v字符串字符串程序设计 cs.sjtu 2005.9程序设计-293排序和查找排序和查找v顺序查找顺序查找v二分查找二分查找v选择排序法选择排序法v气泡排序法气泡排序法程序设计 cs.sjtu 2005.9程序设计-294顺序查找顺序查找v被查找的数存放在一个数组中被查找的数存放在一个数组中v从数组的第一个元素开始,依次往下比从数组的

188、第一个元素开始,依次往下比较,直到找到要找的元素为止。较,直到找到要找的元素为止。v如在一整数数组中查找元素如在一整数数组中查找元素x的存储位置的存储位置:程序设计 cs.sjtu 2005.9程序设计-295intmain()intk,x;intarray=2,3,1,7,5,8,9,0,4,6;coutx;for(k=0;k10;+k)if(x=arrayk)coutk;break;if(k=10)cout中间元素,那么中间元素,那么从从lhmid的这些元素不可能是要查找的元素,修正查找范的这些元素不可能是要查找的元素,修正查找范围为围为lh=mid+1到到rh;如;如keyrh,那么要查

189、找的元素不存在,否那么返回,那么要查找的元素不存在,否那么返回第二步。第二步。v如在数组如在数组CityTable中查找元素中查找元素SanFrancisco的过程如下所的过程如下所示。示。程序设计 cs.sjtu 2005.9程序设计-298二分查找过程二分查找过程0Atlanta1Boston2Chicago3Denver4Detroit5Houston6LosAngeles7Miami8NewYork9Philadelphia10 SanFrancisco11 SeattleSeattle11SanFrancisco10Philadelphia9NewYork8Miami7LosAnge

190、les6Houston5Detroit4Denver3Chicago2Boston1Atlanta0Seattle11SanFrancisco10Philadelphia9NewYork8Miami7LosAngeles6Houston5Detroit4Denver3Chicago2Boston1Atlanta0程序设计 cs.sjtu 2005.9程序设计-299二分查找程序二分查找程序intmain()intlh,rh,mid,x;intarray=0,1,2,3,4,5,6,7,8,9;coutx;lh=0;rh=9;while(lh=rh)mid=(lh+rh)/2;if(x=arra

191、ymid)coutx的位置是:的位置是:midendl;break;if(xrh)cout没有找到没有找到endl;return0;程序设计 cs.sjtu 2005.9程序设计-300搜索算法的效率搜索算法的效率v顺序搜索的平均时间性能顺序搜索的平均时间性能v1+2+3+n)/n=(n+1)/2v二分查找的最坏情况的时间性能二分查找的最坏情况的时间性能vn/2/2/2/2=1vk=log2nK次次程序设计 cs.sjtu 2005.9程序设计-301N和和log2N的值的值Nlog2N10310071000101,000,000201,000,000,00030程序设计 cs.sjtu 20

192、05.9程序设计-302排序与查找排序与查找v顺序查找顺序查找v二分查找二分查找v选择排序法选择排序法v气泡排序法气泡排序法程序设计 cs.sjtu 2005.9程序设计-303选择排序选择排序v使数组元素按某种次序排列使数组元素按某种次序排列v选择排序法:选择排序法:在所有元素中找到最小的元素放在数组的第在所有元素中找到最小的元素放在数组的第0个位置个位置在剩余元素中找出最小的放在第一个位置。以此类推,在剩余元素中找出最小的放在第一个位置。以此类推,直到所有元素都放在适当的位置直到所有元素都放在适当的位置v用伪代码表示用伪代码表示intlh,rh,array;输入要排序的元素,存入输入要排序

193、的元素,存入array;for(lh=0;lhn;lh+)在在array的从的从lh到到n1的元素之间找出最小的放入的元素之间找出最小的放入rh;交换下标交换下标lh和和rh中的值中的值;输出排好序的元素输出排好序的元素;程序设计 cs.sjtu 2005.9程序设计-304选择排序实例选择排序实例31415926535897939397585331594126已正确定位已正确定位9397585341593126已正确定位已正确定位9397585359413126已正确定位已正确定位程序设计 cs.sjtu 2005.9程序设计-305选择排序的完善选择排序的完善intmain()intlh,

194、rh,k,tmp;intarray=2,5,1,9,10,0,4,8,7,6;for(lh=0;lh10;lh+)rh=lh;for(k=lh;k10;+k)if(arraykarrayrh)rh=k;tmp=arraylh;arraylh=arrayrh;arrayrh=tmp;for(lh=0;lh10;+lh)coutarraylh;return0;程序设计 cs.sjtu 2005.9程序设计-306选择排序的效率选择排序的效率v对对n个元素的排序来说,找出第一个元个元素的排序来说,找出第一个元素要比较素要比较n次,找出第二个元素比较次,找出第二个元素比较n1次,次,找出第,找出第n个

195、元素比较一次。因个元素比较一次。因此,总的比较次数为:此,总的比较次数为:v1+2+3+n=n(n+1)/2v那么称时间复杂性为那么称时间复杂性为O(n2)程序设计 cs.sjtu 2005.9程序设计-307排序与查找排序与查找v顺序查找顺序查找v二分查找二分查找v选择排序法选择排序法v气泡排序法气泡排序法程序设计 cs.sjtu 2005.9程序设计-308气泡排序法气泡排序法v对数组元素进行扫描。第一遍扫描冒出对数组元素进行扫描。第一遍扫描冒出一个最大的气泡,放入最后一个位置。一个最大的气泡,放入最后一个位置。然后对剩余元素再进行第二次冒泡,冒然后对剩余元素再进行第二次冒泡,冒出最大的泡

196、放入倒数第二个位置,依次出最大的泡放入倒数第二个位置,依次执行到最后一个元素。执行到最后一个元素。v伪代码表示伪代码表示For (i=1; in; +i) 从元素0到元素n-i进行冒泡,最大的泡放入元素n-i;程序设计 cs.sjtu 2005.9程序设计-309冒泡过程冒泡过程v将待冒泡的数据从头到尾依次处理:比将待冒泡的数据从头到尾依次处理:比较相邻的两个元素,如果大的在前小的较相邻的两个元素,如果大的在前小的在后,就交换这两个元素。这样经过从在后,就交换这两个元素。这样经过从头到尾的检查,最大的一个就被交换到头到尾的检查,最大的一个就被交换到最后了最后了v如果在一次起泡中没有发生交换,那

197、么如果在一次起泡中没有发生交换,那么表示数据都已排好序,不需要再进行起表示数据都已排好序,不需要再进行起泡泡程序设计 cs.sjtu 2005.9程序设计-310进一步细化进一步细化for(i=1;in;+i)从元素从元素0到元素到元素ni进行起泡,最大的泡进行起泡,最大的泡放入元素放入元素ni;if没有发生过数据交换没有发生过数据交换break;程序设计 cs.sjtu 2005.9程序设计-3115730421968待冒泡的元素待冒泡的元素5304217689待冒泡的元素待冒泡的元素3042156789待冒泡的元素待冒泡的元素0321456789待冒泡的元素待冒泡的元素0213456789

198、待冒泡的元素待冒泡的元素0123456789待冒泡的元素待冒泡的元素程序设计 cs.sjtu 2005.9程序设计-312intmain()inta=0,3,5,1,8,7,9,4,2,10,6;inti,j,tmp,n=11;boolflag;for(i=1;in;+i)flag=false;for(j=0;jn-i;+j)if(aj+1aj)tmp=aj;aj=aj+1;aj+1=tmp;flag=true;if(!flag)break;/*一趟冒泡中没有发生交换,排序结束一趟冒泡中没有发生交换,排序结束*/coutendl;for(i=0;in;+i)coutai;return0; 程序

199、设计 cs.sjtu 2005.9程序设计-313第第5章章批量数据处理批量数据处理数组数组v一维数组一维数组v排序和查找排序和查找v二维数组二维数组v字符串字符串程序设计 cs.sjtu 2005.9程序设计-314多维数组多维数组v数组的每一个元素又是数组的数组称为多维数组数组的每一个元素又是数组的数组称为多维数组v最常用的多维数组是二维数组,又称为矩阵最常用的多维数组是二维数组,又称为矩阵v二维数组的定义格式:二维数组的定义格式: 类型说明类型说明 数组名数组名 常量表达式常量表达式11常量表达式常量表达式2 2 常量表达式常量表达式1 1表示行数,常量表达式表示行数,常量表达式2 2表

200、示列数表示列数eg.inta45;相当于定义了相当于定义了50个变量:个变量:a00,a01,.,a04,.a30,a31,.,a34程序设计 cs.sjtu 2005.9程序设计-315二维数组二维数组col0col1col2col3col4row0row1row2row3a23程序设计 cs.sjtu 2005.9程序设计-316二维数组的内存排列二维数组的内存排列a00a01a04a10a34按行序排列程序设计 cs.sjtu 2005.9程序设计-317多维数组的初始化多维数组的初始化v格式:格式:类型说明类型说明数组名数组名常量表达式常量表达式1常量表达式常量表达式2=.;v给所有的

201、元素赋初值。如:给所有的元素赋初值。如:inta34=1,2,3,4,5,6,7,8,9,10,11,12;也可以通过花括号把每一行括起来使这种初始化方法也可以通过花括号把每一行括起来使这种初始化方法表示得更加清晰。表示得更加清晰。inta34=1,2,3,4,5,6,7,8,9,10,11,12;程序设计 cs.sjtu 2005.9程序设计-318多维数组的初始化多维数组的初始化v对局部元素赋值对局部元素赋值vinta34=1,2,3,4,5;程序设计 cs.sjtu 2005.9程序设计-319多维数组的初始化多维数组的初始化v为每一行的局部元素赋初值为每一行的局部元素赋初值vinta3

202、4=1,2,3,4,5;程序设计 cs.sjtu 2005.9程序设计-320程序举例程序举例矩阵乘法矩阵乘法 矩阵乘法矩阵乘法C=A*BALM,BMNCLN输入输入A,B相乘相乘输出输出C程序设计 cs.sjtu 2005.9程序设计-321#defineMAX_SIZE10/矩阵的最大规模矩阵的最大规模intmain()intaMAX_SIZEMAX_SIZE;intbMAX_SIZEMAX_SIZEintcMAX_SIZEMAX_SIZE;inti,j,k;intNumOfRowA,NumOfColA,NumOfColB;/输入输入A,B的大小的大小coutNumOfRowANumOfC

203、olANumOfColB; 程序设计 cs.sjtu 2005.9程序设计-322/输入数组输入数组Acoutn输入数组输入数组A:n;for(i=0;iNumOfRowA;+i)for(j=0;jNumOfColA;+j)coutaijaij;/输入数组输入数组Bcoutn输入数组输入数组B:n;for(i=0;iNumOfColA;+i)for(j=0;jNumOfColB;+j)coutbijbij;程序设计 cs.sjtu 2005.9程序设计-323/执行执行A*Bfor(i=0;iNumOfRowA;+i)for(j=0;jNumOfColB;+j)cij=0;for(k=0;kN

204、umOfColA;+k)cij+=aik*bkj;程序设计 cs.sjtu 2005.9程序设计-324/输出数组输出数组Ccoutn输出数组输出数组C:;for(i=0;iNumOfRowA;+i)coutendl;for(j=0;jNumOfColB;+j)coutcijt;return0;程序设计 cs.sjtu 2005.9程序设计-325程序举例程序举例-打印打印N N阶魔阵阶魔阵81635749217241815235714164613202210121921311182529第一个元素:第一行中间一列第一个元素:第一行中间一列下一单元:行下一单元:行1,列,列+1如行如行1,列,

205、列+1有内容,那么下一单元为有内容,那么下一单元为“行行+1,列不变,列不变程序设计 cs.sjtu 2005.9程序设计-326填写魔阵的思想填写魔阵的思想row=0;col=N/2;magicrowcol=1;for(i=2;i=N;+i)if上一行、下一列有空上一行、下一列有空设置上一行、下一列为当前位置;设置上一行、下一列为当前位置;else设置当前列的下一行为当前位置;设置当前列的下一行为当前位置;将将i放入当前位置放入当前位置程序设计 cs.sjtu 2005.9程序设计-327难点难点v当处于第当处于第0行时,上一行是最后一行。当行时,上一行是最后一行。当处于最后一行时,下一行是

206、第处于最后一行时,下一行是第0行。行。v当处于最后一列时,下一列是第当处于最后一列时,下一列是第0列。列。v解决方案解决方案找下一列找下一列col=(col+1)%scale找下一行找下一行row=(row+1)%scale找上一行找上一行row=(row1+scale)%scale程序设计 cs.sjtu 2005.9程序设计-328#includeusingnamespacestd;#defineMAX15/最高位最高位15阶阶intmain()intmagicMAXMAX=0;introw,col,count,scale;/输入阶数输入阶数scalecoutscale;程序设计 cs.s

207、jtu 2005.9程序设计-329/生成魔阵生成魔阵row=0;col=(scale-1)/2;magicrowcol=1;for(count=2;count=scale*scale;count+)if(magic(row-1+scale)%scale(col+1)%scale=0)row=(row-1+scale)%scale;col=(col+1)%scale;elserow=(row+1)%scale;magicrowcol=count;/输出输出for(row=0;rowscale;row+)for(col=0;colscale;col+)coutmagicrowcolt;coutc

208、h;要输出要输出ch的内容。可直接用的内容。可直接用couts2返回值为正数,返回值为正数,s1=s1返回值返回值为为0,s1s2返回值为负数返回值为负数strncmp(s1,s2,n)如如strcmp,但至多比较,但至多比较n个字符个字符strchr(s,ch)返回一个指向返回一个指向s中第一次出现中第一次出现ch的地址的地址strrchr(s,ch)返回一个指向返回一个指向s中最后一次出现中最后一次出现ch的地址的地址strstr(s1,s2)返回一个指向返回一个指向s1中第一次出现中第一次出现s2的地址的地址程序设计 cs.sjtu 2005.9程序设计-343字符串字符串v字符串的存储

209、及初始化字符串的存储及初始化v字符串的输入输出字符串的输入输出v字符串处理函数字符串处理函数v字符串应用字符串应用程序设计 cs.sjtu 2005.9程序设计-344字符串的应用字符串的应用v实例:输入一行文字,统计有多少个单词。单词和实例:输入一行文字,统计有多少个单词。单词和单词之间用空格分开。单词之间用空格分开。v解题关键:单词的数目可以由单词间的空格决定解题关键:单词的数目可以由单词间的空格决定v解题思路:解题思路:v设置一个计数器设置一个计数器num表示单词个数。开始时,表示单词个数。开始时,num=0。v从头到尾扫描字符串。当发现当前字符为非空格,从头到尾扫描字符串。当发现当前字

210、符为非空格,而当前字符以前的字符是空格,那么表示找到了一而当前字符以前的字符是空格,那么表示找到了一个新的单词,个新的单词,num加加1。v当整个字符串扫描结束后,当整个字符串扫描结束后,num中的值就是单词数。中的值就是单词数。程序设计 cs.sjtu 2005.9程序设计-345intmain()charsentence80,prev=;/prev表示当前字符的前一字符表示当前字符的前一字符inti,num=0;gets(sentence);for(i=0;sentencei!=0;+i)if(prev=&sentencei!=)+num;prev=sentencei;cout单词个数为:

211、单词个数为:numb)return(a)elsereturn(b);函数体函数体程序设计 cs.sjtu 2005.9程序设计-353函数举例函数举例无参数、无返回值的函数无参数、无返回值的函数 v打印一个由五行组成的三角形打印一个由五行组成的三角形*voidprintstar()cout“*n;cout“*n;cout“*n;cout“*n;cout“*n;程序设计 cs.sjtu 2005.9程序设计-354函数举例函数举例有参数、无返回值的函数有参数、无返回值的函数v打印一个由打印一个由n行组成的三角形行组成的三角形voidprintstar(intnumOfLine)voidprint

212、star(numOfLine)intnunOfLine;inti,j;for(i=1;i=numOfLine;+i)coutendl;for(j=1;j=numOfLinei;+j)cout;for(j=1;j=2*i1;+j)cout“*;程序设计 cs.sjtu 2005.9程序设计-355函数举例函数举例有参数、有返回值的函数有参数、有返回值的函数 v计算计算n!intp(intn)ints=1,i;if(n0)return(0);for(i=1;i=n;+i)s*=i;return(s);程序设计 cs.sjtu 2005.9程序设计-356函数举例函数举例返回布尔量的函数返回布尔量的

213、函数v判断某一年是否为润年的函数判断某一年是否为润年的函数boolIsLeapYear(intyear)boolleapyear;leapyear=(year%4=0)&(year%100!=0)|(year%400=0);return(leapyear);程序设计 cs.sjtu 2005.9程序设计-357第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的

214、算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-358函数的声明函数的声明v所有函数在使用前必须被声明,以便让编译器知道所有函数在使用前必须被声明,以便让编译器知道用户的用法是否正确。用户的用法是否正确。v函数声明包括以下内容:函数声明包括以下内容:v函数名函数名v函数的参数类型函数的参数类型v函数的返回类型函数的返回类型v函数的声明被称为函数的原型,它的形式为:函数的声明被称为函数的原型,它的形式为:v返回类型返回类型函数名参数表;函数名参数表;v参数表中的每个参数说明可以是类型,也可以是参数表中的每个参数说明可以是类型,也可以是类型后面再接一个参数名。如:类型后面再接一个

215、参数名。如:vintmax(int,int);vintmax(inta,intb);程序设计 cs.sjtu 2005.9程序设计-359函数说明规那么函数说明规那么v库函数在调用前需要库函数在调用前需要include相应的头文件。相应的头文件。v自定义的函数在调用时需要进行函数原型说明。自定义的函数在调用时需要进行函数原型说明。v函数原型说明与函数首部写法上需要保持一致,函数原型说明与函数首部写法上需要保持一致,即函数类型、函数名、参数个数和参数顺序必即函数类型、函数名、参数个数和参数顺序必须相同。须相同。v如果被调函数的定义在主调函数之前,可以不如果被调函数的定义在主调函数之前,可以不必加

216、声明。必加声明。v如果在所有函数定义之前,在函数外部已经做如果在所有函数定义之前,在函数外部已经做了函数声明,那么在主调函数中无须再作声明。了函数声明,那么在主调函数中无须再作声明。程序设计 cs.sjtu 2005.9程序设计-360函数调用函数调用#includeintmax(inta,intb);main()intx,y;cinxy;coutb)return(a);elsereturn(b);函数原型说明函数原型说明函数调用函数调用函数实现函数实现程序设计 cs.sjtu 2005.9程序设计-361函数调用函数调用#includeintmax(inta,intb)if(ab)retur

217、n(a);elsereturn(b);main()intx,y;cinxy;cout x y; cout max(x, y);int p( int n ) int s =1, i; if (n 0) return(0); for (i=1;in2? n1: n2); mainx(2)y(3)mainx(2)y(3)maxa(2)b(3)n1n2mainx(2)y(3)maxa(2)b(3)n1n2pn(2)simainx(2)y(3)maxa(2)b(3)n1(2)n2pn(3)simainx(2)y(3)maxa(2)b(3)n1(2)n2(6)mainx(2)y(3)程序设计 cs.sjt

218、u 2005.9程序设计-366第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-367数组作为函数的参数数组作为函数的参数v设一程序有以下要求:设一程序有以下要求:v读入一组数据到一数组,直到输入为读入一组数据到一数组,直到输入为0为止为止v将数组的元素倒过来排将数组的元素倒过来排v显示数组元

219、素显示数组元素main()intlistMAX_NUM;GetIntegerArray(list);ReverseIntegerArray(list);PrintIntegerArray(list);存在的问题:存在的问题:输入的数据量是可变的,如何输入的数据量是可变的,如何设置数组的大小?设置数组的大小?函数函数GetIntegerArray和和ReverseIntegerArray只能修改只能修改自己的形式参数,而不能修改自己的形式参数,而不能修改实际参数。实际参数。函数的参数是数组,函数如何函数的参数是数组,函数如何知道数组中有效的元素个数?知道数组中有效的元素个数?程序设计 cs.sj

220、tu 2005.9程序设计-368问题一的解决方案问题一的解决方案v在在main函数中定义一个足够大的数组。不管函数中定义一个足够大的数组。不管GetIntegerArray中输入多少数据都不会下标中输入多少数据都不会下标超界超界v定义一个变量,指出数组中真正有多少元素。定义一个变量,指出数组中真正有多少元素。这样在这样在PrintIntegerArray和和ReverseIntegerArray函数中可以根据这个值函数中可以根据这个值进行操作。因此,要增加一个整型的形式参进行操作。因此,要增加一个整型的形式参数数程序设计 cs.sjtu 2005.9程序设计-369问题二的解决方案问题二的解

221、决方案数组参数的传递机制数组参数的传递机制vC+语言规定,数组作为参数传递时,传递的语言规定,数组作为参数传递时,传递的是数组元素的首地址。当用实际参数是数组元素的首地址。当用实际参数list调用调用函数函数GerIntegerArray时,是把时,是把list的首地址的首地址作为形式参数数组的首地址。如作为形式参数数组的首地址。如list的首地址的首地址为为1000,在函数中,在函数中形参数组的首地址也为形参数组的首地址也为1000。因此在函数中对形参数组。因此在函数中对形参数组的修改就是的修改就是对数组对数组list的修改。的修改。程序设计 cs.sjtu 2005.9程序设计-370函数

222、原型确实定函数原型确实定vPrintIntegerArray和和ReverseIntegerArray需要知道哪一需要知道哪一个数组和数组里有多少元素。而个数组和数组里有多少元素。而GetIntegerArray需要知需要知道哪一个数组、允许输入的最大元素个数,以及输入结束道哪一个数组、允许输入的最大元素个数,以及输入结束字符。该函数执行结束后应能返回有效的数据个数。字符。该函数执行结束后应能返回有效的数据个数。v数组传递本质上传递的是数组的起始地址,真正的元素个数组传递本质上传递的是数组的起始地址,真正的元素个数是通过另一个参数表示,因此形式参数中不需要说明数数是通过另一个参数表示,因此形式

223、参数中不需要说明数组的大小。组的大小。voidPrintIntegerArray(intarray,intn);voidReverseIntegerArray(intarray,intn);intGetIntegerArray(intarray,intmax,intsential);程序设计 cs.sjtu 2005.9程序设计-371Main函数函数intmain()intIntegerArrayMAX+1,flag,CurrentSize;coutflag;CurrentSize=ReadIntegerArray(IntegerArray,MAX,flag);ReverseIntegerA

224、rray(IntegerArray,CurrentSize);PrintIntegerArray(IntegerArray,CurrentSize);return0;程序设计 cs.sjtu 2005.9程序设计-372ReadIntegerArrayintReadIntegerArray(intarray,intmax,intflag)intsize=0;cout请输入数组元素,以请输入数组元素,以flag结束:结束:;while(sizearraysize;if(arraysize=flag)break;else+size;if(sizemax)cout超过数组规模超过数组规模endl;r

225、eturn0;returnsize;程序设计 cs.sjtu 2005.9程序设计-373ReverseIntegerArrayvoidReverseIntegerArray(intarray,intsize)inti,tmp;for(i=0;isize/2;i+)tmp=arrayi;arrayi=arraysizei1;arraysizei1=tmp;程序设计 cs.sjtu 2005.9程序设计-374PrintIntegerArrayvoidPrintIntegerArray(intarray,intsize)inti;if(size=0)return;cout逆序是:逆序是:endl

226、;for(i=0;isize;+i)coutarrayit;coutendl;程序设计 cs.sjtu 2005.9程序设计-375数组作为函数的参数小结数组作为函数的参数小结v可以将整个数组传递给函数,这时实际参数用的可以将整个数组传递给函数,这时实际参数用的是数组名。是数组名。v数组传递的实质是传递地址。把实际参数中的数数组传递的实质是传递地址。把实际参数中的数组首地址作为形式参数中的数组的首地址组首地址作为形式参数中的数组的首地址v数组在函数中的定义:函数原型应该表达参数是数组在函数中的定义:函数原型应该表达参数是一个数组,所以用无数组大小定义的方括号表示一个数组,所以用无数组大小定义的

227、方括号表示数组。数组。v对形式参数数组指定规模是没有意义的。对形式参数数组指定规模是没有意义的。程序设计 cs.sjtu 2005.9程序设计-376第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-377默认参数默认参数v对于某些函数,程序往往会用一些固定的值去调用它对于某些函数,程序往往会用

228、一些固定的值去调用它.例例如对于以某种数制输出整型数的函数如对于以某种数制输出整型数的函数print:voidprint(intvalue,intbase);在大多数情况下都是以十进制输出,因此在大多数情况下都是以十进制输出,因此base的值总是的值总是为为10。vC+在定义或声明函数时可以为函数的某个参数指定默认在定义或声明函数时可以为函数的某个参数指定默认值。当调用函数时没有为它指定实际参数时,系统自动值。当调用函数时没有为它指定实际参数时,系统自动将默认值赋给形式参数。例如,可以将将默认值赋给形式参数。例如,可以将print函数声明为函数声明为voidprint(intvalue,int

229、base=10);调用调用print(20)等价于等价于print(20,10)程序设计 cs.sjtu 2005.9程序设计-378带有默认参数的函数的使用带有默认参数的函数的使用 C+ C+在说明函数原型时,可以为一个或多个参在说明函数原型时,可以为一个或多个参数指定缺省值。调用此函数时,假设缺省某一数指定缺省值。调用此函数时,假设缺省某一参数,参数,C+C+自动以缺省值作为此参数的值。如:自动以缺省值作为此参数的值。如: int special(int x=2, float y=1.5) int special(int x=2, float y=1.5) 调用时可用:调用时可用: 程序设

230、计 cs.sjtu 2005.9程序设计-379带有默认参数的函数带有默认参数的函数本卷须知本卷须知v缺省参数无论有几个,都必须放在参数序缺省参数无论有几个,都必须放在参数序列的最后,列的最后,v 例如:例如:Int SaveName (char *first, Int SaveName (char *first, Char second=Char second=,char *third=,char *third=, , char *fouth=char *fouth=););v在函数调用时,假设某个参数省略,那么在函数调用时,假设某个参数省略,那么其后的参数皆应省略而取其缺省值其后的参数皆应

231、省略而取其缺省值程序设计 cs.sjtu 2005.9程序设计-380带有默认参数的函数带有默认参数的函数本卷须知本卷须知v对参数默认值的指定只有在函数声明处有意义。对参数默认值的指定只有在函数声明处有意义。因为函数的默认值是提供给调用者使用的。因为函数的默认值是提供给调用者使用的。v在不同的源文件中,可以对函数的参数指定不同在不同的源文件中,可以对函数的参数指定不同的默认值。例如对于上面的的默认值。例如对于上面的print函数,如果在某函数,如果在某一个功能模块中输出的大多是十进制数,那么在一个功能模块中输出的大多是十进制数,那么在此功能对应的源文件中可以指定此功能对应的源文件中可以指定ba

232、se的默认值为的默认值为10。如果在另一个功能最模块中经常要以二进制。如果在另一个功能最模块中经常要以二进制输出,那么在此功能模块对应的源文件中可以指输出,那么在此功能模块对应的源文件中可以指定默认值是定默认值是2。程序设计 cs.sjtu 2005.9程序设计-381第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu

233、 2005.9程序设计-382内联函数内联函数v在在C程序中,可以用带参数的宏。宏本身不是函数,但程序中,可以用带参数的宏。宏本身不是函数,但使用起来象函数。用复制宏代码的方式代替函数调用可使用起来象函数。用复制宏代码的方式代替函数调用可以提高速度。最大缺点是容易出错。以提高速度。最大缺点是容易出错。v函数内联用于取代函数内联用于取代C语言中带参数的宏,其目的是为了语言中带参数的宏,其目的是为了提高执行效率。对于任何内联函数,编译器在符号表里提高执行效率。对于任何内联函数,编译器在符号表里放入函数的声明包括名字、参数类型、返回值类型。放入函数的声明包括名字、参数类型、返回值类型。如果编译器没有

234、发现内联函数存在错误,那么该函数的如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在调用内联函数时,编译器直代码也被放入符号表里。在调用内联函数时,编译器直接用内联函数的代码替换函数调用,于是省去了函数调接用内联函数的代码替换函数调用,于是省去了函数调用的开销。用的开销。程序设计 cs.sjtu 2005.9程序设计-383内联函数内联函数v目的:减少函数调用的开销目的:减少函数调用的开销v作用:函数代码复制到程序中作用:函数代码复制到程序中#includeinlinefloatcube(constfloats)returns*s*s;intmain()floatside

235、;cinside;coutcube(side)endls;return0;程序设计 cs.sjtu 2005.9程序设计-384慎用内联函数慎用内联函数v内联以代码复制内联以代码复制(膨胀膨胀)为代价,省去了函数为代价,省去了函数调用的开销,提高函数的执行效率。如果相调用的开销,提高函数的执行效率。如果相比于执行函数体内代码的时间,函数调用的比于执行函数体内代码的时间,函数调用的开销可以忽略不计,那么效率的收获会很小。开销可以忽略不计,那么效率的收获会很小。v以下情况不宜用内联以下情况不宜用内联:v如果函数体内的代码比较长,使用内联将导如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。

236、致内存消耗代价较高。v如果函数体内出现循环,那么执行函数体内如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。代码的时间要比函数调用的开销大。程序设计 cs.sjtu 2005.9程序设计-385第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-386重载函数重载函数v在传统

237、的在传统的C语言中,不允许出现同名函数。当要语言中,不允许出现同名函数。当要求写一组功能类似、参数类型或参数个数不同求写一组功能类似、参数类型或参数个数不同的函数时,必须给它们取不同的函数名的函数时,必须给它们取不同的函数名v例如某个程序要求找出一组数据中的最大值,例如某个程序要求找出一组数据中的最大值,这组数据最多有这组数据最多有5个数据。我们必须写四个函数:个数据。我们必须写四个函数:求两个值中的最大值、求三个值中的最大值、求两个值中的最大值、求三个值中的最大值、求四个值中的最大值和求五个值中的最大值。求四个值中的最大值和求五个值中的最大值。我们必须为这四个函数取四个不同的函数名,我们必须

238、为这四个函数取四个不同的函数名,例如:例如:max2,max3,max4和和max5。程序设计 cs.sjtu 2005.9程序设计-387函数重载函数重载v使参数个数不同、参数类型不同或两者兼使参数个数不同、参数类型不同或两者兼而有之的两个以上的函数取相同的函数名而有之的两个以上的函数取相同的函数名v如如intmax(inta1,inta2);intmax(inta1,inta2,inta3);intmax(inta1,inta2,inta3,inta4);intmax(inta1,inta2,inta3,inta4,inta5);程序设计 cs.sjtu 2005.9程序设计-388函数重

239、载的实现函数重载的实现v由编译器确定某一次函数调用到底是调用了哪由编译器确定某一次函数调用到底是调用了哪一个具体的函数。这个过程称之为绑定一个具体的函数。这个过程称之为绑定binding,又称为联编或捆绑。,又称为联编或捆绑。v编译器首先会为这一组重载函数中的每个函数编译器首先会为这一组重载函数中的每个函数取一个不同的内部名字。当发生函数调用时,取一个不同的内部名字。当发生函数调用时,编译器根据实际参数和形式参数的匹配情况确编译器根据实际参数和形式参数的匹配情况确定具体调用的是那个函数,将这个函数的内部定具体调用的是那个函数,将这个函数的内部函数名取代重载的函数名。函数名取代重载的函数名。程序

240、设计 cs.sjtu 2005.9程序设计-389第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-390函数模板函数模板v如果一组重载函数仅仅是参数的类型不一样,程序的如果一组重载函数仅仅是参数的类型不一样,程序的逻辑完全一样,那么这一组重载函数可以写成一个函逻辑完全一样,那么这一组重载函数可

241、以写成一个函数模板。数模板。v所谓的函数模板就是实现类型的参数化泛型化,所谓的函数模板就是实现类型的参数化泛型化,即把函数中某些形式参数的类型定义成参数,称为模即把函数中某些形式参数的类型定义成参数,称为模板参数板参数v在函数调用时,编译器根据实际参数的类型确定模板在函数调用时,编译器根据实际参数的类型确定模板参数的值,生成不同的模板函数。参数的值,生成不同的模板函数。程序设计 cs.sjtu 2005.9程序设计-391函数模板的定义函数模板的定义v一一般的定义形式般的定义形式vtemplatev返回类型返回类型FunctionName(形式参数表形式参数表)vv/函数定义体函数定义体vv模

242、板形式参数表可以包含根本数据类型,也可以包模板形式参数表可以包含根本数据类型,也可以包含类类型需加前缀含类类型需加前缀classvtemplatevTmax(Ta,Tb)vreturnab?a:b;程序设计 cs.sjtu 2005.9程序设计-392例子例子v假设我们需要一个计算数值幂次方的函假设我们需要一个计算数值幂次方的函数数,名为名为power。该数值可以是整型、长。该数值可以是整型、长整型或实型整型或实型v我们只接受正幂次方,如果是负幂次方,我们只接受正幂次方,如果是负幂次方,结果为结果为0。v如果没有模板,我们需要每种类型写一如果没有模板,我们需要每种类型写一个函数个函数程序设计

243、cs.sjtu 2005.9程序设计-393程序设计 cs.sjtu 2005.9程序设计-394power函数的函数的template版本版本表示表示T是一种类型,而此类型将在调用此函是一种类型,而此类型将在调用此函数时才给予。数时才给予。程序设计 cs.sjtu 2005.9程序设计-395Template函数的调用方法函数的调用方法编译器根据实际参数的类型确定模板参数的类型,生成一个模板函数程序设计 cs.sjtu 2005.9程序设计-396第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函

244、数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-397标识符的作用域标识符的作用域v一个标识符能被存取一个标识符能被存取的程序局部,称为的程序局部,称为标识符的作用域标识符的作用域v标识符的作用域与程标识符的作用域与程序块有关。所谓的序块有关。所谓的程序块是带有声明程序块是带有声明的复合语句的复合语句v如右框中有两块如右框中有两块Int main(void) int a = 2, b = 3; cout a b; int a = 4;

245、cout a b; cout a b;程序设计 cs.sjtu 2005.9程序设计-398标识符的作用域标识符的作用域续续v在块中说明的标识符是在块中说明的标识符是局部局部的,仅能在本块中的,仅能在本块中和内部的块中存取。和内部的块中存取。v当内部块与外部块有同名标识符时,在内部块当内部块与外部块有同名标识符时,在内部块中屏蔽外部块的同名标识符。中屏蔽外部块的同名标识符。v在一个函数中,我们不能存取主调程序的变量,在一个函数中,我们不能存取主调程序的变量,即使知道该变量的名字。即使知道该变量的名字。v函数参数对该函数也是局部的,可以将它看成函数参数对该函数也是局部的,可以将它看成在块内,即函

246、数体内说明的说明的变量。在块内,即函数体内说明的说明的变量。程序设计 cs.sjtu 2005.9程序设计-399局部变量和全局变量局部变量和全局变量v局部变量:在块内定义的变量称为局部变量,局部变量:在块内定义的变量称为局部变量,即使是即使是main函数中定义的变量也是局部的。函数中定义的变量也是局部的。v全局变量:在所有的函数外面定义的变量称为全局变量:在所有的函数外面定义的变量称为全局变量全局变量v作用范围:从定义位置到文件结束。如在作用作用范围:从定义位置到文件结束。如在作用范围外的函数要使用此变量,用关键词范围外的函数要使用此变量,用关键词extern在在函数内说明此全局变量。函数内

247、说明此全局变量。v作用:方便函数间的数据传递作用:方便函数间的数据传递v请写出以下程序的执行结果:请写出以下程序的执行结果:程序设计 cs.sjtu 2005.9程序设计-400intp=1,q=5,r=3;intf1()intp=3,r=2;q=p+q+r;cout“f1:p,q,r=“pqr;intf2()p=p+q+r;cout“f2:p,q,r=“pqr;intf3()intq;r=2*r;q=r+p;cout“f3:p,q,r=“pqr;main()f3();cout“afterf3:p,q,r=pqr;f1();cout“afterf1:p,q,r=“pqr;f2();cout“a

248、fterf2:p,q,r=pqr;结果:结果:f3:p,q,r=176afterf3:p,q,r=156f1:p,q,r=3102afterf1:p,q,r=1106f2:p,q,r=17106afterf2:p,q,r=17106程序设计 cs.sjtu 2005.9程序设计-401全局变量的使用说明全局变量的使用说明v全局变量破坏了模块化,建议尽量少使全局变量破坏了模块化,建议尽量少使用用v当全局变量和局部变量同名时,在局部当全局变量和局部变量同名时,在局部变量的作用范围中全局变量被屏蔽。变量的作用范围中全局变量被屏蔽。v全局变量的使用将在模块化设计中详细全局变量的使用将在模块化设计中详细

249、介绍介绍程序设计 cs.sjtu 2005.9程序设计-402第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-403存储类型存储类型v在在C+语言中,每个变量有两个属性:语言中,每个变量有两个属性:v类型:变量所存储的数据类型类型:变量所存储的数据类型v存储类型:变量所存储的区域:存储类型:变

250、量所存储的区域:v标准的变量定义:标准的变量定义:v存储类型存储类型数据类型数据类型变量名;变量名;v存储类型:存储类型:v自动变量:自动变量:autov存放器变量:存放器变量:registerv外部变量:外部变量:externv静态变量:静态变量:static程序设计 cs.sjtu 2005.9程序设计-404autov在函数内或块内定义的变量缺省时是在函数内或块内定义的变量缺省时是auto。如。如autointi;v当进入块时,系统为自动变量分配空间。当进入块时,系统为自动变量分配空间。当退出块时,系统释放分配给自动变量当退出块时,系统释放分配给自动变量的值。因此自动变量的值就消失了。当

251、的值。因此自动变量的值就消失了。当再次进入该块时,系统重新分配空间。再次进入该块时,系统重新分配空间。程序设计 cs.sjtu 2005.9程序设计-405registerv存储在存放器中,代替自动变量或形参,存储在存放器中,代替自动变量或形参,可以提高变量的访问速度。可以提高变量的访问速度。v如无适宜的存放器可用,那么编译器把如无适宜的存放器可用,那么编译器把它设为自动变量。它设为自动变量。程序设计 cs.sjtu 2005.9程序设计-406externv声明一个不在作用范围内的全局变量。如:声明一个不在作用范围内的全局变量。如:externintnum;num为一个的全局变量。为一个的全

252、局变量。v用途:用途:在某函数中引用了一个声明在本函数后的全局变量时,在某函数中引用了一个声明在本函数后的全局变量时,需要在函数内用需要在函数内用extern声明此全局变量。声明此全局变量。当一个程序有多个源文件组成时,用当一个程序有多个源文件组成时,用extern可引用另一可引用另一文件中的全局变量。文件中的全局变量。程序设计 cs.sjtu 2005.9程序设计-407#includeusingnamespacestd;voidf();externintx;/外部变量的声明外部变量的声明intmain()f();coutinmain():x=“xendl;return0;#includeu

253、singnamespacestd;intx;/全局变量的定义全局变量的定义voidf()coutinf():x=“xendl;程序设计 cs.sjtu 2005.9程序设计-408staticv为在整个程序的运行期间都存在的变量为在整个程序的运行期间都存在的变量限定访问范围。限定访问范围。v两类静态变量:两类静态变量:静态的局部变量静态的局部变量静态的外部变量静态的外部变量程序设计 cs.sjtu 2005.9程序设计-409静态的局部变量静态的局部变量v允许局部允许局部变量保存变量保存它的原有它的原有值,以便值,以便在次进入在次进入块时还可块时还可以使用此以使用此值。值。eg.f(a)int

254、a;intb=0;staticintc=3;b=b+1;c=c+1;return(a+b+c);main()inta=2,i;for(i=0;i3;+i)coutf(a);运行结果为:运行结果为:789程序设计 cs.sjtu 2005.9程序设计-410静态的外部变量静态的外部变量v用用static说明的全局变量其他源文件不能说明的全局变量其他源文件不能用用extern引用它引用它v用用extern还可以用在函数定义或说明中。还可以用在函数定义或说明中。该函数只能被用于根源文件中,其他源该函数只能被用于根源文件中,其他源文件不能调用此函数。文件不能调用此函数。程序设计 cs.sjtu 200

255、5.9程序设计-411静态变量的使用静态变量的使用v未被程序员初始化的静态变量都由系统初未被程序员初始化的静态变量都由系统初始化为始化为0。v局部静态变量的初值是编译时赋的。当运局部静态变量的初值是编译时赋的。当运行时重复调用此函数时,不重复赋初值。行时重复调用此函数时,不重复赋初值。v虽然局部静态变量在函数调用结束后仍然虽然局部静态变量在函数调用结束后仍然存在,但其他函数不能引用它。存在,但其他函数不能引用它。程序设计 cs.sjtu 2005.9程序设计-412voida();voidb();voidc();voidd();main()intx=6;cout“xinmainis“xendl

256、;a();b();c();d(x);x+;a();b();c();d(x);cout“xinmainisxendl;voida()intx=25;cout“xinaisxendl;voidb()staticintx=50;cout“xinbisx+endl;voidc()externintx;x*=10;cout“xincisxendl;intx=2;voidd(intx)cout“xindis+xendl;结果:结果:xinmainis6xinais25xinbis50xincis20xindis7xinais25xinbis51xinc200xindis8xinmainis7程序设计 cs

257、.sjtu 2005.9程序设计-413第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-414递归用途递归用途v递归程序设计:将一个大问题简化为递归程序设计:将一个大问题简化为同样形式同样形式的较小问题。的较小问题。在一个递归求解中,分解的子问题与最初的问题具在一个递归求解中,分解的子问题与最

258、初的问题具有一样的形式有一样的形式 作为处理问题的工具,递归技术是一种非常有力的作为处理问题的工具,递归技术是一种非常有力的工具。利用递归不但可以使得书写复杂度降低,而工具。利用递归不但可以使得书写复杂度降低,而且使程序看上去更加美观且使程序看上去更加美观v递归调用:在一个函数中直接或间接地调用函递归调用:在一个函数中直接或间接地调用函数本身数本身程序设计 cs.sjtu 2005.9程序设计-415递归条件递归条件v必须有递归终止的条件必须有递归终止的条件 v函数有与递归终止条件相关的参数函数有与递归终止条件相关的参数v在递归过程中,决定终止条件的参数有在递归过程中,决定终止条件的参数有规略

259、地递增或递减规略地递增或递减 程序设计 cs.sjtu 2005.9程序设计-416递归的递归的标准模式标准模式v有可对函数的入口进行测试的根本情况有可对函数的入口进行测试的根本情况vif(条件条件)vreturn(不需要递归的简单答案不需要递归的简单答案);velsevreturn(递归调用同一函数递归调用同一函数);根本情况根本情况程序设计 cs.sjtu 2005.9程序设计-417典型的递归函数典型的递归函数阶乘函数阶乘函数n!=1*2*3*4*(n1)*n(n1)!递归形式:递归形式:递归终止条件递归终止条件longp(intn)if(n=0)return1;elsereturnn*

260、p(n1);程序设计 cs.sjtu 2005.9程序设计-418简单应用简单应用求求n的的k次幂次幂intRaiseIntToPower(intn,intk)if(k=0)return(1);elsereturn(n*RaiseIntToPower(n,k1);程序设计 cs.sjtu 2005.9程序设计-419Fibonacci函数函数00112132435568intf(intn)if(n=0)return0;elseif(n=1)return1;elsereturn(f(n1)+f(n2);程序设计 cs.sjtu 2005.9程序设计-420理解递归理解递归v问题:求解问题:求解n

261、!可可以以用用循循环环的的方方法法,即即从从1开开始始,乘乘2,再再乘乘3.一一直直乘乘到到n。这这种种方方法法容容易易理理解解,也容易实现也容易实现由由于于n!=n(n-1)!(n-1)!数数学学里里定定义义0!1,从从而而n!可以用下面的递归公式表示:可以用下面的递归公式表示:程序设计 cs.sjtu 2005.9程序设计-421递归函数设计递归函数设计intp(intn)if(n=0)return(1);elsereturn(n*p(n1);程序设计 cs.sjtu 2005.9程序设计-422递归执行的过程递归执行的过程求求p(4)递归过程回溯程序设计 cs.sjtu 2005.9程序

262、设计-423递归与迭代的选择递归与迭代的选择v对于大多数常用的递归都有简单、等价对于大多数常用的递归都有简单、等价的迭代程序。究竟使用哪一种,凭你的的迭代程序。究竟使用哪一种,凭你的经验选择。经验选择。v迭代程序复杂,但效率高。迭代程序复杂,但效率高。v递归程序逻辑清晰,但往往效率较低。递归程序逻辑清晰,但往往效率较低。程序设计 cs.sjtu 2005.9程序设计-424Fibonacci函数的递归实现函数的递归实现intf(intn)if(n=0)return0;elseif(n=1)return1;elsereturn(f(n1)+f(n2);v实现效率分析:消费的时间是灾难性的!实现效

263、率分析:消费的时间是灾难性的!程序设计 cs.sjtu 2005.9程序设计-425Fibonacci函数的迭代实现函数的迭代实现intf(intn)inti,fn,fn_1=0,fn_2=1;if(n=0)return0;if(n=1)return1;for(i=2;i0)draw(,offset);draw(symbol,length);putchar(n);display(symble,offset+2,length4);程序设计 cs.sjtu 2005.9程序设计-430Draw函数函数v画由画由k个字符组成的一行符号个字符组成的一行符号v该函数同样可以看成递归。画该函数同样可以看成

264、递归。画k个符号可以看成先个符号可以看成先画一个符号,然后再画画一个符号,然后再画k1个字符组成的一行。个字符组成的一行。voiddraw(charc,intk)jf(k0)putchar(c);draw(c,k1);程序设计 cs.sjtu 2005.9程序设计-431Main函数函数v#include#defineSYMBOL*#defineOFFSET0#defineLENGTH19voiddisplay(char,int,int);voiddraw(char,jnt);intmain(void)display(SYMBOL,OFFSET,LENGTH);return0;程序设计 cs.

265、sjtu 2005.9程序设计-432递归过程递归过程-数字旋转方阵蛇阵数字旋转方阵蛇阵v数字旋转方阵如右数字旋转方阵如右图所示。编程输出图所示。编程输出任意任意N*N的蛇阵。的蛇阵。120 19 18 17 16221 32 31 30 15322 33 36 29 14423 34 35 28 13524 25 26 27 12678910 11程序设计 cs.sjtu 2005.9程序设计-433用递归的观点看问题用递归的观点看问题v先填最外圈,然后再填内部内部的填法同上。先填最外圈,然后再填内部内部的填法同上。也是先填最外圈,再填内部。也是先填最外圈,再填内部。v根据上述思想,可以设计

266、一个递归函数根据上述思想,可以设计一个递归函数fill。该。该函数先填外圈,然后递归调用自己填内部。函数先填外圈,然后递归调用自己填内部。v函数原型:函数原型:voidfill(intnumber,intbegin,intsize)number:表示要填入的起始数据:表示要填入的起始数据begin:表示要填的起始位置:表示要填的起始位置size:蛇阵的规模:蛇阵的规模v要生成一个要生成一个6*6的蛇阵只要调用:的蛇阵只要调用:fill(1,0,6)程序设计 cs.sjtu 2005.9程序设计-434Main函数函数intp2020;voidfill(int,int,int);intmain(

267、)introw,col,size;coutsize;fill(1,0,size);for(row=0;rowsize;+row)coutendl;for(col=0;colsize;+col)coutprowcolt;return0;程序设计 cs.sjtu 2005.9程序设计-435Fill函数的设计函数的设计v自上而下填最左列自上而下填最左列v自左而右填最下行自左而右填最下行v自下而上填最右列自下而上填最右列v自右而左填最上行自右而左填最上行v递归调用递归调用fill,规模减,规模减2,起始位置为原,起始位置为原来的下一行下一列,填入的起始数字为来的下一行下一列,填入的起始数字为填入一圈

268、后的第一个数字。填入一圈后的第一个数字。程序设计 cs.sjtu 2005.9程序设计-436Voidfill(intnumber,intbegin,intsize)inti,row=begin,col=begin;if(size=0)return;if(size=1)pbeginbegin=number;return;prowcol=number;+number;for(i=0;isize-1;+i)+row;prowcol=number;+number;for(i=0;isize-1;+i)+col;prowcol=number;+number;for(i=0;isize-1;+i)-ro

269、w;prowcol=number;+number;for(i=0;isize-2;+i)-col;prowcol=number;+number;fill(number,begin+1,size-2);程序设计 cs.sjtu 2005.9程序设计-437递归过程递归过程Hanoi塔问题塔问题目标:将A上的盘子全部移到B上规那么:每次只能移动一个盘子不允许大盘子放在小盘子上 A B C程序设计 cs.sjtu 2005.9程序设计-438Hannoi塔塔vn4最开始的情况最开始的情况n4完成情完成情况况程序设计 cs.sjtu 2005.9程序设计-439Hannoi塔塔v第第1步:从开始的杆到

270、辅助杆步:从开始的杆到辅助杆src到到auxv第第2步:从开始杆到目的杆步:从开始杆到目的杆src到到dst程序设计 cs.sjtu 2005.9程序设计-440Hannoi塔塔v第第3步:从辅助杆到目的杆步:从辅助杆到目的杆aux到到dstv第第4步:从开始的杆到辅助杆步:从开始的杆到辅助杆src到到aux程序设计 cs.sjtu 2005.9程序设计-441Hannoi塔塔v第第5步:从目的杆到开始杆步:从目的杆到开始杆dst到到srcv第第6步:从目的杆到辅助杆步:从目的杆到辅助杆dst到到aux程序设计 cs.sjtu 2005.9程序设计-442Hannoi塔塔v第第7步:从开始杆到

271、目的杆步:从开始杆到目的杆src到到dstv第第8步:从开始杆到目的杆步:从开始杆到目的杆src到到dst程序设计 cs.sjtu 2005.9程序设计-443Hannoi塔塔v第第9步:从辅助杆到目的杆步:从辅助杆到目的杆aux到到dstv第第10步:从辅助杆到开始的杆步:从辅助杆到开始的杆aux到到src程序设计 cs.sjtu 2005.9程序设计-444Hannoi塔塔v第第11步:从目的杆到开始杆步:从目的杆到开始杆dst到到srcv第第12步:从辅助杆到目的杆步:从辅助杆到目的杆aux到到dst程序设计 cs.sjtu 2005.9程序设计-445Hannoi塔塔v第第13步:从开

272、始的杆到辅助杆步:从开始的杆到辅助杆src到到auxv第第14步:从开始杆到目的杆步:从开始杆到目的杆src到到dst程序设计 cs.sjtu 2005.9程序设计-446Hannoi塔塔v第第15步:从辅助杆到目的杆步:从辅助杆到目的杆aux到到dst程序设计 cs.sjtu 2005.9程序设计-447解题思路解题思路v最简单的情况,只有一个盘子:将盘子最简单的情况,只有一个盘子:将盘子直接从直接从A移到移到Bv大于一个盘子的情况:大于一个盘子的情况:将除了最下面一个盘子外的所有盘子从将除了最下面一个盘子外的所有盘子从A移移到到C将最下面的盘子从将最下面的盘子从A移到移到B将将C上的盘子移

273、回上的盘子移回B程序设计 cs.sjtu 2005.9程序设计-448Hanoi塔函数塔函数voidHanoi(intn,charstart,charfinish,chartemp)if(n=1)coutstartfinisht;elseHanoi(n1,start,temp,finish);coutstartfinisht;Hanoi(n1,temp,finish,start);程序设计 cs.sjtu 2005.9程序设计-449全排列问题全排列问题v如给定三个字母如给定三个字母“ABC,那么可形成的,那么可形成的全排列为:全排列为:ABC,ACB,BAC,BCA,CAB,CBA。试设计一

274、个函数,输入一。试设计一个函数,输入一个字符串,输出该字符串中所有字母的个字符串,输出该字符串中所有字母的全排列全排列程序设计 cs.sjtu 2005.9程序设计-450用递归的思想分析问题用递归的思想分析问题v如排列如排列“ABCDE,用递归的思想可以看成:,用递归的思想可以看成:v第一个字母为第一个字母为A,后面是,后面是“BCDE的全排的全排列列v第一个字母为第一个字母为B,后面是,后面是“CDE的全排列的全排列v第一个字母为第一个字母为C,后面是,后面是“BDE的全排列的全排列v第一个字母为第一个字母为D,后面是,后面是“BCE的全排列的全排列v第一个字母为第一个字母为E,后面是,后

275、面是“BCD的全排列的全排列v第一个字母为第一个字母为B,后面是,后面是“ACDE的全排的全排列列v第一个字母为第一个字母为C,后面是,后面是“BADE的全排的全排列列v第一个字母为第一个字母为D,后面是,后面是“BCAE的全排的全排列列v第一个字母为第一个字母为E,后面是,后面是“BCDA的全排的全排列列程序设计 cs.sjtu 2005.9程序设计-451选择存储结构选择存储结构v用一个字符串存储排列。用一个字符串存储排列。v对对n个字符的排列来讲,第一个元素有个字符的排列来讲,第一个元素有n种选择,种选择,对每种选择,排列后面对每种选择,排列后面n1个元素。个元素。vn1个元素的排列:固

276、定第二个元素个元素的排列:固定第二个元素(n1种选择种选择,排列后面,排列后面n2个元素。依此类推。个元素。依此类推。v函数原型可选为:函数原型可选为:voidpermu(charstr,intk)v表示排列字符串表示排列字符串str中从中从k开始的元素开始的元素v函数的调用:排列字符串中的所有元素可调用函数的调用:排列字符串中的所有元素可调用vpermu(charstr,0);程序设计 cs.sjtu 2005.9程序设计-452排列函数排列函数VoidPermuteWithFixedPrefix (charstr,intk)inti;if(k=strlen(str)coutstrendl;

277、elsefor(i=k;istrlen(str);+i)swap(str,k,i);PermuteWithFixedPrefix (str,k+1);swap(str,k,i);程序设计 cs.sjtu 2005.9程序设计-453包裹函数包裹函数staticvoidListPermutations(charstr)PermuteWithFixedPrefix(str,0);程序设计 cs.sjtu 2005.9程序设计-454第第6章章过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v

278、重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-455基于递归的算法基于递归的算法v回溯法回溯法v分治法分治法v动态规划动态规划程序设计 cs.sjtu 2005.9程序设计-456回溯法 v首首先先暂暂时时放放弃弃问问题题规规模模大大小小的的限限制制,并并将将问问题题的的候候选选解解按按某某种种顺顺序序逐逐一一枚枚举举和和检检验验。当当发发现现候候选选解解不不可可能能是是解解时时,就就选选择择下下一一候候选选解解。如如果果当当前前候候选选解解除除了了不不满

279、满足足规规模模要要求求外外,满满足足其其他他所所有有要要求求时时,继继续续扩扩大大当当前前候候选选解解的的规规模模,并并继继续续试试探探。如如果果当当前前的的候候选选解解满满足足包包括括问问题题规规模模在在内内的的所所有有要求时,该候选解就是问题的一个解。要求时,该候选解就是问题的一个解。v寻找下一候选解的过程成为回朔。寻找下一候选解的过程成为回朔。v扩大当前候选解的规模,并继续试探的过程称为扩大当前候选解的规模,并继续试探的过程称为向前试探。向前试探。v分书问题和八皇后都是典型的回溯法问题分书问题和八皇后都是典型的回溯法问题 程序设计 cs.sjtu 2005.9程序设计-457分书问题分书

280、问题v有编号为有编号为0,1,2,3,4的的5本书,准备分给本书,准备分给5个人个人A,B,C,D,E,每个人的阅,每个人的阅读兴趣用一个二维数组描述:读兴趣用一个二维数组描述:Likeij=truei喜欢书喜欢书jLikeij=falsei不喜欢书不喜欢书j写一个程序,输出所有皆大写一个程序,输出所有皆大欢喜的分书方案欢喜的分书方案0011011001011010001001001程序设计 cs.sjtu 2005.9程序设计-458存储设计存储设计v用一个二维数组用一个二维数组like存储用户的兴趣存储用户的兴趣v用一个一维数组用一个一维数组book记录书是否被分掉。记录书是否被分掉。如果

281、如果booki=false表示第表示第i本书尚未被分掉,本书尚未被分掉,等于等于1那么表示以被分掉那么表示以被分掉v用一个一维数组用一个一维数组take表示某本书分给了某表示某本书分给了某人。人。Takei=j表示第表示第j本书给了第本书给了第i个人个人程序设计 cs.sjtu 2005.9程序设计-459解题思路解题思路v依次尝试把书依次尝试把书j分给人分给人i。v如果第如果第i个人不喜欢第个人不喜欢第j本书,那么尝试下一本书,本书,那么尝试下一本书,如果喜欢,并且第如果喜欢,并且第j本书尚未分配,那么把书本书尚未分配,那么把书j分分配给配给i。v如果如果i是最后一个人,那么方案数加是最后一

282、个人,那么方案数加1,输出该方,输出该方案。否那么调用案。否那么调用tryi+1)为第为第i+1个人分书。个人分书。v回溯:第回溯:第i+1个人选不到适宜的书,让第个人选不到适宜的书,让第i个人退回个人退回书书j,尝试下一个,尝试下一个j,即寻找下一个可行的方案,即寻找下一个可行的方案v由于在每次由于在每次try中都要用到中都要用到like,book,take以及目以及目前找到的方案数前找到的方案数n,因此可将它们作为全局变量,因此可将它们作为全局变量,以免每次函数调用时都要带一大串参数。以免每次函数调用时都要带一大串参数。设计一个函数设计一个函数try(i)给第给第i个人分书。个人分书。程序

283、设计 cs.sjtu 2005.9程序设计-460voidtrynext(inti)intj,k;for(j=0;j5;+j)if(likeij&bookj)takei=j;bookj=false;if(i=4)n+;coutn第第n种方案种方案:endl;cout人人t书书endl;for(k=0;k5;k+)coutchar(k+A)ttakekendl;elsetrynext(i+1);bookj=true; 程序设计 cs.sjtu 2005.9程序设计-461当当likelike矩阵的值为矩阵的值为调用调用trynext(0);trynext(0);的结果为:的结果为:第1种方案:人

284、 书A 2B 0C 1D 3E 4第2种方案:人 书A 2B 0C 4D 3E 1程序设计 cs.sjtu 2005.9程序设计-462八皇后问题 v在一个在一个8*88*8的棋盘上放的棋盘上放8 8个皇后,使个皇后,使8 8个皇个皇后中没有两个以上的皇后会在同一行、后中没有两个以上的皇后会在同一行、同一列或同一对角线上同一列或同一对角线上程序设计 cs.sjtu 2005.9程序设计-463八皇后问题的求解过程v求求解解过过程程从从空空配配置置开开始始,在在第第一一列列到到第第m m列列为为合合理理配配置置的的根根底底上上再再配配置置m+1m+1列列,直直到到第第n n列列的的配配置置也也时

285、时合合理理时时,就就找找到到了了一一个个解解。另另外外在在一一列列上上也也有有n n种种配配置置。开开始始时时配配置置在在第第一一行行,以以后后改改变变时时,顺顺序序选选择择第第二二行行、第第三三行行、。、第第n n行行。当当配配置置到到第第n n行行时时还还找找不不到到一一个个合合理理的的配配置置时时,就要回朔,去改变前一列的配置。就要回朔,去改变前一列的配置。程序设计 cs.sjtu 2005.9程序设计-464算法算法m=0;/*从空配置开始从空配置开始*/good=true;/*配置中的皇后不冲突配置中的皇后不冲突*/doif(good)if(m=8)输出解;输出解;重新寻找下一可行的

286、解;重新寻找下一可行的解;else向前试探,扩展至下一列;向前试探,扩展至下一列;else回溯,形成下一候选解;回溯,形成下一候选解;good=检查当前候选解的合理性;检查当前候选解的合理性;while(m!=0);程序设计 cs.sjtu 2005.9程序设计-465棋盘的数据结构的设计v比比较较直直观观的的方方法法是是采采用用一一个个二二维维数数组组,但但仔仔细细考考察察,就就会会发发现,这种表示方法给调整候选解及检查其合理性会带来困难。现,这种表示方法给调整候选解及检查其合理性会带来困难。v对对于于此此题题来来说说,我我们们关关心心的的并并不不是是皇皇后后的的具具体体位位置置,而而是是“

287、一个皇后是否已经在某行和某条斜线合理地安置好了。一个皇后是否已经在某行和某条斜线合理地安置好了。v因因为为在在每每一一列列上上恰恰好好放放一一个个皇皇后后,所所以以引引入入一一个个一一维维数数组组( (设设为为colcol9 9) ),值值coljcolj表表示示在在棋棋盘盘第第j j列列上上的的皇皇后后位位置置。如如col3col3的的值值为为4 4,就就表表示示第第三三列列的的皇皇后后在在第第四四行行。另另外外,为为了了使使程程序序在在找找完完了了全全部部解解后后回回溯溯到到最最初初位位置置,设设定定col0col0的的初初值值为为0 0。当当回回溯溯到到第第0 0列列时时,说说明明程程序

288、序已已求求得得全全部部解解( (或或无解无解) ),结束程序执行。,结束程序执行。程序设计 cs.sjtu 2005.9程序设计-466候选解的合理性检查v引入以下三个工作数组引入以下三个工作数组 数组数组a9a9,aA=trueaA=true表示第表示第A A行上还没有皇后;行上还没有皇后;数数组组b16b16,bA=truebA=true表表示示第第A A条条右右高高左左低低斜斜线线上没有皇后;从左上角依次编到右下角上没有皇后;从左上角依次编到右下角(1-15)(1-15)。数数组组c16c16,cA=truecA=true表表示示第第A A条条左左高高右右低低斜斜线线上没有皇后。从左下角

289、依次编到右上角上没有皇后。从左下角依次编到右上角(1-15)(1-15)。程序设计 cs.sjtu 2005.9程序设计-467voidqueen_a11(intk)/在在8x8棋盘的第棋盘的第k列上找合理的配置列上找合理的配置inti,j;charawn;for(i=1;i=9;i+)/依次在依次在l至至8行上配置行上配置k列的皇后列的皇后if(ai&bk+i-1&c8+k-i)/可行位置可行位置colk=i;ai=bk+i-1=c8+k-i=false;/置对应位置有皇后置对应位置有皇后if(k=8)/找到一个可行解找到一个可行解for(j=1;j=8;j+)coutjcoljt;cout

290、awn;if(awn=Q|awn=q)exit(0);elsequeen_a11(k+1);/递归至第递归至第k十十1列列ai=bk+i-1=c8+k-i=true;/恢复对应位置无皇后恢复对应位置无皇后 程序设计 cs.sjtu 2005.9程序设计-468主程序主程序intcol9;boola9,b17,c17;intmain()intj;for(j=0;j=8;j+)aj=true;for(j=0;j0?aleft:0;maxLeft=maxSum(a,left,center);maxRight=maxSum(a,center+1,right);程序设计 cs.sjtu 2005.9程序

291、设计-476for(inti=center;i=left;-i)leftSum+=ai;if(leftSummaxLeftTmp)maxLeftTmp=leftSum;for(inti=center+1;imaxRightTmp)maxRightTmp=rightSum;returnmax3(maxLeft,maxRight,maxLeftTmp+maxRightTmp);程序设计 cs.sjtu 2005.9程序设计-477快速排序快速排序v思路:思路:将待排序的数据放入数组将待排序的数据放入数组a中,数据为中,数据为alow,ahigh从待排序的数据中任意选择一个,如从待排序的数据中任意选

292、择一个,如alow,将它放入变量将它放入变量k将待排序的数据分成两组,一组比将待排序的数据分成两组,一组比k小,放入小,放入数组的前一半;一组比数组的前一半;一组比k大,放入数组的后一大,放入数组的后一半;将半;将k放入中间位置。放入中间位置。对前一半和后一半分别重复上述方法。对前一半和后一半分别重复上述方法。v最好时间效率:最好时间效率:O(nlogn)程序设计 cs.sjtu 2005.9程序设计-47857304219681230457689lowhigh1230457689013245768901234576890123456789程序设计 cs.sjtu 2005.9程序设计-479

293、快速排序要解决的问题快速排序要解决的问题v如何选择作为分段基准的元素?如何选择作为分段基准的元素?采用第一个元素采用第一个元素选取第一个、中间一个和最后一个中的中选取第一个、中间一个和最后一个中的中间元素间元素v如何分段?考虑空间问题如何分段?考虑空间问题程序设计 cs.sjtu 2005.9程序设计-480快速排序函数快速排序函数Voidquicksort(inta,intlow,inthigh)intmid;if(low=high)return;mid=divide(a,low,high);quicksort(a,low,mid1);quicksort(a,mid+1,high);程序设计

294、 cs.sjtu 2005.9程序设计-481划分过程划分过程从右向左开始检查。如果从右向左开始检查。如果high的值大于的值大于k,high减减1,继续往前检查,直到遇到一个小于继续往前检查,直到遇到一个小于k的值。的值。v将大于将大于k的这个值放入的这个值放入low的位置。然后从的位置。然后从low位置开位置开始从左向右检查,直到遇到一个大于始从左向右检查,直到遇到一个大于k的值。的值。v将将low位置的值放入位置的值放入high位置,重复第一步,直到位置,重复第一步,直到low和和high重叠。将重叠。将k放入此位置。放入此位置。5730421968lowhighK=5程序设计 cs.s

295、jtu 2005.9程序设计-482730421968lowhighK=5730421968lowhigh173042968lowhigh130427968lowhigh123047968lowhigh程序设计 cs.sjtu 2005.9程序设计-483Divide函数函数Intdivide(inta,intlow,inthigh)intk=alow;dowhile(low=k)high;if(lowhigh)alow=ahigh;+low;while(lowhigh&alow=k)+low;if(lowhigh)ahigh=alow;while(low!=high);alow=k;retu

296、rnlow;程序设计 cs.sjtu 2005.9程序设计-484基于递归的算法基于递归的算法v回溯法回溯法v分治法分治法v动态规划动态规划程序设计 cs.sjtu 2005.9程序设计-485动态规划的思想动态规划的思想v在实际中经常会遇到一个复杂的问题不能简单地分成在实际中经常会遇到一个复杂的问题不能简单地分成几个子问题,而是会分解出一系列的子问题。如果用几个子问题,而是会分解出一系列的子问题。如果用分治法的话会使得递归调用的次数呈指数增长。如分治法的话会使得递归调用的次数呈指数增长。如Finonacci数列的计算,第数列的计算,第i个个Fibonacci数是前两个数是前两个Fibonac

297、ci数之和。数之和。v它是基于分而治之算法。在每一阶段都将当前问题分它是基于分而治之算法。在每一阶段都将当前问题分解为多个已解决的子问题解为多个已解决的子问题v为解决递归爆炸问题,通常先找出小问题的解,记录为解决递归爆炸问题,通常先找出小问题的解,记录在一个表中,在解决大问题时不需要递归,只需要从在一个表中,在解决大问题时不需要递归,只需要从表中取出小问题的解。表中取出小问题的解。程序设计 cs.sjtu 2005.9程序设计-486找零问题找零问题v对于一种货币,有面值为对于一种货币,有面值为C1,C2,CN(分分)的硬币,最少需要多少个硬币来的硬币,最少需要多少个硬币来找出找出K分钱的零钱

298、。分钱的零钱。程序设计 cs.sjtu 2005.9程序设计-487贪婪法解法贪婪法解法v我们不断使用可能的最大面值的硬币我们不断使用可能的最大面值的硬币v如:美元的硬币有如:美元的硬币有1、5、10和和25分的面值分的面值(忽略流忽略流通频率很低的通频率很低的50分硬币分硬币)。我们可以通过使用。我们可以通过使用2个个25分、一个分、一个10分的硬币以及三个分的硬币以及三个1分来找出分来找出63分钱,分钱,一共是一共是6个硬币。个硬币。v如果美元中包含一个如果美元中包含一个21分硬币时,贪心算法仍然分硬币时,贪心算法仍然给出一个用六个硬币的解,但是最正确的解是用给出一个用六个硬币的解,但是最

299、正确的解是用三个硬币三个硬币(三个都是三个都是21分的硬币。分的硬币。)程序设计 cs.sjtu 2005.9程序设计-488解法解法1分治法分治法v如果我们可以用一个硬币找零,这就是最如果我们可以用一个硬币找零,这就是最小的。小的。v否那么,对于每个可能的值否那么,对于每个可能的值i,我们可以,我们可以独立计算找独立计算找i分钱零钱和分钱零钱和Ki分钱需要的最分钱需要的最小硬币数。然后选择这个和最小的小硬币数。然后选择这个和最小的i。程序设计 cs.sjtu 2005.9程序设计-489怎样找出怎样找出63分钱零钱分钱零钱v找出找出1分钱零钱和分钱零钱和62分钱零钱分别需要的硬币数分钱零钱分

300、别需要的硬币数是是1和和4。因此,。因此,63分钱需要使用五个硬币。分钱需要使用五个硬币。v找出找出2分钱和分钱和61分钱分别需要分钱分别需要2和和4个硬币,一共个硬币,一共是六个硬币。是六个硬币。v我们继续尝试所有的可能性。我们看到一个我们继续尝试所有的可能性。我们看到一个21分分和和42分的分解,它可以分别用一个和两个硬币来分的分解,它可以分别用一个和两个硬币来找开,因此,这个找零问题就可以用三个硬币解找开,因此,这个找零问题就可以用三个硬币解决。决。v我们需要尝试的最后一种分解是我们需要尝试的最后一种分解是31分和分和32分。我分。我们可以用两个硬币找出们可以用两个硬币找出31分零钱,用

301、三个硬币找分零钱,用三个硬币找出出32分零钱,一共是五个硬币。分零钱,一共是五个硬币。v因此最小值是三个硬币。因此最小值是三个硬币。程序设计 cs.sjtu 2005.9程序设计-490intcoin(intk)inti,tmp,intcoinNum=k;if能用一个硬币找零能用一个硬币找零return1;for(i=1;icoinNum)coinNum=tmp;returncoinNum;程序设计 cs.sjtu 2005.9程序设计-491上述解法分析上述解法分析v此算法的效率很低此算法的效率很低v事实上事实上63分钱找零的问题是不会在一个分钱找零的问题是不会在一个合理的时间内解决的。就如

302、合理的时间内解决的。就如Finbonacci函数一样函数一样程序设计 cs.sjtu 2005.9程序设计-492解法解法2v通过指定其中的一个硬币来递归地简化问题。通过指定其中的一个硬币来递归地简化问题。v例如,对于例如,对于63分钱,我们可以给出以下找零的方分钱,我们可以给出以下找零的方法。法。v一个一个1分的硬币加上递归地分派分的硬币加上递归地分派62分钱分钱v一个一个5分的硬币加上递归地分派分的硬币加上递归地分派58分钱分钱v一个一个10分的硬币加上递归地分派分的硬币加上递归地分派53分钱分钱v一个一个21分的硬币加上递归地分派分的硬币加上递归地分派42分钱分钱v一个一个25分的硬币加

303、上递归地分派分的硬币加上递归地分派38分钱分钱v该算法的问题仍然是效率问题该算法的问题仍然是效率问题程序设计 cs.sjtu 2005.9程序设计-493动态规划解动态规划解v效率低下主要是由于重复计算造成的。效率低下主要是由于重复计算造成的。因此,可把已有子问题的答案存放起来,因此,可把已有子问题的答案存放起来,当再次遇到此子问题时就不用重复计算当再次遇到此子问题时就不用重复计算了。了。v在本例中,我们用在本例中,我们用coinsUsedi代表了找代表了找i分零钱所需的最小硬币数。分零钱所需的最小硬币数。程序设计 cs.sjtu 2005.9程序设计-494算法思想算法思想v先找出一分钱的找

304、零方法,把最小硬币先找出一分钱的找零方法,把最小硬币数存入数存入coinUsed1v依次找出依次找出2分钱、分钱、3分钱分钱的找零方法,的找零方法,知道到达要找零的钱为止:知道到达要找零的钱为止:对每个要找的零钱对每个要找的零钱i,可以把,可以把i分解成某个分解成某个coinsj和和icoinsj,所需硬币数为所需硬币数为coinUsedicoinsj+1。对所。对所有的有的j,取最小的,取最小的coinUsedicoinsj+1作为作为i元钱找零的的答案。元钱找零的的答案。程序设计 cs.sjtu 2005.9程序设计-495函数原型函数原型vVoidmakechange(intcoins,

305、intdifferentCoins,intmaxChange,intcoinUsed)vCoins存放所有不同的硬币值,不同的硬存放所有不同的硬币值,不同的硬币个数为币个数为differentCoins。vmaxChange为要找的零钱数为要找的零钱数程序设计 cs.sjtu 2005.9程序设计-496voidmakechange(intcoins,intdifferentCoins,intmaxChange,intcoinUsed)coinUsed0=0;for(intcents=1;cents=maxChange;cents+)intminCoins=cents;/都用都用1分找零,硬币

306、数最大分找零,硬币数最大for(intj=1;jcents)continue;/coinj硬币不可用硬币不可用if(coinUsedcents-coinsj+1minCoins)/分解成分解成coinsi和和cents-coinsjminCoins=coinUsedcents-coinsj+1;/用此硬币用此硬币coinUsedcents=minCoins; 程序设计 cs.sjtu 2005.9程序设计-497总结总结v函数可以将一段完成独立功能的程序封装起来。函数可以将一段完成独立功能的程序封装起来。通过函数名就可执行这一段功能。使用函数可以通过函数名就可执行这一段功能。使用函数可以将程序

307、模块化将程序模块化vC+的程序是由一组函数组成。每个程序必须有的程序是由一组函数组成。每个程序必须有一个名为一个名为main的函数,它对应于一般的程序设计的函数,它对应于一般的程序设计语言中主程序语言中主程序v函数也可以调用自己,这样的函数称为递归函数函数也可以调用自己,这样的函数称为递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2005.9程序设计-498第第7章章间接访问间接访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级

308、指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-499指针介绍 本章将介绍本章将介绍C+C+语言的一个重要的特性:指针,为了语言的一个重要的特性:指针,为了成为一个优秀的成为一个优秀的C+C+语言程序员,你必须掌握指针并语言程序员,你必须掌握指针并熟练地使用它们。熟练地使用它们。指针指针是内存的地址并可作为数据是内存的地址并可作为数据是一个灵活和危险的机制是一个灵活和危险的机制允许共享处理数据允许共享处理数据允许内存动态分配只要需要,而非预先定允许内存动态分配只要需要,而非预先定义义程序设计 cs.sjtu 2005.9程

309、序设计-500指针的概念指针的概念v指针就是把地址作为数据处理指针就是把地址作为数据处理v指针变量:存储地址的变量指针变量:存储地址的变量v变量的指针:当一个变量存储另一个变量的变量的指针:当一个变量存储另一个变量的地址时,那我们说它就是那个变量的指针地址时,那我们说它就是那个变量的指针v使用指针的目的:提供间接访问使用指针的目的:提供间接访问程序设计 cs.sjtu 2005.9程序设计-501指针的概念指针的概念续续续续v如在某一程序中定义了如在某一程序中定义了vintx=2;v如系统给如系统给x分配的空间是分配的空间是1000号单号单元,那么指向元,那么指向x的指针是另一个变的指针是另一

310、个变量量p,p中存放的数据为中存放的数据为1000v1000号单元的内容有两种访问方号单元的内容有两种访问方式:式:v访问变量访问变量x直接访问直接访问v访问变量访问变量p指向的单元的内容间指向的单元的内容间接访问接访问1000 21000xp程序设计 cs.sjtu 2005.9程序设计-502定义指针变量定义指针变量v定义指针变量要告诉编译器该变量中存放的是一定义指针变量要告诉编译器该变量中存放的是一个地址。个地址。v指针变量的主要用途是提供间接访问,因此也需指针变量的主要用途是提供间接访问,因此也需要知道指针指向的单元的数据类型要知道指针指向的单元的数据类型v指针变量的定义指针变量的定义

311、 类型标识符类型标识符 *指针变量;指针变量; 如:如:int int *intp;intp; double double *doublep;doublep; int *p, x, *q; int *p, x, *q;程序设计 cs.sjtu 2005.9程序设计-503指针变量的操作指针变量的操作v如何让指针指向某一变量?因为我们不知道系统分如何让指针指向某一变量?因为我们不知道系统分配给变量的真正地址是什么。配给变量的真正地址是什么。v用地址运算符用地址运算符 “& “& 解决。如表达式解决。如表达式 “&x “&x 返回返回的是变量的是变量 x x 的地址。如:的地址。如:intp =

312、&x;intp = &x;v& & 运算符后面不能跟常量或表达式。如运算符后面不能跟常量或表达式。如 &2 &2 是没有是没有意义的,意义的,&(m * n + p )&(m * n + p )。也是没有意义的。也是没有意义的v如何通过指针变量处理和改变它所指向的单元的值如何通过指针变量处理和改变它所指向的单元的值?v用引用运算符用引用运算符 “* “* 解决。如解决。如 *intp *intp 表示的是表示的是 intp intp 指向的这个单元的内容。如:指向的这个单元的内容。如:*intp = 5 *intp = 5 等价等价于于 x = 5 x = 5v在对在对 intp intp 使

313、用引用运算之前,必须先对使用引用运算之前,必须先对 intp intp 赋赋值值程序设计 cs.sjtu 2005.9程序设计-504指针实例指针实例如有:如有:intX,*intp,Y;X=3;Y=4;intp=&X;1000intp10044Y10003X如执行:如执行:*intp=Y+4;1000intp10044Y10008X注意:不能用注意:不能用 intp=100;intp=100;因为我们永远不知道变量存储的因为我们永远不知道变量存储的 真实地址,而且真实地址,而且程序每次运行变量地址可能都不同。程序每次运行变量地址可能都不同。程序设计 cs.sjtu 2005.9程序设计-50

314、5指针使用指针使用v指针变量可以指向不同的变量。如上例中指针变量可以指向不同的变量。如上例中intp指向指向x,我们可以通过对,我们可以通过对intp的重新赋值改变指针的指向。的重新赋值改变指针的指向。如果想让如果想让intp指向指向y,只要执行,只要执行intp=&y就可以了。就可以了。这时,这时,intp与与x无任何关系。无任何关系。v同类的指针同类的指针变量之间可相互赋值,表示二个指针指变量之间可相互赋值,表示二个指针指向同一内存空间。向同一内存空间。v空指针空指针指针没有指向任何空间指针没有指向任何空间空指针用常量空指针用常量NULLNULL表示,表示,NULLNULL的值一般赋为的值

315、一般赋为0 0不能引用空指针指向的值不能引用空指针指向的值程序设计 cs.sjtu 2005.9程序设计-506指针变量的使用指针变量的使用设有定义设有定义intx,y;int*p1,*p2;1000x1004y1008p11012p2执行语句:执行语句:x=23;y=234;1000 23x1004 234y1008p11012p2执行语句:执行语句:p1=&x;p2=&y;1000 23x1004 234y1008 1000p11012 1004p2执行语句:执行语句:*p1=34;p2=p1;1000 34x1004 17y1008 1000p11012 1000p2程序设计 cs.sj

316、tu 2005.9程序设计-507指针实例指针实例有以下结构有以下结构Ap1aBp2b比较执行比较执行p1=p2和和*p1=*p2后的不同结果。后的不同结果。解:解:Ap1aBp2bBp1aBp2b程序设计 cs.sjtu 2005.9程序设计-508指针的初始化指针的初始化v指针在使用前必须初始化。指针在使用前必须初始化。v和别的变量一样,定义指针不初始化是一个比和别的变量一样,定义指针不初始化是一个比较普通的错误。较普通的错误。v没有初始化的指针可能指向任意地址,对这些没有初始化的指针可能指向任意地址,对这些指针作操作可能会导致程序错误。指针作操作可能会导致程序错误。vNULLNULL是一

317、个特殊指针值,称为空指针。它的值是一个特殊指针值,称为空指针。它的值为为0 0。它可被用来初始化一个指针,表示不指。它可被用来初始化一个指针,表示不指向任何地址。向任何地址。程序设计 cs.sjtu 2005.9程序设计-509第第7章章间接访问间接访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-510指针运算和数组指针运算和

318、数组v指向数组元素的指针指向数组元素的指针v数组元素是一个独立的变量,因此可以有指数组元素是一个独立的变量,因此可以有指针指向它。如:针指向它。如:p=&a1,p=&aiv数组元素的地址是通过数组首地址计算的。数组元素的地址是通过数组首地址计算的。如数组的首地址是如数组的首地址是1000,那么第,那么第i个元素的个元素的地址是地址是1000+i*每个数组元素所占的空间每个数组元素所占的空间长度长度程序设计 cs.sjtu 2005.9程序设计-511指针与数组指针与数组v在在C+C+中,指针和数组关系密切,几乎可以互中,指针和数组关系密切,几乎可以互换使用换使用v数组名可以看成是常量指针,对一

319、维数组来说,数组名可以看成是常量指针,对一维数组来说,数组名是数组的起始地址,也就是第数组名是数组的起始地址,也就是第0 0个元素个元素的地址的地址v如执行了如执行了p=arrayp=array,那么,那么p p与与arrayarray是等价的,是等价的,对该指针可以进行任何有关数组下标的操作对该指针可以进行任何有关数组下标的操作程序设计 cs.sjtu 2005.9程序设计-512例如:有定义例如:有定义 int a10, *p int a10, *p 并且执行了并且执行了 p = a p = a, 那么可用以下语句访问数组那么可用以下语句访问数组a a的元素的元素for ( i=0; i1

320、0; +i )for ( i=0; i10; +i ) cout pi; cout pi; 程序设计 cs.sjtu 2005.9程序设计-513指针运算指针运算v指针指针+1表示数组中指针指向元素的下一元素表示数组中指针指向元素的下一元素地址;地址;v指针指针1表示数组中指针指向元素的上一元素地表示数组中指针指向元素的上一元素地址;址;v合法的指针操作:合法的指针操作:p+k,pk,p1p2指针保存的是一个地址,地址是一个整型数,因此可指针保存的是一个地址,地址是一个整型数,因此可以进行各种算术运算,但仅有加减运算是有意义的。以进行各种算术运算,但仅有加减运算是有意义的。指针运算与数组有密切

321、的关系指针运算与数组有密切的关系程序设计 cs.sjtu 2005.9程序设计-514数组元素的指针表示数组元素的指针表示v当把数组名,如当把数组名,如intarray,赋给了一个同类指针,赋给了一个同类指针intp后,后,intarray的元素可以通过的元素可以通过intp访问。第访问。第i个元素的地址可表示为个元素的地址可表示为intp+i,第,第i个元素的值个元素的值可表示为可表示为*(intp+i)。v通过指针访问数组时,下标有效范围由程序员自通过指针访问数组时,下标有效范围由程序员自己检查。己检查。v如输出数组如输出数组a的十个元素的十个元素程序设计 cs.sjtu 2005.9程序

322、设计-515方法方法3:for(p=a;pa+10;+p)cout *p; 方法方法2:for(i=0;i10;+i)cout*(a+i); 方法方法1:for(i=0;i10;+i)coutai; 方法方法4:for(p=a,i=0;i10;+i)cout *(p+i); 方法方法5:for(p=a,i=0;i10;+i)cout pi;以下程序段以下程序段有无问题?有无问题?for(i=0;i10;+i)cout*a;+a;程序设计 cs.sjtu 2005.9程序设计-516指针和数组的区别指针和数组的区别v虽然通过指针可以访问数组,但两者本质是不同的。虽然通过指针可以访问数组,但两者本

323、质是不同的。v在定义数组时为数组的各个元素分配了全部的存储区,在定义数组时为数组的各个元素分配了全部的存储区,而在定义指针时,仅仅分配四个字节的存储区存放指而在定义指针时,仅仅分配四个字节的存储区存放指针地址。只有把一个数组名付给了对应的指针后,指针地址。只有把一个数组名付给了对应的指针后,指针才能当作数组使用针才能当作数组使用v如有:如有:int array5, *intp;int array5, *intp;arrayintp当执行了当执行了 intp = arrayintp = array后后程序设计 cs.sjtu 2005.9程序设计-517第第7章章间接访问间接访问指针指针v指针的

324、概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-518指针作为函数参数和返回值指针作为函数参数和返回值v指针作为函数参数指针作为函数参数v数组名作为函数参数数组名作为函数参数v返回指针的函数返回指针的函数v引用和引用传递引用和引用传递v返回引用的函数返回引用的函数程序设计 cs.sjtu 2005.9程序设计-519指针作为函数参数指针作为函数参

325、数例:编一函数,交换二个参数值。例:编一函数,交换二个参数值。voidswap(inta,intb)intc;c=a;a=b;b=c;希望通过调用希望通过调用swap(x, swap(x, y)y)交换变量交换变量x x和和y y的值的值新手可能会编出如下的函数:新手可能会编出如下的函数:因为因为C+C+采用的是值传递机制,函数中采用的是值传递机制,函数中a a、b b值的值的交换不会影响实际参数交换不会影响实际参数x x和和y y的值的值程序设计 cs.sjtu 2005.9程序设计-520voidswap(int*a,int*b)intc;c=*a;*a=*b;*b=c;34xyab交换交

326、换x x和和y y的值,可以调用的值,可以调用swap(&x, &y)swap(&x, &y)用指针作为参数可以在函数中修改主调程序用指针作为参数可以在函数中修改主调程序的变量值,即实现变量传递。必须小心使用!的变量值,即实现变量传递。必须小心使用!正确的方法程序设计 cs.sjtu 2005.9程序设计-521能解一元二次方程的函数能解一元二次方程的函数v目前为止我们了解到的函数只能有一个返目前为止我们了解到的函数只能有一个返回值,由回值,由return语句返回。语句返回。v一个一元二次方程有二个解,如何让此函一个一元二次方程有二个解,如何让此函数返回二个解。答案是采用指针作为函数数返回二个

327、解。答案是采用指针作为函数的参数。的参数。v由调用程序准备好存放两个根的变量,将由调用程序准备好存放两个根的变量,将变量地址传给函数。在函数中将两个根的变量地址传给函数。在函数中将两个根的值分别放入这两个地址值分别放入这两个地址程序设计 cs.sjtu 2005.9程序设计-522函数原型函数原型v函数原型可设计为:函数原型可设计为:voidSolveQuadratic(doublea,doubleb,doublec,double*px1,double*px2)v函数的调用函数的调用SolveQuadratic(1.3,4.5,2.1,&x1,&x2)SolveQuadratic(a,b,c,

328、&x1,&x2)程序设计 cs.sjtu 2005.9程序设计-523原型的改进原型的改进v并不是每个一元二次方程都有两个不同根,并不是每个一元二次方程都有两个不同根,有的可能有两个等根,有的可能没有根。函有的可能有两个等根,有的可能没有根。函数的调用者如何知道数的调用者如何知道x1和和x2中包含的是否是中包含的是否是有效的解?有效的解?v解决方案:让函数返回一个整型数。该整型解决方案:让函数返回一个整型数。该整型数表示解的情况数表示解的情况程序设计 cs.sjtu 2005.9程序设计-524完整的函数完整的函数intSolveQuadratic(doublea,doubleb,double

329、c,double*px1,double*px2)doubledisc,sqrtDisc;if(a=0)return3;/不是一元二次方程不是一元二次方程disc=b*b-4*a*c;if(disc0)return2;/无根无根if(disc=0)*px1=-b/(2*a);return1;/等根等根/两个不等根两个不等根sqrtDisc=sqrt(disc);*px1=(-b+sqrtDisc)/(2*a);*px2=(-b-sqrtDisc)/(2*a);return0;程序设计 cs.sjtu 2005.9程序设计-525函数的调用函数的调用intmain()doublea,b,c,x1,

330、x2;intresult;coutabc;result=SolveQuadratic(a,b,c,&x1,&x2);switch(result)case0:cout方程有两个不同的根:方程有两个不同的根:x1=x1x2=x2;break;case1:cout方程有两个等根:方程有两个等根:x1;break;case2:cout方程无根方程无根;break;case3:cout不是一元二次方程不是一元二次方程;return0;程序设计 cs.sjtu 2005.9程序设计-526指针作为函数参数和返回值指针作为函数参数和返回值v指针作为函数参数指针作为函数参数v数组名作为函数参数数组名作为函数参

331、数v返回指针的函数返回指针的函数v引用和引用传递引用和引用传递v返回引用的函数返回引用的函数程序设计 cs.sjtu 2005.9程序设计-527数组传递的进一步讨论数组传递的进一步讨论v数组传递的本质是地址传递,因此形参和实参可数组传递的本质是地址传递,因此形参和实参可以使用数组名,也可以使用指针。以使用数组名,也可以使用指针。数组传递是函数原型可写为:数组传递是函数原型可写为:typefun(typea,intsize);也可写为也可写为typefun(type*p,intsize);但在函数内部,但在函数内部,a和和p都能当作数组使用都能当作数组使用调用时,对这两种形式都可用数组名或指针

332、作为实参调用时,对这两种形式都可用数组名或指针作为实参v建议:如果传递的是数组,用第一种形式;如果建议:如果传递的是数组,用第一种形式;如果传递的是普通的指针,用第二种形式传递的是普通的指针,用第二种形式程序设计 cs.sjtu 2005.9程序设计-528#includeusingnamespacestd;voidf(intarr,intk)coutsizeof(arr)sizeof(k)endl;voidmain()inta10=1,2,3,4,5,6,7,8,9,0;coutsizeof(a)endl;f(a,10);输出:输出:44C+将数组名作为参数传递处理成指针的传递将数组名作为参

333、数传递处理成指针的传递即在即在mainmain中,中,a a是数是数组,占用了组,占用了4040个字个字节。而在函数节。而在函数f f中,中,arrarr是一个指针是一个指针程序设计 cs.sjtu 2005.9程序设计-529数组传递的灵活性数组传递的灵活性void sort(int p , int n)void sort(int p , int n).main()main()int a100;int a100; . . sort(a, 100); / sort(a, 100); /排序整个数组排序整个数组 sort(a, 50); /sort(a, 50); /排序数组的前排序数组的前50

334、50个元素个元素 sort(a+50, 50); /sort(a+50, 50); /排序数组的后排序数组的后5050个元素个元素 . 程序设计 cs.sjtu 2005.9程序设计-530实例实例v设计一函数用分治法在一个整数数组中找出最大设计一函数用分治法在一个整数数组中找出最大和最小值和最小值v具体方法是:具体方法是:v如果数组只有一个元素,那么最大最小都是他。如果数组只有一个元素,那么最大最小都是他。v如果数组中只有两个元素,那么大的一个就是最如果数组中只有两个元素,那么大的一个就是最大数,小的就是最小数。这种情况不需要递归。大数,小的就是最小数。这种情况不需要递归。v否那么,将数组分

335、成两半,递归找出前一半的最否那么,将数组分成两半,递归找出前一半的最大最小值和后一半的最大最小值。取两个最大值大最小值和后一半的最大最小值。取两个最大值中的较大者作为最大值,两个最小值中的较小值中的较大者作为最大值,两个最小值中的较小值作为最小值。作为最小值。程序设计 cs.sjtu 2005.9程序设计-531设计考虑设计考虑v函数的参数是要查找的数组,传递一个数组要两个参函数的参数是要查找的数组,传递一个数组要两个参数:数组名和数组规模数:数组名和数组规模v函数返回的是数组中的最大值和最小值,将它们作为函数返回的是数组中的最大值和最小值,将它们作为指针传递的参数指针传递的参数v查找数组的前

336、一半就是递归调用本函数,传给他的参查找数组的前一半就是递归调用本函数,传给他的参数是当前的数组名,数组的规模是原来的一半数是当前的数组名,数组的规模是原来的一半v查找数组的后一半也是递归调用本函数,传给它的参查找数组的后一半也是递归调用本函数,传给它的参数是数组后一半的起始地址,规模也是原来的一半数是数组后一半的起始地址,规模也是原来的一半程序设计 cs.sjtu 2005.9程序设计-532伪代码伪代码voidminmax(inta,intn,int*min_ptr,int*max_ptr)switch(n)case1:最大最小都是最大最小都是a0;case2:大的得放入大的得放入*max_

337、ptr,小的放入,小的放入*min_ptr;Default:对数组对数组a的前一半和后一般分别调用的前一半和后一般分别调用minmax;取两个最大值中的较大者作为最大值;取两个最大值中的较大者作为最大值;取两个最小值中的较小值作为最小值取两个最小值中的较小值作为最小值程序设计 cs.sjtu 2005.9程序设计-533voidminmax(inta,intn,int*min_ptr,int*max_ptr)intmin1,max1,min2,max2;switch(n)case1:*min_ptr=*max_ptr=a0;return;case2:if(a0a1)*min_ptr=a0;*m

338、ax_ptr=a1;else*min_ptr=a1;*max_ptr=a0;return;default:minmax(a,n/2,&min1,&max1);minmax(a+n/2,n-n/2,&min2,&max2);if(min1min2)*min_ptr=min1;else*min_ptr=min2;if(max1*b)if(*a*c)return(a);elsereturn(c);elseif(*b*c)return(b);elsereturn(c);int*min(int*a,int*b,int*c)if(*a*b)if(*a*c)return(a);elsereturn(c);e

339、lseif(*bxyz;coutendlxyz;swap(max(&x,&y,&z),min(&x,&y,&z);coutendlxyz;return0;程序设计 cs.sjtu 2005.9程序设计-540指针作为函数参数和返回值指针作为函数参数和返回值v指针作为函数参数指针作为函数参数v数组名作为函数参数数组名作为函数参数v返回指针的函数返回指针的函数v引用和引用传递引用和引用传递v返回引用的函数返回引用的函数程序设计 cs.sjtu 2005.9程序设计-541引用传递引用传递v引用传递是地址传递的另一种更简单明引用传递是地址传递的另一种更简单明了的实现方法了的实现方法引用的概念引用的概

340、念函数中的引用函数中的引用程序设计 cs.sjtu 2005.9程序设计-542C+中的引用v引用的定义:给一个变量取一个别名引用的定义:给一个变量取一个别名, ,使一个内使一个内存单元可以通过不同的变量名来访问。存单元可以通过不同的变量名来访问。 例:例:int i;int i; int &j=i; int &j=i; j j是是i i的别名,的别名,i i与与j j是同一个内存单元。是同一个内存单元。vC+C+引入引用的主要目的是将引用作为函数的参引入引用的主要目的是将引用作为函数的参数。数。程序设计 cs.sjtu 2005.9程序设计-543v定义引用时必须立即对它初始化,不能定义完成

341、后再赋值。定义引用时必须立即对它初始化,不能定义完成后再赋值。如:如:inti;int&j;/错误错误j=i;v为引用提供的初始值可以是一个变量或另一个引用。如:为引用提供的初始值可以是一个变量或另一个引用。如:inti=5;int&j1=i;int&j2=j1;v引用不可重新赋值,不可使其作为另一变量的别名。引用不可重新赋值,不可使其作为另一变量的别名。inti,k;int&j=i;j=&k;/错误错误引用使用的本卷须知引用使用的本卷须知程序设计 cs.sjtu 2005.9程序设计-544引用传递引用传递v引用传递是地址传递的另一种更简单明引用传递是地址传递的另一种更简单明了的实现方法了的

342、实现方法引用的概念引用的概念函数中的引用函数中的引用程序设计 cs.sjtu 2005.9程序设计-545引用参数引用参数vC+引入引用的主要目的是将引用作为引入引用的主要目的是将引用作为函数的参数。函数的参数。指针参数指针参数voidswap(int*m,int*n)inttemp;temp=*m;*m=*n;*n=temp;调用:调用:swap(&x,&y)引用参数引用参数voidswap(int&m,int&n)inttemp;temp=m;m=n;n=temp;调用:调用:swap(x,y)注意:实参必须是变量,而不能是一个表达式注意:实参必须是变量,而不能是一个表达式程序设计 cs.

343、sjtu 2005.9程序设计-546v调用调用swap(x,y)时,相当于发生了变量定义时,相当于发生了变量定义int&m=xint&n=yv即,形式参数即,形式参数m和实际参数和实际参数x共享一块空共享一块空间,形式参数间,形式参数n和实际参数和实际参数y共享一块空间。共享一块空间。在在swap函数中交换了函数中交换了m和和n的值,就相当的值,就相当于交换了于交换了x和和y的值。的值。程序设计 cs.sjtu 2005.9程序设计-547验证引用传递验证引用传递voidf(int&r)cout“r=“rendl;cout“&r=“&rendl;r=5;cout“r=“rendl;intma

344、in()intx=47;cout“x=“xendl;cout“&x=“&xendl;f(x);cout“x=“xb)if(ac)return(a);elsereturn(c);elseif(bc)return(b);elsereturn(c);int&min(int&a,int&b,int&c)if(ab)if(ac)return(a);elsereturn(c);elseif(bc)return(b);elsereturn(c);voidswap(int&a,int&b)intc;c=a;a=b;b=c;程序设计 cs.sjtu 2005.9程序设计-552返回引返回引用的函数的主要用途用的

345、函数的主要用途v将函数用于赋值运算符的左边,即作为左值。将函数用于赋值运算符的左边,即作为左值。inta=1,3,5,7,9;int&index(int);/声明返回引用的函数声明返回引用的函数voidmain()index(2)=25;/将将a2重新赋值为重新赋值为25coutindex(2);int&index(intj)returnaj;/函数是函数是aj的一个引用的一个引用程序设计 cs.sjtu 2005.9程序设计-553第第7章章间接访问间接访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配

346、v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-554动态分配动态分配v在在C+C+语言中,每个程序需要用到几个变量,语言中,每个程序需要用到几个变量,在写程序前就应该知道。每个数组有几个元素在写程序前就应该知道。每个数组有几个元素也必须在写程序时就决定。也必须在写程序时就决定。v有时我们并不知道我们需要多大的数组元素直有时我们并不知道我们需要多大的数组元素直到程序开始运行。因此希望能在程序中根据某到程序开始运行。因此希望能在程序中根据某一个当前运行值来决定数组的

347、大小。如设计一一个当前运行值来决定数组的大小。如设计一个打印魔阵的程序,我们希望先输入魔阵的阶个打印魔阵的程序,我们希望先输入魔阵的阶数,然后根据阶数定义一个矩阵数,然后根据阶数定义一个矩阵程序设计 cs.sjtu 2005.9程序设计-555动态分配方法动态分配方法v这些问题的解决方案就是内存的动态分这些问题的解决方案就是内存的动态分配。我们定义一个指针,并让它指向一配。我们定义一个指针,并让它指向一个适宜的内存。如:个适宜的内存。如:v int *scores; int *scores;v scores = scores = 内存的起始地址;内存的起始地址;程序设计 cs.sjtu 200

348、5.9程序设计-556动态内存分配与回收动态内存分配与回收v用语言编程,动态分配是通过系统函数用语言编程,动态分配是通过系统函数malloc(),freemalloc(),free()()和运算符和运算符sizeofsizeof来实现动态分配来实现动态分配v中由中由new new 和和 deletedelete两个运算符替代两个运算符替代- - 运算符运算符newnew用于进行内存分配:用于进行内存分配: 申请动态变量:申请动态变量:p = new type;p = new type; 申请动态数组:申请动态数组:p = new typesize;p = new typesize; 申请动态变

349、量并初始化:申请动态变量并初始化:p = new type(p = new type(初值初值) ); - - 运算符运算符delete delete 释放释放 newnew分配的内存:分配的内存: 释放动态变量:释放动态变量:delete p;delete p; 释放动态数组:释放动态数组:delete p;delete p;程序设计 cs.sjtu 2005.9程序设计-557动态内存分配与回收动态内存分配与回收/为简单变量动态分配内存,并作初始化为简单变量动态分配内存,并作初始化int main()int main() int *p; int *p; p = new int(99); p

350、 = new int(99); / /动态分配内存,并将动态分配内存,并将9999作为初始化值赋给它作为初始化值赋给它 cout *p;cout *p; delete p; delete p; return 0; return 0; 程序设计 cs.sjtu 2005.9程序设计-558动态内存分配与回收动态内存分配与回收/动态字符串的使用动态字符串的使用intmain()int*p;char*q;p=newint(5);q=newchar10;strcpy(q,abcde);cout*pendl;coutqendl;deletep;deleteq;return0;输出结果:输出结果:5abc

351、de程序设计 cs.sjtu 2005.9程序设计-559动态分配的检查动态分配的检查vNew操作的结果是申请到的空间的地址操作的结果是申请到的空间的地址v当系统空间用完时,当系统空间用完时,new操作可能失败操作可能失败vNew操作失败时,返回空指针操作失败时,返回空指针程序设计 cs.sjtu 2005.9程序设计-560动态内存分配与回收动态内存分配与回收/动态分配检查动态分配检查int main()int main()int *p;int *p; p = new int; p = new int; if(!p) if(!p) cout allocation failuren; cout

352、 allocation failuren; return 1; return 1; *p = 20; cout *p; *p = 20; cout *p; delete p; return 0; delete p; return 0; 程序设计 cs.sjtu 2005.9程序设计-561assert宏宏vassert宏在标准头文件宏在标准头文件cassert中中vassert()有一个参数,表示断言为真的表有一个参数,表示断言为真的表达式,预处理器产生测试该断言的代码。达式,预处理器产生测试该断言的代码。如果断言不是真,那么在发出一个错误如果断言不是真,那么在发出一个错误消息后程序会终止。消

353、息后程序会终止。程序设计 cs.sjtu 2005.9程序设计-562#include#include/包含包含assert宏的头文件宏的头文件usingnamespacestd;intmain()int*p;p=newint;assert(p!=0);/p等于等于0,那么退出程序,那么退出程序*p=20;cout*p;deletep;return0;程序设计 cs.sjtu 2005.9程序设计-563内存分配的进一步介绍内存分配的进一步介绍v静态分配:对全局变量和静态变量,编静态分配:对全局变量和静态变量,编译器为它们分配空间,这些空间在整个译器为它们分配空间,这些空间在整个程序运行期间都

354、存在程序运行期间都存在v自动分配:函数内的局部变量空间是分自动分配:函数内的局部变量空间是分配在系统的栈工作区。当函数被调用时,配在系统的栈工作区。当函数被调用时,空间被分配;当函数执行结束后,空间空间被分配;当函数执行结束后,空间被释放被释放v动态分配:在程序执行过程中需要新的动态分配:在程序执行过程中需要新的存储空间时,可用动态分配的方法向系存储空间时,可用动态分配的方法向系统申请新的空间,当不再使用时用显式统申请新的空间,当不再使用时用显式的方法还给系统。这局部空间是从被称的方法还给系统。这局部空间是从被称为堆的内存区域分配。为堆的内存区域分配。OSProgramHeap动态分配动态分配

355、Stack自动分配自动分配Globevariables静态分配静态分配程序设计 cs.sjtu 2005.9程序设计-564内存泄漏内存泄漏v动态变量是通过指针间接访问的。如果该指针被修改,这动态变量是通过指针间接访问的。如果该指针被修改,这个区域就被丧失了。堆管理器认为你在继续使用它们,但个区域就被丧失了。堆管理器认为你在继续使用它们,但你不知道它们在哪里,这称为内存泄露。你不知道它们在哪里,这称为内存泄露。v为了防止出现孤立的区域,应该明白地告诉堆管理器这些为了防止出现孤立的区域,应该明白地告诉堆管理器这些区域不再使用。可以采用区域不再使用。可以采用deletedelete操作,它释放由操

356、作,它释放由newnew申请申请的内存。的内存。v当释放了内存区域,堆管理器重新收回这些区域,而指针当释放了内存区域,堆管理器重新收回这些区域,而指针仍然指向堆区域,但不能再使用指针指向的这些区域。仍然指向堆区域,但不能再使用指针指向的这些区域。v要确保在程序中同一个区域释放一次。要确保在程序中同一个区域释放一次。v释放内存对一些程序不重要,但对有些程序很重要。如果释放内存对一些程序不重要,但对有些程序很重要。如果你的程序要运行很长时间,而且存在内存泄漏,这样程序你的程序要运行很长时间,而且存在内存泄漏,这样程序会耗尽所有内存,直至崩溃。会耗尽所有内存,直至崩溃。程序设计 cs.sjtu 20

357、05.9程序设计-565动态空间分配例如动态空间分配例如v输入一批数据,计算它们的和。数据个数在设输入一批数据,计算它们的和。数据个数在设计程序时尚无法确定。计程序时尚无法确定。v存储一批数据应该用数组,但存储一批数据应该用数组,但C+语言的数组语言的数组大小必须是固定的。该问题有两个解决方案:大小必须是固定的。该问题有两个解决方案:v开设一个足够大的数组,每次运行时只使用一开设一个足够大的数组,每次运行时只使用一局部。缺点:浪费空间局部。缺点:浪费空间v用动态内存分配根据输入的数据量申请一个动用动态内存分配根据输入的数据量申请一个动态数组态数组程序设计 cs.sjtu 2005.9程序设计-

358、566#includeusingnamespacestd;intmain()int*p,i,n,sum=0;coutAnarraywillbecreateddynamically.nn;coutn;if(!(p=newintn)exit(1);for(i=0;ipi;for(i=0;in;+i)sum+=pi;deletep;coutNumberofelements:nendl;coutSumoftheelements:sumendl;return0;可改为:可改为:p=newintn;assert(p!=NULL);程序设计 cs.sjtu 2005.9程序设计-567第第7章章间接访问间接

359、访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-568字符串再讨论字符串再讨论v字符串的另一种表示是定义一个指向字符的字符串的另一种表示是定义一个指向字符的指针。然后直接将一个字符串常量或字符串指针。然后直接将一个字符串常量或字符串变量赋给它变量赋给它v如如vchar*String,ss=“abcdef;vString=“ab

360、cde;String=ss;程序设计 cs.sjtu 2005.9程序设计-569String“abcde”ProgramOS数据段数据段或代码区或代码区栈栈堆堆String=“abcde;的执行结的执行结果果字符串常量存储在一字符串常量存储在一个称为数据段的内存区个称为数据段的内存区域里域里 将存储字符串将存储字符串abcdeabcde的内存的首地址赋给的内存的首地址赋给指针变量指针变量StringString。 程序设计 cs.sjtu 2005.9程序设计-570String“abcdef0”ProgramOS数据段数据段栈栈堆堆String=ss的执行过程的执行过程将字符数组将字符数组

361、ss的起的起始地址存入始地址存入String程序设计 cs.sjtu 2005.9程序设计-571String=newchar5;strcpy(String,“aaa)StringProgramOS数据段数据段栈栈堆堆“aaa0”动态变量存储在堆工动态变量存储在堆工作区作区 将存储字符串将存储字符串aaaaaa的内存的首地址赋给指的内存的首地址赋给指针变量针变量StringString。 程序设计 cs.sjtu 2005.9程序设计-572用指针表示的字符串的操作用指针表示的字符串的操作v可以直接作为字符串操作函数的参数。但必须可以直接作为字符串操作函数的参数。但必须注意,如果该指针指向的是

362、一个字符串常量时注意,如果该指针指向的是一个字符串常量时,那么使用是受限的。如不能作为,那么使用是受限的。如不能作为strcpy的第的第一个参数一个参数v由于在由于在C+中,数组名被解释成指向数组首地中,数组名被解释成指向数组首地址的指针。因此,字符串是用一个指针变量表址的指针。因此,字符串是用一个指针变量表示,我们可以把此指针变量解释成数组的首地示,我们可以把此指针变量解释成数组的首地址,通过下标访问字符串中的字符。如址,通过下标访问字符串中的字符。如string3的值是的值是d。程序设计 cs.sjtu 2005.9程序设计-573用指针处理串用指针处理串v目的:编写一个记录串中单词的个数

363、的目的:编写一个记录串中单词的个数的函数。函数。v关键技术:要传递一个字符串给函数关键技术:要传递一个字符串给函数程序设计 cs.sjtu 2005.9程序设计-574字符串作为函数的参数字符串作为函数的参数v字符串作为函数的参数和数组名作为参数传递字符串作为函数的参数和数组名作为参数传递一样,可以有两种方法一样,可以有两种方法作为字符数组传递作为字符数组传递作为指向字符的指针传递作为指向字符的指针传递v两种传递方式的本质是一样的,都是传递了字两种传递方式的本质是一样的,都是传递了字符串的首地址符串的首地址v字符串作为字符数组传递时不需要指定长度。字符串作为字符数组传递时不需要指定长度。因为字

364、符串操作的结束是依据因为字符串操作的结束是依据0程序设计 cs.sjtu 2005.9程序设计-575#includeUsingnamespacestd;intword_cnt(constchar*s)intcnt=0;while(*s!=0) while(isspace(*s)+s;/跳过空白字符跳过空白字符if(*s!=0)+cnt;/找到一个单词找到一个单词while(!isspace(*s)&*s!=0)+s;/跳过单词跳过单词 returncnt;统计字符串中单词数的函数程序设计 cs.sjtu 2005.9程序设计-576Eg. Eg. 试设计一个函数,计算两个试设计一个函数,计算

365、两个128128位的整数的和,位的整数的和,结果作为函数值返回结果作为函数值返回设计思想:用一个由数字组成的字符串来表示数据。设计思想:用一个由数字组成的字符串来表示数据。如允许的最大长度为如允许的最大长度为128128位,那么字符数位,那么字符数组的长度为组的长度为128128。如数字。如数字123123,可表示为,可表示为127 54321000000123程序设计 cs.sjtu 2005.9程序设计-577加法函数的设计加法函数的设计voidadd(constchar*p1,constchar*p2,char*s)inti,j=0;/*j为进位为进位*/for(i=0;i=10)j=s

366、i/10;elsej=0;si=si%10+0;程序设计 cs.sjtu 2005.9程序设计-578辅助函数辅助函数v为了测试这个函数,设计了两个辅助函为了测试这个函数,设计了两个辅助函数数vSet函数将一个字符串存储为所设计的格函数将一个字符串存储为所设计的格式式vShow函数显示一个字符串表示的整型数函数显示一个字符串表示的整型数程序设计 cs.sjtu 2005.9程序设计-579intset(constchar*s1,char*s)inti=strlen(s1)-1,j=0;while(i=0)if(s1i9|s1i0)coutseterrorn;return-1;elsesj=s1

367、i;-i;+j;for(;j=0)coutsi;-i;coutendl;程序设计 cs.sjtu 2005.9程序设计-581测试程序的设计intmain()charnum1128,num2128,sum128;set(123,num1);set(345,num2);show(num1);show(num2);add(num1,num2,sum);show(sum);return0;执行结果:执行结果:123345468程序设计 cs.sjtu 2005.9程序设计-582第第7章章间接访问间接访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函

368、数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-583指针数组与多级指针指针数组与多级指针v指针数组指针数组vMain函数的参数函数的参数v多级指针多级指针程序设计 cs.sjtu 2005.9程序设计-584指针数组指针数组v地址本身也是数据,他们也可以像其他数据一地址本身也是数据,他们也可以像其他数据一样组织成一个数组样组织成一个数组v一个数组,如果他的元素均为指针,那么称为一个数组,如果他的元素均为指针,那么称为指针数

369、组指针数组v一维指针数组的定义形式:一维指针数组的定义形式:v类型名类型名*数组名数组名数组长度数组长度;v例如,例如,char*String10;定义了一个名为定义了一个名为String的指针数组,该数组有的指针数组,该数组有10个元素,数组个元素,数组的每个成员是一个指向字符的指针的每个成员是一个指向字符的指针程序设计 cs.sjtu 2005.9程序设计-585指针数组的应用指针数组的应用v字符串可以用一个指向字符的指针表示,字符串可以用一个指向字符的指针表示,一组字符串可以用一个指向字符的指针一组字符串可以用一个指向字符的指针数组来表示数组来表示v例:写一个函数用二分法查找某一个城例:

370、写一个函数用二分法查找某一个城市在城市表中是否出现。用递归实现市在城市表中是否出现。用递归实现v关键问题:关键问题:v城市表的存储:用指向字符的指针数组城市表的存储:用指向字符的指针数组v查找时的比较:用字符串比较函数查找时的比较:用字符串比较函数程序设计 cs.sjtu 2005.9程序设计-586IntbinarySearch(char*cityTable,intlh,intrh,char*cityName)intmid,result;while(lh0)returnbinarySearch(cityTable,lh,mid-1,cityName);elsereturnbinarySear

371、ch(cityTable,mid+1,rh,cityName);return-1;/没有找到没有找到程序设计 cs.sjtu 2005.9程序设计-587函数的应用函数的应用#includeusingnamespacestd;intbinarySearch(char*cityTable,intlh,intrh,char*cityName);intmain()char*string10=aaa,bbb,ccc,ddd,eee,fff,ggg,hhh,iii,jjj;chartmp10;while(cintmp)coutbinarySearch(string,0,9,tmp)endl;return

372、0;程序设计 cs.sjtu 2005.9程序设计-588“aaa”“bbb”“ccc”“ddd”“eee”“fff”“ggg”“hhh”“iii”“jjj”程序设计 cs.sjtu 2005.9程序设计-589指针数组与多级指针指针数组与多级指针v指针数组指针数组vMain函数的参数函数的参数v多级指针多级指针程序设计 cs.sjtu 2005.9程序设计-590main函数的形参函数的形参v如需要实现:如需要实现:copyab之类的功能,可之类的功能,可以用带有参数的以用带有参数的main函数来实现函数来实现vmain函数有二个形式参数:函数有二个形式参数:intargc,char*arg

373、vvargc参数的数目包括命令名本身参数的数目包括命令名本身vargv指向每个参数的指针,是一个指向每个参数的指针,是一个指向字符串的指针数组指向字符串的指针数组程序设计 cs.sjtu 2005.9程序设计-591把参数传递给把参数传递给main()#includeintmain(intargc,char*argv)inti;coutargc=“argcendl;for(i=0;iargc;+i)coutargv“i“=“argviendl;return0;假设生成的执行文件程序设计 cs.sjtu 2005.9程序设计-592把参数传递给把参数传递给main()续续续续v假设生成的执行文件

374、假设生成的执行文件v在命令行输入:在命令行输入:myprogram输出结果:输出结果:argc=1argv0=myprogramv在命令行输入:在命令行输入:myprogramtrythis输出结果:输出结果:argc=3argv0=myprogramargv1=tryargv2=this程序设计 cs.sjtu 2005.9程序设计-593例:编一程序打印例:编一程序打印N阶的魔阵,阶数在命令行中输入。即如阶的魔阵,阶数在命令行中输入。即如文件名为文件名为printmagic,那么打印,那么打印5阶魔阵可用命令阶魔阵可用命令printmagic5解:解:main(intargc,char*a

375、rgv)intm2020;intn=0,i=0;charnum5;strcpy(num,argv1);while(numi)n=n*10+numi0;+i;其余同魔阵打印;其余同魔阵打印;程序设计 cs.sjtu 2005.9程序设计-594指针数组与多级指针指针数组与多级指针v指针数组指针数组vMain函数的参数函数的参数v多级指针多级指针程序设计 cs.sjtu 2005.9程序设计-595多级指针多级指针v指针指向的内容还是一个指针,称为多级指针指针指向的内容还是一个指针,称为多级指针v如有定义:如有定义:char*string10;string是一个数组,数组元素可以通过指针来访是一个

376、数组,数组元素可以通过指针来访问。如果问。如果p是指向数组是指向数组string的某一个元素,那么的某一个元素,那么p指向的内容是一个指向字符的指针,因此指向的内容是一个指向字符的指针,因此p就就是一个多级指针。是一个多级指针。string也是一个多级指针,不也是一个多级指针,不过是一个常指针过是一个常指针程序设计 cs.sjtu 2005.9程序设计-596多级指针的定义多级指针的定义v两级指针:类型名两级指针:类型名*变量名;变量名;v三级指针:类型名三级指针:类型名*变量名;变量名;v如:如:int*q;表示表示q指向的内容是一个指向整型的指针。可以这样使指向的内容是一个指向整型的指针。

377、可以这样使用:用:intx=15,*p=&x;q=&p;v同样:同样:char*s;表示表示s指向的内容是一个指向字符的指针指向的内容是一个指向字符的指针qp15s“abcde程序设计 cs.sjtu 2005.9程序设计-597多级指针的应用多级指针的应用v可以用指向指针的指针访问指针数组的元素。如可以用指向指针的指针访问指针数组的元素。如#includeusingnamespacestd;intmain()char*city=aaa,bbb,ccc,ddd,eee;char*p;for(p=city;pcity+5;+p)cout*pendl;return0;输出结果:输出结果:aaabb

378、bcccdddeee程序设计 cs.sjtu 2005.9程序设计-598第第7章章间接访问间接访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-599二维数组与指针二维数组与指针inta34;等价于定义了等价于定义了3个变量个变量aa1a2a0123456789101112程序设计 cs.sjtu 2005.9程序设计-600

379、指向一维数组的指针指向一维数组的指针va a 是一个指针数组,它的每个元素是一个整型指是一个指针数组,它的每个元素是一个整型指针,指向每一行的第一个元素。针,指向每一行的第一个元素。a a是一个指向一维是一个指向一维数组的指针,指向数组的指针,指向a a 的第一个元素。对的第一个元素。对a a加加1 1,事,事实上是跳到下一行实上是跳到下一行 v指向一维数组的指针可以这样定义:指向一维数组的指针可以这样定义:v 类型名类型名 * *指针变量名指针变量名 一维数组的元素个数一维数组的元素个数 ;v注意:圆括号不能省略,如果省略了圆括号就变成注意:圆括号不能省略,如果省略了圆括号就变成了指针数组了

380、指针数组 程序设计 cs.sjtu 2005.9程序设计-601等价于等价于aij的表达式的表达式aij*(ai+j)(*(a+i)j*(*(a+i)+j)*(&a00+5*i+j)inta35;程序设计 cs.sjtu 2005.9程序设计-602用指向数组的指针输出二维数组用指向数组的指针输出二维数组aint(*p)4,*q;for(p=a;pa+3;+p)/每一行每一行for(q=*p;q*p+4;+q)/每一列每一列cout*qt;coutendl;注意:如果输出a和a0,这两个值是相同的。但是,这两个值的含义是不同的,前者是第0行的首地址,它的类型是指向由四个元素组成的一位数组的首地

381、址,后者是第0行第一个元素的地址,它的类型是整型指针 程序设计 cs.sjtu 2005.9程序设计-603第第7章章间接访问间接访问指针指针v指针的概念指针的概念v指针运算与数组指针运算与数组v指针作为函数参数和返回值指针作为函数参数和返回值v动态内存分配动态内存分配v字符串再讨论字符串再讨论v指针数组与多级指针指针数组与多级指针v指向多维数组的指针指向多维数组的指针v指向函数的指针指向函数的指针程序设计 cs.sjtu 2005.9程序设计-604函数的指针和指向函数的指针变量函数的指针和指向函数的指针变量v定义:返回类型定义:返回类型(*指针变量名指针变量名)();v使用使用:赋值赋值e

382、g.intisdigit(intn,intk);.int(*p)(int,int);p=isdigit;引用:引用:a=isdigit(n,k);a=(*p)(n,k);或或a=p(n,k)函数的指针:指向函数代码的起始地址函数的指针:指向函数代码的起始地址程序设计 cs.sjtu 2005.9程序设计-605函数的指针的用途函数的指针的用途v菜单项选择择的实现菜单项选择择的实现v作为函数的参数作为函数的参数程序设计 cs.sjtu 2005.9程序设计-606函数指针的应用函数指针的应用v用函数指针的数组实现菜单项选择择用函数指针的数组实现菜单项选择择v例如,在一个工资管理系统中有如下功能:

383、例如,在一个工资管理系统中有如下功能:v1。添加员工;。添加员工;v2。删除员工;。删除员工;v3。修改员工信息;。修改员工信息;v4。打印工资单;。打印工资单;v5。打印汇总表;。打印汇总表;v6。退出。退出。v在设计中,一般把每个功能设计成一个函数。如添加员工的在设计中,一般把每个功能设计成一个函数。如添加员工的函数为函数为add,删除员工的函数为,删除员工的函数为delete,修改员工信息的函数,修改员工信息的函数为为modify,打印工资单的函数为,打印工资单的函数为printSalary,打印汇总表函,打印汇总表函数为数为printReport。主程序是一个循环,显示所有功能和它的。

384、主程序是一个循环,显示所有功能和它的编号,请用户输入编号,根据编号调用相应的函数。编号,请用户输入编号,根据编号调用相应的函数。程序设计 cs.sjtu 2005.9程序设计-607intmain()intselect;while(1)cout1-addn;cout2-deleten;cout3-modifyn;cout4-printsalaryn;cout5-printreportn;coutselect;switch(select)case0:return0;case1:add();break;case2:erase();break;case3:modify();break;case4:p

385、rintSalary();break;case5:printReport();break;default:coutinputerrorn;程序设计 cs.sjtu 2005.9程序设计-608利用指向函数的指针利用指向函数的指针intmain()intselect;void(*func6)()=NULL,add,erase,modify,printSalary,printReport;while(1)cout1addn;cout2deleten;cout3modifyn;cout4printsalaryn;cout5printreportn;coutselect;if(select=0)ret

386、urn0;if(select5)coutinputerrorn;elsefuncselect();程序设计 cs.sjtu 2005.9程序设计-609函数指针的应用函数指针的应用v把函数指针作为函数的参数把函数指针作为函数的参数v例:设计一个通用的快速排序函数,可例:设计一个通用的快速排序函数,可以排序任何类型的数据以排序任何类型的数据v关键问题关键问题v如何表示要排序的数据:将快速排序设如何表示要排序的数据:将快速排序设计成一个函数模板,将待排序的数据类计成一个函数模板,将待排序的数据类型设计成模板参数型设计成模板参数v不同类型的数据有不同的比较方式:向不同类型的数据有不同的比较方式:向排

387、序函数传递一个比较函数来解决。排序函数传递一个比较函数来解决。程序设计 cs.sjtu 2005.9程序设计-610templatevoidquicksort(Tdata,intlow,inthigh,int(*comp)(T,T)intmid;if(low=high)return;mid=divide(data,low,high,comp);quicksort(data,low,mid-1,comp);quicksort(data,mid+1,high,comp);程序设计 cs.sjtu 2005.9程序设计-611templateintdivide(Tdata,intlow,inthig

388、h,int(*comp)(T,T)Tk=datalow;dowhile(low0)-high;if(lowhigh)datalow=datahigh;+low;while(lowhigh&comp(datalow,k)0)+low;if(lowhigh)datahigh=datalow;-high;while(low!=high);datalow=k;returnlow;程序设计 cs.sjtu 2005.9程序设计-612通用快速排序的应用通用快速排序的应用v如果需要排序一组字符串,待排序的一组如果需要排序一组字符串,待排序的一组字符串保存在数组字符串保存在数组a中。中。a的定义如下:的定义

389、如下:char*a=aaa,nnn,rrr,fff,sss,ggg,ddd;v调用调用quicksort(a,0,6,strcmp);程序设计 cs.sjtu 2005.9程序设计-613通用快速排序的应用通用快速排序的应用v如果要排序一组整型数,那么需要定义一如果要排序一组整型数,那么需要定义一个比较函数,如下所示:个比较函数,如下所示:vintintcmp(inta,intb)vif(a=b)return0;vif(astudent1.birthday.day;v同类型的结构变量之间可以相互赋值,如同类型的结构变量之间可以相互赋值,如Student1=student2;将将student2

390、的成员对应赋给的成员对应赋给student1的成员的成员程序设计 cs.sjtu 2005.9程序设计-634结构变量的输出结构变量的输出v结构体变量的输出通常是通过输出它的每一结构体变量的输出通常是通过输出它的每一个成员而实现。如:输出个成员而实现。如:输出student1的内容可的内容可用用:成员成员如:如:spnamestudent1.成员成员 是所有运算符中优先级最高的是所有运算符中优先级最高的通常程序员习惯使用第二种方法通常程序员习惯使用第二种方法程序设计 cs.sjtu 2005.9程序设计-638结构体类型的变量结构体类型的变量v结构体变量的定义结构体变量的定义v结构体类型的引用

391、结构体类型的引用v指向结构体的指针指向结构体的指针v动态分配结构体的空间动态分配结构体的空间程序设计 cs.sjtu 2005.9程序设计-639动态分配结构体的空间动态分配结构体的空间v指向结构体指针的另一种用法是存储动指向结构体指针的另一种用法是存储动态申请到的内存的首地址。用法和申请态申请到的内存的首地址。用法和申请普通的动态变量一样。如:普通的动态变量一样。如:studentT*sp;sp=newstudentT;程序设计 cs.sjtu 2005.9程序设计-640第第8章章数据封装数据封装结构体结构体v结构体的概述结构体的概述v结构体类型的定义结构体类型的定义v结构体类型的变量结构

392、体类型的变量v结构体数组结构体数组v结构体作为函数的参数结构体作为函数的参数v链表链表程序设计 cs.sjtu 2005.9程序设计-641 结构体数组结构体数组v用于描述个体的集合用于描述个体的集合v定义格式:定义格式:studentTstudentArraySIZE;程序设计 cs.sjtu 2005.9程序设计-642结构体数组的引用结构体数组的引用v引用数组的某一成员的成员引用数组的某一成员的成员vstudentArray3.namev数组成员之间相互赋值数组成员之间相互赋值vstudentArray4=studentArray2v结构数组的初始化结构数组的初始化vstudentTst

393、udentArray5=“00001,张三张三“,80,90,98,;程序设计 cs.sjtu 2005.9程序设计-643统计候选人得票。设有三个候选人,每次输入一个统计候选人得票。设有三个候选人,每次输入一个得票的候选人名字,要求最后输出各人得票结果。得票的候选人名字,要求最后输出各人得票结果。structpersonTintid;intcount;leader3=0,0,1,0,2,0;程序设计 cs.sjtu 2005.9程序设计-644Intmain()inti,j,inputID;for(i=1;iinputID;if(inputID2)cout“废票;废票;continue;le

394、aderinputID.count+=1;coutendl;for(i=0;i3;+i)coutleaderi.id“leaderi.count);return0;程序设计 cs.sjtu 2005.9程序设计-645例:输出通讯录例:输出通讯录 #include#includeusingnamespacestd;structpersonTcharname10;charsex;charaddr30;intphonenum;constintMAX=100;程序设计 cs.sjtu 2005.9程序设计-646intmain()personTpMAX;inti,num=0;cout姓名姓名性别性别

395、地址地址表示结束:表示结束:n;while(numpnum.name;if(pnum.name0=)break;cinpnum.sexpnum.addrpnum.phonenum;+num;程序设计 cs.sjtu 2005.9程序设计-647coutNameSexttAddrtttPhoneNumn;coutsetiosflags(ios:left);for(i=0;inum;+i)coutsetw(10)pi.namepi.sextsetw(30)pi.addrtpi.phonenumendl;return0;程序设计 cs.sjtu 2005.9程序设计-648指针与结构体数组指针与结构

396、体数组v与普通的指针一样,指向结构体的指针与普通的指针一样,指向结构体的指针也能够用来指向一个结构体数组。此时,也能够用来指向一个结构体数组。此时,对指针加对指针加1就是加了该结构体的大小。就是加了该结构体的大小。程序设计 cs.sjtu 2005.9程序设计-649第第8章章数据封装数据封装结构体结构体v结构体的概述结构体的概述v结构体类型的定义结构体类型的定义v结构体类型的变量结构体类型的变量v结构体数组结构体数组v结构体作为函数的参数结构体作为函数的参数v链表链表程序设计 cs.sjtu 2005.9程序设计-650结构体作为参数传递结构体作为参数传递v尽管结构体和数组一样也有许多分量组

397、尽管结构体和数组一样也有许多分量组成,但结构体的传递和普通内置类型是成,但结构体的传递和普通内置类型是一样的。它是将实际参数中的每个分量一样的。它是将实际参数中的每个分量复制到形式参数的每个分量中。复制到形式参数的每个分量中。程序设计 cs.sjtu 2005.9程序设计-651结构体的传递结构体的传递Void printPerson(PersonT p)程序设计 cs.sjtu 2005.9程序设计-652指向结构体的指针作为参数指向结构体的指针作为参数v因为结构体是值传递,当希望把函数内部对结构因为结构体是值传递,当希望把函数内部对结构体的修改返回给主调函数时,可以用指针传递或体的修改返回

398、给主调函数时,可以用指针传递或引用传递引用传递v由于结构体一般占用的内存量都比较大,值传递由于结构体一般占用的内存量都比较大,值传递既浪费空间又浪费时间。因此可用指针传递或引既浪费空间又浪费时间。因此可用指针传递或引用传递用传递v指针传递形式比较繁琐,所以指针传递形式比较繁琐,所以C+C+通常用引用传递通常用引用传递v引用传递的问题是函数中可以修改实际参数,要引用传递的问题是函数中可以修改实际参数,要控制函数中不能修改实际参数,可以加控制函数中不能修改实际参数,可以加constconst限定限定程序设计 cs.sjtu 2005.9程序设计-653指向结构体的指针作为参数指向结构体的指针作为参

399、数v和普通的指和普通的指针传递一样,针传递一样,函数中可以函数中可以通过指针访通过指针访问主调函数问主调函数的记录的记录v减少函数调减少函数调用时的数据用时的数据传递量传递量Void PrintPerson(personT &p);Void PrintPerson(const personT &p);程序设计 cs.sjtu 2005.9程序设计-654结构体传递的实例结构体传递的实例v设计一函数,打印学生信息设计一函数,打印学生信息程序设计 cs.sjtu 2005.9程序设计-655设计一:值传递设计一:值传递VoidPrintStudent(studentTs)couts.nots.na

400、mets.chinesets.mathts.englishendl;缺点:浪费时间空间缺点:浪费时间空间程序设计 cs.sjtu 2005.9程序设计-656设计二:指针传递或引用传递设计二:指针传递或引用传递VoidPrintStudent(studentT*s)coutnotnametchinesetmathtenglishendl;VoidPrintStudent(studentT&s)couts.nots.namets.chinesets.mathts.englishendl;缺点:不平安缺点:不平安程序设计 cs.sjtu 2005.9程序设计-657设计三:设计三:C+的常规做法的

401、常规做法VoidPrintStudent(conststudentT&s)couts.nots.namets.chinesets.mathts.englishdata=x;/把把x放入新节点的数据成员中放入新节点的数据成员中tmp-next=p-next;/把新节点和把新节点和p的下一成员相连的下一成员相连p-next=tmp;/把把p和新节点连接起来和新节点连接起来程序设计 cs.sjtu 2005.9程序设计-669单链表操作单链表操作删除删除把结点把结点p后的结点删除后的结点删除headpdelPtr delPtr=pnext;pnext=delPtrnext;deletedelPtr;

402、程序设计 cs.sjtu 2005.9程序设计-670单链表操作单链表操作-建立建立v定义头指针:定义头指针:linkRec*head;v建立头结点建立头结点申请空间申请空间设为头结点设为头结点head程序设计 cs.sjtu 2005.9程序设计-671单链表操作单链表操作-建立续建立续v逐个从键盘输入数据,存入链表逐个从键盘输入数据,存入链表接受输入接受输入申请空间申请空间输入数据放入申请到的空间输入数据放入申请到的空间链入链表尾链入链表尾v置链表结束标志置链表结束标志headabcd 程序设计 cs.sjtu 2005.9程序设计-672head=newlinkRec;rear=head

403、;cinin_data;while(输入未结束输入未结束)p=newlinkRec;pdata=in_data;rearnext=p;rear=p;cinin_data;rearnext=NULL;程序设计 cs.sjtu 2005.9程序设计-673单链表操作单链表操作输出输出headabcd p=headnext;while(p!=NULL)coutdata;p=pnext;程序设计 cs.sjtu 2005.9程序设计-674创立并访问一个带头结点的、存创立并访问一个带头结点的、存储整型数据的单链表,数据从键储整型数据的单链表,数据从键盘输入,盘输入,0为输入结束标志。为输入结束标志。#

404、includeusingnamespacestd;structlinkRecintdata;linkRec*next;程序设计 cs.sjtu 2005.9程序设计-675intmain()intx;/存放输入的值存放输入的值linkRec*head,*p,*rear;head=rear=newlinkRec;while(true)/创立链表的其他结点创立链表的其他结点cinx;if(x=0)break;p=newlinkRec;pdata=x;rearnext=p;rear=p;rearnext=NULL;/设置设置rear为表尾,其后没有结点了为表尾,其后没有结点了/读链表读链表coutn

405、ext;while(p!=NULL)coutdatanext;coutdatadata)c=a;a=anext;elsec=b;b=bnext;p=c;while(a!=NULL&b!=NULL)if(adatadata)pnext=a;a=anext;elsepnext=b;b=bnext;p=pnext;if(a=NULL)pnext=b;elsepnext=a;return(c);程序设计 cs.sjtu 2005.9程序设计-679单链表单链表v链表的概念链表的概念v链表的存储链表的存储v链表的操作链表的操作v链表的应用链表的应用v循环链表循环链表程序设计 cs.sjtu 2005.9

406、程序设计-680例:例:n个人围成一圈,从第一个人开始报数个人围成一圈,从第一个人开始报数1、2、3。凡报到。凡报到3者退出圈子。找出最后留在圈子中的人的序号。者退出圈子。找出最后留在圈子中的人的序号。解。用循环链表解。用循环链表01243head当当n=5时,其删除的节点的顺序为时,其删除的节点的顺序为2,0,4,1,最后剩,最后剩下的节点为下的节点为3。循环链表的应用循环链表的应用约瑟夫环约瑟夫环程序设计 cs.sjtu 2005.9程序设计-681structnodeintdata;node*next;intmain()node*head,*p,*q;/head为链表头为链表头intn,

407、i;/输入输入ncoutn;/建立链表建立链表head=p=newnode;p-data=0;/p指向表尾指向表尾for(i=1;idata=i;p-next=q;p=q;/将将q链入表尾链入表尾p-next=head;/头尾相连头尾相连程序设计 cs.sjtu 2005.9程序设计-682/删除过程删除过程q=head;while(q-next!=q)/只要表非空只要表非空for(i=0;inext;p-next=q-next;/绕过节点绕过节点qcoutdatanext;/让让q指向报指向报1的节点的节点/打印结果打印结果coutn最后剩下:最后剩下:dataendl;return0; 程

408、序设计 cs.sjtu 2005.9程序设计-683链表总结链表总结v实现较复杂实现较复杂v插入、删除效率高,但查找第插入、删除效率高,但查找第i个元素效个元素效率低率低v无表满的问题无表满的问题v适合于动态表适合于动态表程序设计 cs.sjtu 2005.9程序设计-684总结总结v本章介绍了结构体本章介绍了结构体v作用:作用:处理更复杂的数据处理更复杂的数据v使用:使用:定义类型定义类型定义变量定义变量v链表链表程序设计 cs.sjtu 2005.9程序设计-685第第9章章模块化开发模块化开发v自顶向下的分解自顶向下的分解v模块划分模块划分v库的设计与实现库的设计与实现v库的应用库的应用

409、程序设计 cs.sjtu 2005.9程序设计-686猜硬币的游戏猜硬币的游戏v功能:功能:提供游戏指南;提供游戏指南;计算机随机产生正反面,让用户猜,报告计算机随机产生正反面,让用户猜,报告对错结果。对错结果。v重复此过程,直到用户不想玩了为止。重复此过程,直到用户不想玩了为止。程序设计 cs.sjtu 2005.9程序设计-687顶层分解顶层分解v程序要做两件事:显示程序指南;模拟程序要做两件事:显示程序指南;模拟玩游戏的过程。玩游戏的过程。main( )main( ) 显示游戏介绍;显示游戏介绍; 玩游戏;玩游戏;主程序的两个步骤是相互独主程序的两个步骤是相互独立的两个,没有什么联系,因

410、立的两个,没有什么联系,因此可设计成两个函数:此可设计成两个函数:voidprn_instruction()voidplay(程序设计 cs.sjtu 2005.9程序设计-688int main()int main() prn_instruction(); prn_instruction(); play(); play(); return 0; return 0; 程序设计 cs.sjtu 2005.9程序设计-689prn_instruction的实现的实现vprn_instruction函数的实现非常简单,函数的实现非常简单,只要一系列的输出语句把程序指南显示只要一系列的输出语句把程序指

411、南显示一下就可以了一下就可以了voidprn_instruction()cout这是一个猜硬币正反面的游戏这是一个猜硬币正反面的游戏.n;cout我会扔一个硬币,你来猜我会扔一个硬币,你来猜.n;cout如果猜对了,你赢,否那么我赢。如果猜对了,你赢,否那么我赢。n;程序设计 cs.sjtu 2005.9程序设计-690play函数的实现函数的实现vPlay函数随机产生正反面,让用户猜,函数随机产生正反面,让用户猜,报告对错结果,然后询问是否要继续玩报告对错结果,然后询问是否要继续玩voidplay()charflag=y;while(flag=Y|flag=y)coin=生成正反面生成正反面

412、;输入用户的猜测;输入用户的猜测;if用户猜测用户猜测=coin报告本次猜测结果正确;报告本次猜测结果正确;else报告本次猜测结果错误;报告本次猜测结果错误;程序设计 cs.sjtu 2005.9程序设计-691play函数的细化函数的细化v生成正反面:如果用生成正反面:如果用0表示正面,表示正面,1表示反面,表示反面,那么生成正反面就是随机生成那么生成正反面就是随机生成0和和1两个数两个数v输入用户的猜测。如果不考虑程序的鲁棒性,输入用户的猜测。如果不考虑程序的鲁棒性,这个问题也可以直接用一个输入语句即可。但这个问题也可以直接用一个输入语句即可。但想让程序做得好一点,就必须考虑得全面一些。

413、想让程序做得好一点,就必须考虑得全面一些。比方,用户可以不守规那么,既不输入比方,用户可以不守规那么,既不输入0也不输也不输入入1,而是输入一个其他值,程序该怎么办?因,而是输入一个其他值,程序该怎么办?因此这个任务还可以进一步细化,所以再把它抽此这个任务还可以进一步细化,所以再把它抽象成一个函数象成一个函数get_call_from_user。程序设计 cs.sjtu 2005.9程序设计-692voidplay()intcoin;charflag=Y;srand(time(NULL);/设置随机数种子设置随机数种子while(flag=Y|flag=y)coin=rand()*2/RAND

414、_MAX;/生成扔硬币的结果生成扔硬币的结果if(get_call_from_user()=coin)cout你赢了你赢了;elsecout我赢了我赢了;coutflag;程序设计 cs.sjtu 2005.9程序设计-693get_call_from_user的实现的实现v该函数接收用户输入的一个整型数。如该函数接收用户输入的一个整型数。如果输入的数不是果输入的数不是0或或1,那么重新输入,那么重新输入,否那么返回输入的值否那么返回输入的值intget_call_from_user()intguess;/0=head,1=taildocoutguess;while(guess!=0&gues

415、s!=1);returnguess;程序设计 cs.sjtu 2005.9程序设计-694这是一个猜硬币正反面的游戏这是一个猜硬币正反面的游戏.我会扔一个硬币,你来猜我会扔一个硬币,你来猜.如果猜对了,你赢,否那么我赢。如果猜对了,你赢,否那么我赢。输入你的选择输入你的选择0表示正面,表示正面,1表示反面表示反面:1我赢了我赢了继续玩吗继续玩吗Y或或y?y输入你的选择输入你的选择0表示正面,表示正面,1表示反面表示反面:6输入你的选择输入你的选择0表示正面,表示正面,1表示反面表示反面:1你赢了你赢了继续玩吗继续玩吗Y或或y?nPressanykeytocontinue运行实例运行实例程序设计

416、 cs.sjtu 2005.9程序设计-695第第9章章模块化开发模块化开发v自顶向下的分解自顶向下的分解v模块划分模块划分v库的设计与实现库的设计与实现v库的应用库的应用程序设计 cs.sjtu 2005.9程序设计-696模块划分模块划分v当程序变得更长的时候,要在一个单独的源文当程序变得更长的时候,要在一个单独的源文件中处理如此众多的函数会变得困难件中处理如此众多的函数会变得困难v把程序再分成几个小的源文件。每个源文件都把程序再分成几个小的源文件。每个源文件都包含一组相关的函数。一个源文件被称为一个包含一组相关的函数。一个源文件被称为一个模块。模块。v模块划分标准:块内联系尽可能大,块间

417、联系模块划分标准:块内联系尽可能大,块间联系尽可能小尽可能小程序设计 cs.sjtu 2005.9程序设计-697石头、剪刀、布游戏石头、剪刀、布游戏v游戏规那么游戏规那么v布覆盖石头布覆盖石头v石头砸坏剪刀石头砸坏剪刀v剪刀剪碎布剪刀剪碎布v游戏的过程为:游戏者选择出石头、剪子或布,游戏的过程为:游戏者选择出石头、剪子或布,计算机也随机选择一个,输出结果,继续游戏计算机也随机选择一个,输出结果,继续游戏,直到游戏者选择结束为止。在此过程中,游,直到游戏者选择结束为止。在此过程中,游戏者也可以阅读游戏指南或看看当前战况。戏者也可以阅读游戏指南或看看当前战况。程序设计 cs.sjtu 2005.

418、9程序设计-698第一层的分解第一层的分解While While 用户输入用户输入 != quit != quit switch switch用户的选择用户的选择 case paper, rock, scissor: case paper, rock, scissor: 机器选择;机器选择; 评判结果;评判结果; 报告结果;报告结果; case game: case game: 显示目前的战况;显示目前的战况; case help: case help: 显示帮助信息;显示帮助信息; default: default: 报告错误;报告错误; 显示战况;显示战况;程序设计 cs.sjtu 200

419、5.9程序设计-699函数抽取函数抽取v获取用户输入获取用户输入selection_by_playerv获取机器输入获取机器输入selection_by_machinev评判结果评判结果comparev报告结果并记录结果信息报告结果并记录结果信息reportv显示目前战况显示目前战况prn_game_statusv显示帮助信息显示帮助信息prn_help六个函数六个函数程序设计 cs.sjtu 2005.9程序设计-700枚举类型的定义枚举类型的定义v为了提高程序的可读性,我们定义两个为了提高程序的可读性,我们定义两个枚举类型枚举类型:enump_r_spaper,rock,scissor,g

420、ame,help,quit;enumoutcomewin,lose,tie,error;程序设计 cs.sjtu 2005.9程序设计-701模块划分模块划分v分成四个模块:分成四个模块:v主模块:主模块:main函数函数v获取选择的模块:获取选择的模块:selection_by_player和和vselection_by_machinev比较模块:比较模块:comparev输出模块:输出模块:report、prn_game_status和和vprn_help函数函数程序设计 cs.sjtu 2005.9程序设计-702Select模块的设计模块的设计vselection_by_player从

421、键盘接收用户的输从键盘接收用户的输入并返回此输入值。因此,原型为入并返回此输入值。因此,原型为vp_r_sselection_by_player;vselection_by_machine函数由机器产生一函数由机器产生一个石头、剪子、布的值,并返回。因此,个石头、剪子、布的值,并返回。因此,原型为原型为vp_r_sselection_by_machine;程序设计 cs.sjtu 2005.9程序设计-703Compare模块的设计模块的设计vcompare函数比较用户输入的值和机器产生函数比较用户输入的值和机器产生的值,确定输赢。的值,确定输赢。v它要有两个参数,都是它要有两个参数,都是p_

422、r_s类型的,它也类型的,它也应该有一个返回值,就是判断的结果应该有一个返回值,就是判断的结果。v原型为:原型为:outcomecompare(p_r_s,p_r_s);程序设计 cs.sjtu 2005.9程序设计-704print模块的设计模块的设计vprn_help显示一个用户输入的指南,告诉用户显示一个用户输入的指南,告诉用户如何输入他的选择。因此,它没有参数也没有如何输入他的选择。因此,它没有参数也没有返回值。返回值。vReport函数报告输赢结果,并记录输赢的次数。函数报告输赢结果,并记录输赢的次数。因此它必须有四个参数:输赢结果、输的次数因此它必须有四个参数:输赢结果、输的次数、

423、赢的次数和平局的次数,但没有返回值。、赢的次数和平局的次数,但没有返回值。vprn_game_status函数报告至今为止的战况,函数报告至今为止的战况,因此需要三个参数:输的次数、赢的次数和平因此需要三个参数:输的次数、赢的次数和平的次数,但没有返回值。的次数,但没有返回值。程序设计 cs.sjtu 2005.9程序设计-705print模块的进一步考虑模块的进一步考虑v输的次数、赢的次数和平局的次数在输的次数、赢的次数和平局的次数在Report和和prn_game_status两个函数中都出现。两个函数中都出现。vReport函数修改这些变量的值,函数修改这些变量的值,prn_game_s

424、tatus函数显函数显示这些变量的值。示这些变量的值。v这三个函数的原型和用户期望的原型不一致,用户不希这三个函数的原型和用户期望的原型不一致,用户不希望原型中有参数。望原型中有参数。v输的次数、赢的次数和平局的次数和其他模块的函数无输的次数、赢的次数和平局的次数和其他模块的函数无任何关系,因此可作为该模块的内部状态。任何关系,因此可作为该模块的内部状态。v内部状态可以作为该模块的全局变量内部状态可以作为该模块的全局变量v这样这样report和和prn_game_status函数中都不需要这三个参函数中都不需要这三个参数了。数了。程序设计 cs.sjtu 2005.9程序设计-706头文件的设

425、计头文件的设计v为方便起见,我们把所有的符号常量定义、类型定义为方便起见,我们把所有的符号常量定义、类型定义和函数原型声明写在一个头文件中,让每个模块都和函数原型声明写在一个头文件中,让每个模块都include这个头文件。这个头文件。v那么,每个模块就不必要再写那些函数的原型声明了那么,每个模块就不必要再写那些函数的原型声明了v但这样做又会引起另一个问题,当把这些模块连接起但这样做又会引起另一个问题,当把这些模块连接起来时,编译器会发现这些类型定义、符号常量和函数来时,编译器会发现这些类型定义、符号常量和函数原型的声明在程序中反复出现屡次,原型的声明在程序中反复出现屡次,v解决方法:需要用到一

426、个新的编译预处理命令:解决方法:需要用到一个新的编译预处理命令:v#ifndef标识符标识符vv#endif程序设计 cs.sjtu 2005.9程序设计-707头文件的格式头文件的格式#ifndef_name_h#define_name_h 头文件真正需要写的内容头文件真正需要写的内容#endif程序设计 cs.sjtu 2005.9程序设计-708石头、剪子、布游戏的头文件石头、剪子、布游戏的头文件/文件:文件:/本文件定义了两个枚举类型,声明了本程序包括的所有函数原型本文件定义了两个枚举类型,声明了本程序包括的所有函数原型#ifndefP_R_S#defineP_R_S#include#

427、include#includeusingnamespacestd;enump_r_spaper,rock,scissor,game,help,quit;enumoutcomewin,lose,tie,error;outcomecompare(p_r_splayer_choice,p_r_smachine_choice);voidprn_final_status();voidprn_game_status();voidprn_help();voidreport(outcomeresult);p_r_sselection_by_machine();p_r_sselection_by_player(

428、);#endif程序设计 cs.sjtu 2005.9程序设计-709主模块的实现主模块的实现/文件:文件:/石头、剪子、布游戏的主模块石头、剪子、布游戏的主模块#includep_r_s.hintmain(void)outcomeresult;p_r_splayer_choice,machine_choice;/seedtherandomnumbergeneratorsrand(time(NULL);程序设计 cs.sjtu 2005.9程序设计-710while(player_choice=selection_by_player()!=quit)switch(player_choice)c

429、asepaper:caserock:casescissor:machine_choice=selection_by_machine();result=compare(player_choice,machine_choice);report(result);break;casegame:prn_game_status();break;casehelp:prn_help();break;default:coutPROGRAMMERERROR!nn;exit(1);prn_game_status();return0;程序设计 cs.sjtu 2005.9程序设计-711select模块的实现模块的实

430、现/文件:文件:/包括机器选择包括机器选择selection_by_machine和和/玩家选择玩家选择selection_by_player函数的实现函数的实现#includep_r_s.hp_r_sselection_by_machine()intselect=(rand()*3/(RAND_MAX+1);coutIam;switch(select)case0:coutpaper.;break;case1:coutrock.;break;case2:coutscissor.;break;return(p_r_s)select);程序设计 cs.sjtu 2005.9程序设计-712p_r_

431、sselection_by_player()charc;p_r_splayer_choice;prn_help();/显示输入提示显示输入提示coutc;switch(c)casep:player_choice=paper;coutyouarepaper.;break;caser:player_choice=rock;coutyouarerock.;break;cases:player_choice=scissor;coutyouarescissor.;break;caseg:player_choice=game;break;caseq:player_choice=quit;break;def

432、ault:player_choice=help;break;returnplayer_choice;程序设计 cs.sjtu 2005.9程序设计-713Compare模块的实现模块的实现/文件文件:compare.cpp/包括包括compare函数的实现函数的实现#includep_r_s.houtcomecompare(p_r_splayer_choice,p_r_smachine_choice)outcomeresult;if(player_choice=machine_choice)returntie;switch(player_choice)casepaper:result=(mac

433、hine_choice=rock)?win:lose;break;caserock:result=(machine_choice=scissor)?win:lose;break;casescissor:result=(machine_choice=paper)?win:lose;break;default:coutPROGRAMMERERROR: Unexpectedchoice!nn;exit(1);returnresult;程序设计 cs.sjtu 2005.9程序设计-714Print模块的实现模块的实现/文件:文件:print.cpp/包括所有与输出有关的模块。包括所有与输出有关的模块

434、。/有有prn_game_status,prn_help和和report函数函数#includep_r_s.hintwin_cnt=0,lose_cnt=0,tie_cnt=0;/模块的内部状态模块的内部状态程序设计 cs.sjtu 2005.9程序设计-715void report(outcome result)switch(result) case win: +win_cnt; cout You win. n; break; case lose: +lose_cnt; cout You lose.n; break; case tie: +tie_cnt; cout A tie.n; bre

435、ak; default: cout PROGRAMMER ERROR!nn; exit(1); 程序设计 cs.sjtu 2005.9程序设计-716voidprn_game_status()coutendl;coutGAMESTATUS:endl;coutwin:win_cntendl;coutLose:lose_cntendl;couttie:tie_cntendl;coutTotal:win_cnt+lose_cnt+tie_cntendl;程序设计 cs.sjtu 2005.9程序设计-717voidprn_help()coutendlThefollowingcharacterscan

436、beused:npforpapernrforrocknsforscissorsngprintthegamestatusnhhelp,printthislistnqquitthegamen;程序设计 cs.sjtu 2005.9程序设计-718第第9章章模块化开发模块化开发v自顶向下的分解自顶向下的分解v模块划分模块划分v库的设计与实现库的设计与实现v库的应用库的应用程序设计 cs.sjtu 2005.9程序设计-719设计自己的库设计自己的库v如果你的工作经常要用到一些特殊的工具,你如果你的工作经常要用到一些特殊的工具,你可以设计自己的库可以设计自己的库v一个库应该有一个主题。一个库中的函数都

437、应一个库应该有一个主题。一个库中的函数都应该是处理同一类问题。如标准库该是处理同一类问题。如标准库iostream包含输包含输入输出功能,入输出功能,cmath包含数学运算函数。我们自包含数学运算函数。我们自己设计的库也要有一个主题。己设计的库也要有一个主题。v设计一个库还要考虑到它的通用性。库中的功设计一个库还要考虑到它的通用性。库中的功能应来源于某一应用,但不局限于该应用,而能应来源于某一应用,但不局限于该应用,而且要高于该应用。在某一应用程序中提取库内且要高于该应用。在某一应用程序中提取库内容时应尽量考虑到兼容更多的应用,使其他应容时应尽量考虑到兼容更多的应用,使其他应用程序也能共享这个

438、库。用程序也能共享这个库。程序设计 cs.sjtu 2005.9程序设计-720库的设计和实现库的设计和实现v设计库的接口:设计库的接口:库的用户必须了解的内容,包括库中函数的原库的用户必须了解的内容,包括库中函数的原型、这些函数用到的符号常量和自定义类型型、这些函数用到的符号常量和自定义类型接口表现为一个头文件接口表现为一个头文件v设计库中的函数的实现:表现为一个源文件设计库中的函数的实现:表现为一个源文件v库的这种实现方法称为信息隐藏库的这种实现方法称为信息隐藏程序设计 cs.sjtu 2005.9程序设计-721随机函数库的设计随机函数库的设计v库的功能库的功能在中,用到了随机生成在中,

439、用到了随机生成0和和1在中,用到了随机生成在中,用到了随机生成0和和2在自动出题中,用到了随机生成在自动出题中,用到了随机生成0和和3及随机生成及随机生成0到到9用一个函数概括:生成用一个函数概括:生成low到到high之间的随机数之间的随机数intRandomInteger(intlow,inthigh)初始化函数初始化函数RandomInit()实现设置随机数种子的功能实现设置随机数种子的功能在节中,设计了一个掷硬币的程序。该程序用到了随机数的一些特性。如果我们的工作经常需要用到随机数,我们可以把随机数的应用写成一个库。 程序设计 cs.sjtu 2005.9程序设计-722接口文件接口文

440、件v头文件的格式:与石头、剪子、布游戏头文件的格式:与石头、剪子、布游戏中的头文件格式一样。中的头文件格式一样。v头文件中,每个函数声明前应该有一段头文件中,每个函数声明前应该有一段注释,告诉用户如何使用这些函数。注释,告诉用户如何使用这些函数。程序设计 cs.sjtu 2005.9程序设计-723库接口的设计库接口的设计/文件:文件:/随机函数库的头文件随机函数库的头文件#ifndef_random_h#define_random_h/函数函数:RandomInit/用法用法:RandomInit()/作用作用:此函数初始化随机数种子此函数初始化随机数种子voidRandomInit();/

441、函数函数:RandomInteger/用法用法:n=RandomInteger(low,high)/作用:此函数返回一个作用:此函数返回一个low到到high之间的随机数,包括之间的随机数,包括low和和highintRandomInteger(intlow,inthigh);#endif程序设计 cs.sjtu 2005.9程序设计-724库的实现库的实现v库的实现文件和头文件的名字是相同的。库的实现文件和头文件的名字是相同的。如头文件为,那么实现文件为。如头文件为,那么实现文件为。v实现文件的格式:实现文件的格式:v注释:这一局部简单介绍库的功能。注释:这一局部简单介绍库的功能。vincl

442、ude此此cpp文件所需的头文件。文件所需的头文件。v每个实现要包含自己的头文件,以便编译每个实现要包含自己的头文件,以便编译器能检查函数定义和函数原型声明的一致器能检查函数定义和函数原型声明的一致性。性。v每个函数的实现代码。在每个函数实现的每个函数的实现代码。在每个函数实现的前面也必须有一段注释。前面也必须有一段注释。程序设计 cs.sjtu 2005.9程序设计-725/文件:文件:/该文件实现了该文件实现了Random库库#include#include#includeRandom.h/函数:函数:RandomInit/该函数取当前系统时间作为随机数发生器的种子该函数取当前系统时间作为

443、随机数发生器的种子voidRandomInit()srand(time(NULL);程序设计 cs.sjtu 2005.9程序设计-726/函数:函数:RandomInteger/该函数将该函数将0到到RAND_MAX的区间的划分成的区间的划分成high-low+1个个/子区间。当产生的随机数落在第一个子区间时,那么映射成子区间。当产生的随机数落在第一个子区间时,那么映射成low。/当落在最后一个子区间时,映射成当落在最后一个子区间时,映射成high。当落在第。当落在第i个子区间时个子区间时/i从从0到到high-low,那么映射到,那么映射到low+iintRandomInteger(int

444、low,inthigh)return(low+(high-low+1)*rand()/(RAND_MAX+1);程序设计 cs.sjtu 2005.9程序设计-727第第9章章模块化开发模块化开发v自顶向下的分解自顶向下的分解v模块划分模块划分v库的设计与实现库的设计与实现v库的应用库的应用程序设计 cs.sjtu 2005.9程序设计-728库的应用库的应用-龟兔赛跑龟兔赛跑动物动物跑动类型跑动类型占用时间占用时间跑动量跑动量乌龟乌龟快走快走50%向前走向前走3点点后滑后滑20%向后退向后退6点点慢走慢走30%向前走一点向前走一点兔子兔子睡觉睡觉20%不动不动大后滑大后滑20%向后退向后退9

445、点点快走快走10%向前走向前走14点点小步跳小步跳30%向前走向前走3点点慢后滑慢后滑20%向后退向后退2点点程序设计 cs.sjtu 2005.9程序设计-729龟兔赛跑解题思路龟兔赛跑解题思路v分别用变量分别用变量tortoisetortoise和和harehare代表乌龟和代表乌龟和兔子的当前位置兔子的当前位置v时间用秒计算时间用秒计算v用随机数来决定乌龟和兔子在每一秒的用随机数来决定乌龟和兔子在每一秒的动作,根据动作决定乌龟和兔子的位置动作,根据动作决定乌龟和兔子的位置的移动的移动v跑道的长度设为跑道的长度设为7070个点个点程序设计 cs.sjtu 2005.9程序设计-730第一层

446、分解第一层分解main()inthare=0,tortoise=0,timer=0;/timer是计时器,从是计时器,从0开始计时开始计时while(hareRACE_END&tortoisetortoise)coutnharewins!;elsecoutntortoisewins!;程序设计 cs.sjtu 2005.9程序设计-731抽取函数抽取函数v乌龟在这一秒的移动距离:乌龟在这一秒的移动距离:intmove_tortoise();v兔子在这一秒的移动距离:兔子在这一秒的移动距离:intmove_hare();v输出当前计时和兔子乌龟的位置输出当前计时和兔子乌龟的位置voidprint

447、_position(inttimer,inttortoise,inthare);程序设计 cs.sjtu 2005.9程序设计-732模块划分模块划分v主模块主模块v移动模块移动模块move_tortoisemove_hare()v输出模块输出模块print_position程序设计 cs.sjtu 2005.9程序设计-733主模块主模块#includeRandom.h/包含随机数库包含随机数库#includeusingnamespacestd;constintRACE_END=70;/设置跑道的长度设置跑道的长度intmove_tortoise();intmove_hare();voidp

448、rint_position(int,int,int);程序设计 cs.sjtu 2005.9程序设计-734intmain()inthare=0,tortoise=0,timer=0;RandomInit();/随机数初始化随机数初始化couttimertortoiseharen;/输出表头输出表头while(hareRACE_END&tortoisetortoise)coutnharewins!n;elsecoutntortoisewins!n;return0;程序设计 cs.sjtu 2005.9程序设计-735如何用随机数模拟概率如何用随机数模拟概率v以乌龟为例,它的三种情况和概率如下:

449、以乌龟为例,它的三种情况和概率如下:为此我们可以生成为此我们可以生成09之间的随机数,当生成的随之间的随机数,当生成的随机数为机数为04时,认为是第一种情况,时,认为是第一种情况,56是第二种情是第二种情况,况,79是第三种情况。这样就可以根据生成的随是第三种情况。这样就可以根据生成的随机数确定发生的事件机数确定发生的事件快走快走50%50%后滑后滑20%20%慢走慢走30%30%程序设计 cs.sjtu 2005.9程序设计-736Move模块模块/文件名:文件名:#includeRandom.h/本模块用到了随机函数库本模块用到了随机函数库intmove_tortoise()intprob

450、ability=RandomInteger(0,9);/产生产生0到到9之间的随机数之间的随机数if(probability5)return3;/快走快走elseif(probability7)return6;/后滑后滑elsereturn1;/慢走慢走程序设计 cs.sjtu 2005.9程序设计-737intmove_hare()intprobability=RandomInteger(0,9);if(probability2)return0;/睡觉睡觉elseif(probability4)return-9;/大后滑大后滑elseif(probability5)return14;/快走快

451、走elseif(probability8)return3;/小步跳小步跳elsereturn-2;/慢后滑慢后滑程序设计 cs.sjtu 2005.9程序设计-738Print模块模块/文件名:文件名:#includeusingnamespacestd;voidprint_position(inttimer,intt,inth)if(timer%6=0)coutendl;/每隔每隔6秒空一行秒空一行couttimerttthn;程序设计 cs.sjtu 2005.9程序设计-739总结总结v本章介绍了本章介绍了v如何利用结构化程序设计的技术来解决一个如何利用结构化程序设计的技术来解决一个大问题。大问题。v利用结构化程序设计的技术可以容易地将一利用结构化程序设计的技术可以容易地将一个应用分成假设干个独立的模块来构建整个个应用分成假设干个独立的模块来构建整个程序。程序。v如何在模块中保存内部状态如何在模块中保存内部状态v如何从程序中抽取出库以及如何设计和使用如何从程序中抽取出库以及如何设计和使用库库

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号