《c++程序设计谭浩强第3章.doc》由会员分享,可在线阅读,更多相关《c++程序设计谭浩强第3章.doc(75页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第三章 程序设计初步31 面向过程的程序设计和算法3.1.1 算法的概念一个程序应包括对解决问题所需要的数据的描述和对数据处理的描述。1对数据的描述,即数据结构。2对数据处理的描述,即计算机算法。算法是为解决一个问题而采取的方法和步骤,是程序的灵魂。为此,著名计算机科学家沃思(Nikiklaus Wirth)提出一个经典公式: 数据结构 + 算法 = 程序案例3.1 输入三个数,求其最大值。问题分析:设num1,num2,num3存放3个数,max存放其最大值。为求其最大值,就必须对3个数进行比较,可按如下步骤去做:输入3个数num1,num2,num3;先把第一个数num1的值赋给max;将
2、第2个数num2与max比较,如果num2max,则把第2个数num2的值赋给max(否则不做任何工作)将第3个数num3与max比较,如果num3max,则把第3个数num3的值赋给max(否则不做任何工作)输出max的值,即最大值。从案例中可以看出,首先分析问题,然后寻找一种实现这个问题所要完成功能的方法,这种方法的具体化就称为算法。因此可以说:算法是由一套明确的规则组成的一些步骤,他指定了操作顺序并通过有限个步骤将问题解决、得出结果。3.1.2 算法的特性一个算法应具有以下5个特性:(1)有穷性一个算法必须总是在执行有限个操作步骤和可以接受的时间内完成其执行过程。(2)确定性算法中的每一
3、步都必须有明确的含义,不允许存在二义性。(3)有效性算法中描述的每一步操作都应该能有效地执行,并最终得到确定的结果。(4)输入一个算法有零个或多个输入数据。(5)输出一个算法有1个或多个输出数据。3.1.2 算法的表示方法(P46)算法的表示方法很多,常见的有:自然语言、传统流程图、N-S结构图、伪代码、PAD图等。(1)用自然语言表示自然语言就是人们日常使用的语言,可以是中文、英文等。用自然语言表示的算法通俗易懂,但一般篇幅冗长,表达上往往不易准确,容易引起理解上的“歧义性”。所以,一般用于算法较简单的情况。(2)用传统流程图表示传统流程图是用规定的一组符号、流程线和文字说明来表示各种操作算
4、法的表示方法。传统流程图常用的符号如图3.1所示案例3.1 用传统流程图描述的算法如下图所示。(3)用N-S结构图表示N-S结构图的目标是开发一种不破坏结构化基本构成元素的过程设计表示。其主要特点是:完全取消了流程线,不允许有随意的控制流,全部算法写在一个矩形框内,该矩形框以三种基本结构(顺序、分支、循环)描述符号为基础符合而成。案例3.1 用N-S结构图描述如下 (4)用伪代码表示伪代码是一种介于自然语言和计算机语言之间的文字和符号来描述算法。伪代码的表现形式比较灵活自由,没有严谨的语法格式。案例3.1用伪代码描述如下input num1,num2,num3num1maxif num2max
5、 then num2 maxif num3max then num3 maxprint max32 C+程序和语句 一 C+程序的组成 (P47)预处理命令声明部分函数二、C+的语句概述 (P48)一条完整的语句必须以分号“;”结束。C+程序语句有如下几类:(1)说明语句用来说明变量的类型和初值。如:float a,b,c;int sum=0;(2)表达式语句由一个表达式构成一个语句,用以描述算术运算、逻辑运算、或产生某种特定动作,在任何表达式最后加一个分号就构成了一个语句。如:c=a+b /*赋值表达式*/c=a+b; /*赋值表达式语句*/注:掌握表达式语句的用法,关键在于要正确理解有关表
6、达式的内容。(3)程序控制语句用来描述语句的执行条件与执行顺序的语。C+的控制语句有9种,如下所示。其语句中的括号( )表示其中是条件,表示内嵌的语句if () else 条件(分支)语句switch 多分支选择语句for () 循环结构语句while () 循结构环语句do while () 循环结构语句continue 结束本次循环语句break 中止执行switch或循环语句goto 转移语句return 从函数返回语句(4)复合语句复合语句是由一对花括号 括起来的一组语句。如果要在只执行一条语句的地方执行多条语句,那么这多条语句要用一对花括号 括起来构成一条复合语句。例如: c=a;a
7、=b;b=c; /实现a,b两个变量值的交换(5)函数调用语句函数调用语句是由一次函数调用加一个分号而构成的一个语句。例如:max(x,y);(6)空语句空语句不进行任何操作,它仅由一个分号“;”构成。通常用在应该放置语句而又不需要执行任何动作的地方,例如:;33 赋值语句 (P4950)赋值语句是由赋值表达式加上一个分号构成的。最简单的一种形式为:变量=表达式;例如: rad=14.5; /*将实型数赋给变量rad*/ cr=2*3.14*rad; /*将表达式2*3.14*rad的值赋给变量cir*/说明:“=”是赋值符号,赋值符号的右边是由常量、变量、运算符和函数组成的表达式。因赋值语句
8、是由赋值表达式加上一个分号构成,所以下面是合法的赋值语句:i+;x+=2;j-;注:在程序设计中,赋值语句不仅用于为变量进行赋值,同时还大量用于运算处理。34 C+的输入与输出(P5057)3.4.1 输入流与输出流的基本操作在C+中,将数据从一个对象到另一个对象的流动抽象为“流“,如:每次输入或输出都可以看做是数据流。数据的输入与输出时通过I/O流来实现的。1输出操作标准输出流cout与流插入运算符 联用,可实现一般的屏幕数据输出。一般格式如下: cout表达式表达式说明:(1)在输出语句中,可以串联多个插入运算符,输出多个数据项。例如: cout”hellon”; cout”how are
9、 you?”; cout”My name is Alice”; coutendl;可写成:cout”hellon”how are you?”My name is Alice”endl;或:cout”hellon”how are you?” ”My name is Alice” endl;注:中间的行尾没有分号结尾(2)在插入运算符后面可以是任意复杂的表达式,系统将自动计算出它们的值,并传给输入符。例如:cout“3+4=“”联用,可实现一般的键盘输入。一般格式如下: cin 变量1变量2 说明:在输入语句中,提取符可以连续写多个,每个后面跟一个变量。例如: int a,b; cinab;用户在
10、输入多个数据时,各数据之间应用空格分隔。(P53)3.4.2 在输入流与输出流中使用控制符C+提供的预定义的操作符见P53表3.1说明:(1)C+中所有不带形参的操作符都定义在头文件iostream中,带形参的操作符定义在头文件iomanip.h中;(2)在进行输入输出时,操作符必须嵌入到输入或输出键中用来控制输入输出格式。案例32 操作符的使用#include#includeusing namespace std;int main()coutsetw(10)123567endl;cout123setiosflags(ios:scientific)setw(20)123.endl;cout12
11、3setw(10)hex123endl;cout123setw(10)oct123endl;cout123setw(10)dec123endl;coutresetiosflags(ios:scientific)setprecision(4)123.endl;coutsetiosflags(ios:left)setfill(#)setw(8)123endl;coutresetiosflags(ios:left)setfill($)setw(8)456endl;return 0;案例33 各行小数点对齐P53例3.1#include #include using namespace std;int
12、 main() double a=123.456,b=3.14159,c=-3214.67; coutsetiosflags(ios:fixed)setiosflags(ios:right)setprecision(2); coutsetw(10)aendl; coutsetw(10)bendl; coutsetw(10)cendl; return 0;3.4.3 用getchar和putchar函数实现字符的输入和输出1. 字符输出putchar函数putchar()函数的功能是用于将一个字符输出到显示器上显示。putchar()函数的一般调用形式为: putchar(c);即把变量c的值输
13、出到显示器上,这里的c 可以是字符型或整型变量,也可以是一个转义字符。案例3.4 putchar()函数应用举例1#include using namespace std;int main() char a,b,c,d; a=g; b=o; c=111; d=d; putchar(a); putchar(b); putchar(c); putchar(d); return 0;运行情况如下:good说明:putchar()函数只能用于单个字符的输出,并且一次只能输出一个字符。2. 字符输入grtchar函数getchar()函数的一般调用形式为:c= getchar();案例3.5 getch
14、ar()函数应用举例P56例3.3#include using namespace std;int main()char c; c=getchar(); /*接收用户从键盘上输入的一个字符*/ putchar(c+32); /*输出字符变量c+32后的值*/ putchar(n); return 0;运行情况如下:A a 说明:getchar()函数只能用于单个字符的输入,且一次只能输入一个字符3.4.4 用scanf和printf函数实现输入和输出 (P57)C+保留了C的由标准库函数printf(),scanf()来实现输入/输出操作的方法。一、printf()格式输出函数 格式输出函数p
15、rintf()的功能是按指定的格式向显示器输出一个或多个任意类型的数据。printf()函数的一般调用形式为:printf(“格式控制”,输出项表);例如:printf(“hello”);printf(“The area is :%fn“,area);说明:格式控制。格式控制的两边必须用引号,其中的内容可以包含:普通字符、格式说明符和转义字符(a)普通字符:即需要原样输出的字符信息。(b)格式说明符:用%开头后面跟有一个字母,它规定了输出项的输出形式。格式说明符在个数和类型上应与输出项匹配。常用的格式说明符见下表。案例36 printf输出形式举例1#include using namespa
16、ce std;int main() int num1,num2; float r1,r2,re; char ch; num1=65; num2=-3; r1=234.5; r2=18.75; re=r1+r2; ch=A; printf(%d %c %d %o %f %c %d,num1,num1,num2,num2,re,ch,ch); printf(%sn,Very good); return 0;运行情况:说明:整型变量可以以字符的形式输出,而字符变量也可以整数的形式输出,ASCII码是他们之间的桥梁。负数在计算机内存中是以补码的形式存放。变量num2的值为-3,-3的补码为:11111
17、11111111101用八进制表示即:,所以变量num2以%o的格式输出时,显示。(c)附加格式字符()字 符说 明字母 l,hl用于长整型整数,h用于短整型或无符号短整型整数,可以加在格式字符d,o,x,u前面m(代表一个正整数)数据的输出宽度n(代表一个正整数)对实数,表示输出小数位的位数;对字符串,表示截取的字符个数-输出的数字或字符向左靠齐案例37 printf输出形式举例2#include using namespace std;int main() int num1=123; long num2=; float re=123.4567; printf(%d,%6d,%-6d,%2d
18、n,num1,num1,num1,num1); printf(%ld,%8ld,%4ldn,num2,num2,num2); printf(%f,%10f,%10.2f,%-10.2fn,re,re,re,re); printf(%s,%10.5s,%-10.5sn,student,student,student);运行情况如下:输出项表。输出项表中可以有多个输出项,各项之间用逗号分隔。注:Printf()函数在使用时要注意以下几点:(a)Printf()函数可以输出常量、变量和表达式的值。但格式控制中的格式说明符必须按从左到右的顺序,与输出项表中的每个数据一一对应,否则会出错。(b)类型转换
19、字符紧跟在“%”后面时作为类型转换字符,否则将作为普通字符处理(即原样输出)。例如:printf(“c=%c,f=%fn”,c,f)中的第一个c和f都是普通字符。二、数据输入函数(scanf)格式输入函数scanf()的功能是用来从外部输入设备(通常是键盘),向程序中的变量输入一个或多个任意类型的数据。1scanf()函数的一般调用形式为:scanf(“格式控制”,输入项表);例如: scanf(“%d%f”,&x,&y);说明:格式控制。格式控制的两边必须用引号,其中的内容可以由格式说明符和普通字符组成。(a)普通字符。普通字符在输入数据时,必须在对应位置上原样输入这些字符。例如: scan
20、f(“character:%c,real:%f”,&x,&y);函数中的:“character:”、“real:”和“,”都是普通字符,则在实际运行时输入: character:w,real:12.5 (b)格式说明符。scanf()中的格式说明符的使用与printf()函数相似,必须用%开头后面跟一个字母(也可在其中间增加附加字符),它规定了输入项对应的输入数据格式。同样格式说明符要在个数和类型上与输入项相匹配。scanf()函数常用的格式说明符及附加字符见下表:scanf()函数格式说明符格式说明符输 入 内 容%d十进制整数%o八进制整数%x十六进制整数%c单个字符%s输入一个字符串,输
21、入时以非空白字符开始,以第一个空白字符结束。(字符串送到一个字符数组中)%f实数。可以用小数形式或指数形式输入%e同%f,e与f可以相互替换scanf()函数附加格式说明符附加说明字符说 明l用于输入长型数据:%ld,%lo,%lx等h用于输入短整型数据:%hd等域宽m指定输入数据所占的列数*表示本输入数据在读入后不赋给相应的变量输入项表。输入项表中是要输入数据的变量的存储单元地址。“&”是地址运算符,“&x”表示变量x在内存中的地址。2scanf函数在使用时,从键盘输入数据要注意以下几点:(a)scanf函数没有计算功能,因此输入的数据只能是常量,而不可以是表达式。例如: scanf(“%d
22、%d%d”,&x,&y,&z);表示要输入3 个十进制整数,可按以下方式输入:12 34 56 或 12 34 56 例如: scanf(“%c%c”,&c1,&c2);表示要输入两个字符型数据,按以下方式输入:ab 则字符a符给变量c1,字符b符给变量c2。(b)输入格式中,除格式说明符之外的普通字符应原样输入。例如:scanf(“x=%d,y=%d,z=%d”,&x,&y,&z);应使用以下形式输入:x=12,y=34,z=56 (c)由于scanf()函数本身不具有显示提示信息功能,为改善人机交互性,在设计输入操作时,一般先用printf()函数输出一个提示信息,然后再用scanf()函
23、数进行数据输入。例如:printf(“Enter width and height:”) scanf(“%f,%f”,&width,&height)35 顺序结构程序设计在顺序结构程序中,程序的执行是按照各语句出现的先后次序,顺序执行的,并且每个语句都会被执行到。例如:已知某个三角形的底和高,计算其面积。问题分析:设:h表示三角形的高,w表示三角形的底,则三角形面积为: area=w*h/2解决该问题的算法用传统流程图描述如下:从图中可以看出,顺序结构程序通常由三部分组成:输入数据: 进行处理: 输出结果: 案例38 编程实现输入某个三角形的底和高,计算其面积。#include using n
24、amespace std;int main() float w,h,area; coutwh; area=w*h/2.0; cout”The area is :areaendl; return 0;运行结果为:Enter width and height:2.5,4The area is :5.案例39输入一个double类型的数,使该数保留小数点后两位,对第三位小数进行四舍五入。#include using namespace std;int main() double x; coutx; cout(1) x=xendl; x=x*100; x=x+0.5; x=(int)x; x=x/10
25、0; cout(2) x=xendl; return 0;36 分支(选择)结构程序设计36.1 分支结构的设计思想顺序结构程序的流程方向永远是自上而下顺序执行的。但在实际应用中常常需要根据不同的条件(即情况)。执行不同的程序流程(即进行不同的处理),即形成了所谓的“分支”结构。案例3.10 货运公司对旅客托运行李计算收费。按规定,托运行李不超过30kg时,每千克收取运费0.15元,如超过30kg,超过的部分按每千克0.25 元收费。问题分析:设行李质量为:w(kg),运费为:f(元)。根据题意可得运费的计算公式为: 其算法如下图所示:从图中可以看出,分支结构程序的设计要考虑两个方面的问题:判
26、断条件。实现分支结构语句的构成及选择。3.6.2 实现分支结构判断条件的构成一、关系运算符与关系表达式(P59)1关系运算符及其优先顺序说明:关系运算符的优先级别与其他种类运算符相比,低于算术运算符,但高于赋值运算符。例如:ca+b 等效于 cb 等效于 c=(ab)关系运算符=,b , a+b=9.7 , x!=y关系表达式的运算结果只有两种情况:当关系成立时,则表达式的结果值为1(表示“真”);当关系不成立时,则表达式的结果值为0(表示“假”)。这里的0和1都看成是整型量,可以进行整型量所允许的各种操作。例如: a=(bc)当b的值时10,c的值为6时,a的值1;而当b的值时5,c的值为7
27、时,a的值0;二、逻辑常量和逻辑变量C+新增了逻辑型数据。其中:逻辑型常量表示为:true,flase逻辑型变量表示为:bool 例如: bool f1, f2;注:可对f1, f2取值true或flase; 表示“真”或“假” 亦可取值 0或非0数值,但其内存中只存放1或0 说明:1. 逻辑型变量在内存中分配一个字节,用于存放 1 或 02.逻辑型数据可参加算术运算例如:int a=2;bool f1=true;a=a+true+f1;couta ;输出结果: 4三、逻辑运算符与逻辑表达式(P61)1逻辑运算符极其优先顺序 逻辑运算符说明:逻辑运算符“&”和“|”是双目运算符,而“!”是单目
28、运算符;逻辑运算符的优先级与其他种类的运算符相比,其优先关系从高到低如下所示: !(非) 算术运算 关系运算 &(与) |(或) 赋值运算例如: x=ab&c=d 相当于: x=(ab)&(c=0)&(x10) 的值为 1 (x10) 的值为 02逻辑表达式用逻辑运算符将运算量连接起来的表达式称为逻辑表达式。逻辑表达式的值是一个逻辑值,即“真“或“假”。这里的运算量通常是关系表达式或逻辑量。例如:表示“三门课成绩均为及格“的逻辑表达式为: (math=60)&(phys=60)&(engl=60)表示“三门课成绩中至少有一门不及格“的逻辑表达式为:(math60) | (phys60) | (
29、engl60)需要注意的是,在逻辑表达式的求解过程中,并不是所有的逻辑运算符都被执行,只是在必须执行下一逻辑运算符才能求出表达式的解时,才执行该运算符。例如:a&b&c,当a为0时,就不再判断或计算b和c的值,因为此时整个逻辑表达式的值已经可以确定为0;a | b | c,当a为1时,就不再判断或计算b和c的值,因为此时整个逻辑表达式的值已经可以确定为1;3.6.3实现分支结构程序设计的语句一、 if 语句1if 语句的简单形式if (表达式) 语句语句的执行过程:先判断或计算表达式的值,若结果为“真“(非0),则执行指定的语句,否则跳过所给出的语句,接着执行下面的语句。例311 根据输入的学
30、生成绩对其进行判断处理:如果成绩及格(假定60分是及格分数线),则输出“Passed“(及格);否则,不做任何输出。程序如下:#include using namespace std;int main() int score; coutscore; if (score=60) cout”nPassedn; return 0;2If语句的标准形式表达式 语句1假真假 语句2if (表达式) 语句1else 语句2语句的执行过程:先判断或计算表达式的值,若结果为“真“(非0),则执行语句1,否则执行语句2。例312 将例3.11改为:如果成绩及格,则输出“Passed“;否则输出”Failed“。
31、程序如下:#include using namespace std;int main() int score; coutscore; if (score=60) coutnPassedn; else coutnFailedn; return 0;3If语句的嵌套形式所谓if 语句的嵌套形式是指在if 语句中又包含了一个或多个if 语句。if 语句嵌套的目的是为了解决多路分支处理问题。(1)在if子句中嵌套具有else子句的if语句if (表达式1) if (表达式2) 语句1 else 语句2else 语句3(2)在if子句中嵌套不含else字句的if语句if (表达式1) if (表达式2)
32、 语句1 else 语句2注意:在if字句中的一对花括号不可省略。(C规定,else字句总是与前面最近的不带else的if配对)问题:在此嵌套的if语句中,什么条件下将执行语句1。(3)在else字句中嵌套if语句形式一: 形式二:嵌套if语句带有else 嵌套if语句不带有elseif (表达式1) if (表达式1) 语句1 语句1else else if (表达式2) if (表达式2)语句2 语句2 else 语句3一种较为规范的嵌套的ifelse结构形式:if (表达式1) 语句1else if (表达式2) 语句2 else if (表达式3) else if (表达式n) 语句n
33、 else 语句n+1例313 输入一个学生的成绩,当成绩90时,输出“Very good“;当80成绩90时,输出“Good“;当60成绩80时,输出“Passed”;当成绩60时,输出“Failed”。问题分析:根据学生成绩分别落入不同的分数段(4种),而输出不同的评语。这是一个具有4路分支的问题。程序如下:#include using namespace std;int main() int score; coutscore; if (score=90) cout=80) cout=60) coutPassedn; else coutFailedn; return 0; 关于if 语句,
34、有以下几点需加以说明:if 语句后面的表达式一般为关系表达式或逻辑表达式,但也可以是任意的数值类型(整型、实型、字符型、指针型数据)例如: if (5)coutb) t=a; a=b ; b=t; 在if 语句的嵌套中,要注意if 和else的配对关系。从最内层开始,else总是与它上面最近的且未曾配对的if 配对。4条件运算符与条件表达式 例如:求x的绝对值 if (x=0) y=x; else y=-x;用条件运算符处理为:y=(x=0)? x:-x /*如果(x0)条件为“真“(非0),则y=x,否则y=-x*/其中:“? :”是条件运算符,它是C中惟一的三目运输符。由它与运算量x=0,
35、x, -x一起构成的表达式(x=0)?x:-x称为“条件表达式”。条件表达式的一般形式为: 表达式1?表达式2:表达式3其运算规则为:该表达式1为“真”(非0),则求解表达式2的值,即作为整个条件表达式的值;否则求解表达式3的值,作为整个条件表达式的值。如下图所示:条件表达式在使用时要注意以下几点:条件运算符的优先级高于赋值运算符,但低于关系运算符和算术运算符。例如: y=x0 ? x+1 : x*x/2 相当于 y=(x0 ? (x+1) : (x*x/2)条件运算符具有右结合性,并允许嵌套使用。例如: x0?1:x0?1:(xy? 1:1.5条件表达式的值为:1.0二、switch语句()
36、switch语句的一般形式为:switch (表达式) case 常量表达式1:语句组1; case 常量表达式2:语句组2; case 常量表达式n:语句组n; default:语句组n+1;switch语句的执行过程为:先计算表达式的值。然后顺次同case后的常量表达式的值比较,找到相等的常量表达式i,则执行该常量表达式冒号后的语句组i。在执行过程中,若遇到break语句,则跳出switch结构,将程序流程转向switch结构外的下一条语句执行;若没有break语句,则从该语句组为入口,依次执行其后的所有冒号后面的语句。如果switch语句后面的表达式的值找不到匹配的常量表达式的值,此时要
37、考虑是否有default可选项,若有,则执行default后面的语句组直到结束;否则什么也不执行。例3.14 用switch语句实现例3.13#include using namespace std;int main() int score,mark; coutscore; mark=-1; if (score=0 & score=100) mark=score/10; switch (mark) case 10: case 9:coutVery goodn;break; case 8:coutGoodn;break; case 7: case 6:coutPassedn;break; case 5: case 4: case 3: case 2: case 1: case 0:coutFailedn;break; default:coutEnter error!n; switch结构使用时要注意以下几点:switch后面表达式的类型,一般为整型、字符型或枚举类型;每个case后面常量表达式的值必须互不相同,即不允许对表达式的同一个值有两种或两种以上的处理方案。尽管各个case和default出现的次序不影响程序的执行结果,但是把defau