1.07k likes | 1.26k Views
第二章 基本控制结构程序设计. 结构化程序设计的特点是任何程序都可由 三种基本结构 及其组合来描述。 本章将介绍 C++ 分支结构和循环结构的设计方法。还将介绍一些 常用算法 。. 第二章 基本控制结构程序设计. 2.1 算法的概念与表示方法. 2.2 分支结构程序设计. 2.3 循环结构 程序设计. 2.4 转向语句. 2.5 结构化程序设计思想(选读). 2.6 常用算法的应用实例. 2.7 枚举类型. 2.8 输入输出文件简介. 2.1 算法的概念与表示方法. 2.1.1 算 法 的 概 念.
E N D
第二章 基本控制结构程序设计 结构化程序设计的特点是任何程序都可由三种基本结构及其组合来描述。 本章将介绍C++分支结构和循环结构的设计方法。还将介绍一些常用算法。
第二章 基本控制结构程序设计 2.1 算法的概念与表示方法 2.2 分支结构程序设计 2.3 循环结构程序设计 2.4 转向语句 2.5 结构化程序设计思想(选读) 2.6 常用算法的应用实例 2.7 枚举类型 2.8 输入输出文件简介
2.1 算法的概念与表示方法 2.1.1 算 法 的 概 念 2.1.2 算 法 的 表 示 2.1.3 算 法描述的三种基本结构
2.1.1 算 法 的 概 念 • 算法: • 算法是解决问题的步骤。 • 计算机算法的特征: • 可执行性 • 确定性 • 有穷性 • 可输入输出信息 • 算法是程序设计学习的重点。
2.1.2算法的表示 流程图: 流程图是图形化的表示方法,比较直观,基本组成元件包括矩形框、菱形框、箭头线等。其中矩形框表示要执行的指令,在框内标注指令内容;菱形框表示要判断其中表达式的值是真还是假;箭头线则标示指令的流程方向。 伪码: 伪码是介于自然语言和程序设计语言之间的一种类自然语言的表示方法,书写形式自由,容易转换为程序。
2.1.3算法描述的三种基本结构 算法的基本结构: 对算法的理论研究和实践表明,任何算法的描述都可以分解为三种基本结构或它们的组合,这三种基本结构是顺序结构、分支结构和循环结构。 1 顺 序 结 构 2 分 支 结 构 3循 环 结 构
块1 块2 块3 num1 15 寄存器 35 + num2 20 sum 35 2.1.3算法描述的三种基本结构 (1)顺序结构 演示算法执行过程 【例2.1】 求两数之和。 显示结果:35 num115; num220; sumnum1+num2; 输出sum; 流程图
条件 7 z x y CPU 比较 12 比较 10 12 max 2.1.3算法描述的三种基本结构 演示算法执行过程 (2) 分支结构 【例2.2】输入三个数,输出其中的最大数。 真 假 x7; y12; 块1 块2 z10; if(x>y) maxx; else max y; 显示结果:12 流程图 if (z>max) maxz; 输出max;
条件 (3) 循环结构 count 4 真 假 sum 0 x 12 块 流程图 2.1.3算法描述的三种基本结构 演示算法执行过程 【例2.3】求4个整数的和。 0 3 2 1 count4; //整数个数 sum0; //累加和的初值 while (count>0) { x输入一个整数; sumsum+x; countcount-1; } 输出sum; 12 26 42 60 14 16 18 显示结果:60
2.2 分支结构程序设计 对程序的运行流程进行控制,主要通过执行专门用来控制流程的语句来实现。 分支语句是基本流程控制语句之一。C++提供三种分支语句。 2.2.1 if语句 2.2.2 if语句的嵌套 2.2.3 条件运算符“?:” 2.2.4 swich语句
2.2.1 if语句 if语句基本格式: 1、if (表达式) 语句1; 2、if (表达式) 语句1; else 语句2; 【例2.4】 输入一个年份,判断是否闰年。 【例2.5】 从键盘上输入三个整数,输出其中的最大数。
2.2.2 if 语句的嵌套 嵌套if语句: if 语句中,如果内嵌语句又是if语句,就构成了嵌套if语句。if 语句可实现二选一分支,而嵌套if语句则可以实现多选一的多路分支情况。 嵌套有两种形式,嵌套在else分支中: if (表达式1) 语句1; else if (表达式2) 语句2; else if … else语句n; 嵌套在if分支中: if (<表达式1>) if (<表达式2>) <语句1>; else<语句2>; 【例2.6】用嵌套if语句完成【例2.5】的任务。
2.2.2 if 语句的嵌套 else和if的配对关系: C++规定了if和else的“就近配对”原则,即相距最近且还没有配对的一对if和else首先配对。按上述规定,第二种嵌套形式中的else应与第二个if配对。如果根据程序的逻辑需要改变配对关系,则要将属于同一层的语句放在一对“{}”中。如第二种嵌套形式中,要让else和第一个if配对,语句必须写成: if (表达式1) { if (表达式2) 语句1 ; } else 语句2 ; 第二种嵌套形式较容易产生逻辑错误,而第一种形式配对关系则非常明确,因此从程序可读性角度出发,建议尽量使用第一种嵌套形式。
配对关系实例: //语句1: if(n%3==0) if(n%5==0) cout<<n<<″是15的倍数″<<endl; else cout<< n<<″是3的倍数但不是5的倍数″ <<endl; //语句2: if(n%3==0){ if(n%5==0) cout<<n<<″是15的倍数″<<endl; } else cout<< n <<″不是3的倍数″ 两个语句的差别只在于一个“{}”,但表达的逻辑关系却完全不同。 【例2.7】 某商场购物优惠活动 【例2.8】 求一元二次方程的根。
真 表达式1 假 表达式2 表达式3 图2.4 条件运算符的语义 2.2.3 条件运算符“?:” 三元运算符: 三元运算符条件运算符“?:”可以用来简化if语句表达。其构成的表达式格式为: 表达式1 ? 表达式2 : 表达式3 例如:int a=6,b=7, min=a<b?a:b; //min=6 min=a<b?++a:++b; //min=7 a=7 b=7 min=a<b?a++:b++; //min=6 a=7 b=7 ok
2.2.4 switch语句 开关语句(switch语句) 用来实现多选一: switch (表达式) { case 常量表达式1: 《语句序列1》《break;》 …… case常量表达式n:《语句序列n》《break;》 《default:语句序列》 } 开关语句注意要点: (1)各个case(包括default)分支出现的次序可以任意,通常将default放在最后。 (2)break语句可选,如果没有break语句,每一个case分支都只作为开关语句的执行入口,执行完该分支后,还将接着执行其后的所有分支。因此,为保证逻辑的正确实现,通常每个case 分支都与break语句联用。
2.2.4 switch语句 (3)每个常量表达式的取值必须各不相同,否则将引起歧义。 (4)允许多个常量表达式对应同一个语句序列。 例如: char score; cin>>score; switch (score) { case ′A′: case ′a′: cout<<″excellent″; break; case ′B′: case ′b′: cout<<″good″; break; default: cout<<″fair″; }
2.2.4 switch语句 (5)从形式上看,switch语句的可读性比嵌套if语句好,但不是所有多选一的问题都可由开关语句完成,这是因为开关语句中限定了条件表达式的取值类型。 【例2.9】运输货物实行分段计费。采用不带break的开关语句实例 【例2.10】设计一个计算器程序, 实现加、减、乘、除运算。 ok
2.3 循环结构程序设计 循环控制语句是基本流程控制语句之一。C++提供三种循环语句: 2.3.1 while语句 2.3.2 do-while 语句 2.3.3 for语句 2.3.4 循环的嵌套
2.3.1 while 语句 求表达式的值 while语句也称为当循环。 语句格式为: while (表达式) 循环体语句; 表达式值为真? 否 是 执行循环体语句 【例2.11】 求1+2+3 +4+…+100的值。 图2.5 while语句的执行流程图
2.3.1 while 语句 注意: 在有循环语句的程序中,通常循环开始前对循环条件进行初始化;而在循环体语句中要包含修改循环条件的语句,否则循环将不能终止而陷入死循环。 C++表达方式灵活,上例中的循环语句还可以写成: while (i<=n) sum+=i++; 或者 while (sum+=i++, i<=n) ;//循环体为空语句 修改程序后在VC++平台上运行,看是否正确
2.3.2 do-while 语句 执行循环体语句 do-while语句称为直到循环,格式为: do 循环体语句 while( 表达式 ) 求表达式的值 表达式的 值为真? 是 否 图2.6 do-while语句的执行流程图
2.3.2 do-while 语句 do/while语句和while语句的区别: do/while语句至少执行一次循环体后再判断循环条件是否满足; while语句先判断条件是否满足,然后才执行循环体。可能一次也不执行。 多数情况下可以互相替代。 【例2.12】用迭代法求a的平方根近似值。 【例2.13】输入一段文本,统计文本的行数、单词数及字符数。
表达式2值为真? 否 是 求表达式3的值 图2.7 for语句的执行流程图 求表达式1的值 求表达式2的值 执行循环体语句 2.3.3 for 语句 for循环语句的格式为: for ( 表达式1; 表达式2; 表达式3 ) 循环体语句 ok
for语句、while语句、do/while语句比较: int i=1,sum=0; //循环初始条件 do { sum+=i; i++;//修改循环条件 } while(i<=4); int i=1,sum=0; //循环初始条件 while(i<=4) { sum+=i; i++;//修改循环条件 } int i,sum=0; for( i=1; i<=4; i++ ) { sum+=i; } /*习惯上:表达式1:循环初始条件;表达式2:循环终止条件;表达式3:修改循环条件*/ ok
for 语句的应用 • for语句的几点说明: 1、是先判断型的,同while语句; 2、使用更为灵活: 三个表达式可以是任意表达式,因此它们就可以实现循环初始化、计算、修改循环条件等任务,而不一定非在循环体中进行;
for 语句的应用 【例2.14】 设计程序输出Fibonacii 数列的前20项 【例2.14】运行结果: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 【例2.15】 输入一个不超过5位的整数,将其反向后输出。
2.3.4循环的嵌套 嵌套循环: 当循环语句中的循环体中又有循环语句时,就构成了嵌套循环。 嵌套层次一般不超过3层,以保证可读性。 【例2.16】 打印九九表。 【例2.17】打印如下图形。 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2.4转向语句 break语句 continue语句 goto 语句 return语句
2.4转向语句 Break语句: break语句只能用在switch语句和循环语句中,用来跳出switch语句或提前终止循环,转去执行switch语句或循环语句之后的语句。 在for循环中可以用break结束循环: for(; ;) { … if(<表达式>) break; … } 【例2.18】 给定正整数m,判定其是否为素数。
2.4转向语句 continue语句: continue语句只能用在循环语句中,用来终止本次循环。当程序执行到continue语句时,将跳过其后尚未执行的循环体语句,开始下一次循环。下一次循环是否执行仍然取决于循环条件的判断。 continue语句与break语句的区别在于,continue语句结束的只是本次循环,而break结束的是整个循环。
例:输出1~100内3的倍数。 分析:设置整型变量I从1变化到100,依次测试I是否3的倍数,算法属于穷举法。 for (I=1;I<=100;I++) { if ( I%3!=0) continue; //I不是3的倍数,不输出,继续下一个I; 输出I的值;//I是3的倍数才输出 }
2.4转向语句 goto语句: goto语句和标号语句一起使用,所谓标号语句是用标识符标识的语句,它控制程序从goto语句所在的地方转移到标号语句处。goto语句会导致程序结构混乱,可读性降低,而且它所完成的功能完全可以用算法的三种基本结构实现,因此一般不提倡使用goto语句。但在某些特定场合下goto语句可能会显出价值,比如在多层循环嵌套中,要从深层地方跳出所有循环,如果用break语句,不仅要使用多次,而且可读性较差,这时goto语句可以发挥作用。
2.4转向语句 return语句: return语句用于结束函数的执行,返回调用者,如果是主函数,则返回至操作系统。 利用一个return语句可以将一个数据返回给调用者。通常,当函数的返回类型为void时, return语句可以省略,如果使用也仅作为函数或程序结束的标志。
2.5 结构化程序设计思想(选读) 结构化程序设计方法: 传统的程序设计方法可以归结为“程序=算法+数据结构”,将程序定义为处理数据的一系列过程。这种设计方法的着眼点是面向过程的,特点是数据与程序分离,即数据与数据处理分离。 结构化程序设计的基本思想是采用自顶向下、逐步细化的设计方法和单入单出的控制结构。
1.读入数据 正整数个数为0;负整数个数0 取第一个整数 2.统计正数、负数的个数; 2.1 如数大于0,正整数个数加1 2.2 如数小于0,负整数个数加1 2.3: 取下一个整数 重复 至统 计完 3. 输出结果 2.5 结构化程序设计思想(选读) 举一个简单的例子,要求读入一组整数,统计其中正整数和负整数的个数。 该任务的模块结构及细化过程如下:
2.5 结构化程序设计思想(选读) 结构化程序设计缺陷: (1)难以适应大型软件的设计。由于数据与数据处理相对独立,在大型多文件软件系统中,随着数据量的增大,程序越来越变得难以理解,多个文件之间的数据沟通也变得困难,还容易产生意想不到的结果,即所谓副作用。 (2)程序可重用性差。处理方法的改变或数据类型的改变都将导致重新设计,这种额外开销与可重用性相左,称为重复投入
2.6常用算法的应用实例 【例2.19】 用筛选法求100之内的所有素数 【例2.20】世界数学史上著名的“百鸡问题” 【例2.21】用欧基里德算法(也称辗转法) 求两个整数的最大公约数 【例2.22】输入一个小于1的数x,求sinx的近似值 【例2.23】输入一个8位二进制数,将其转换为十进制数输出。
2.7 枚举类型 • 枚举类型(enumerate)是c++中的一种派生数据类型,它是用户定义的若干枚举常量的集合。 • 枚举类型的变量,只能取枚举常量表中所列的值。 • 定义枚举类型的主要目的是增加程序的可读性。 2.7.1 枚举类型的定义 2.7.2 枚举变量的使用
2.7.1 枚举类型的定义 枚举类型定义: enum <类型名> {<枚举常量表>}; 关键字enum指明其后的标识符是一个类型的名字,枚举常量表中列出该类型的所有取值,各枚举常量之间以“,”间隔。 例: enmu color_set1 {RED, BLUE, WHITE, BLACK}; enum week {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; 枚举常量(或称枚举成员)是以标识符形式表示的整型量,非法定义实例: enum letter_set {‘a’, ‘d’, ‘F’, ’s’, ‘T’}; //枚举常量只能是标识符 enum year_set{2000,2001,2002,2003,2004,2005}; //改为y2000等则正确
2.7.1 枚举类型的定义 枚举常量: 枚举常量代表该枚举类型的变量可能取的值,编译系统为每个枚举常量指定一个整数值,缺省状态下,这个整数就是所列举元素的序号,序号从0开始。如上例中RED、 BLUE、 WHITE、 BLACK的值分别为0、1、2、3。 用户也可以在类型定义时为部分或全部枚举常量指定整数值,在第一个指定值之前的枚举常量仍按缺省方式取值,而指定值之后的枚举常量按依次加1的原则取值。各枚举常量的值可以重复,但各枚举常量标识符必须不同。 例: enum fruit_set {apple, orange, banana=1, peach, grape} enum week {Sun=7, Mon=1, Tue, Wed, Thu, Fri, Sat}; 枚举常量apple、orange、banana、peach、grape的值分别为0、1、1、2、3。枚举常量Sun, Mon, Tue, Wed, Thu, Fri, Sat的值分别为7、1、2、3、4、5、6。
2.7.2 枚举类型的变量的使用 枚举类型应用要点: 1、定义枚举类型之后,就可以定义枚举类型的变量;亦可类型与变量同时定义(甚至类型名可省): color_set1 color1, color2; enum {Sun, Mon, Tue, Wed, Thu, Fri, Sat} weekday1, weekday2; 2、枚举变量的取值范围就是整型数的一个子集。枚举变量占用内存的大小与整型数相同。 3、枚举变量允许的操作只有赋值和关系运算;如: color3=color4=BLUE; if (color3==color4) cout<<”相等”; cout<< color3<WHITE; //输出“真”,即1
2.7.2 枚举类型的变量的使用 4、枚举变量不能直接输入,可以直接输出,但输出的是变量的整数值。例如: cin>>color1 //非法 cout<<color3 //合法,输出的是2 从程序的合法性和可读性出发,枚举变量的输入输出一般都采用switch语句将其转换为字符或字符串。同时,枚举类型数据的其他处理也往往应用switch语句。 *【例2.24】口袋中有红、黄、蓝、白、黑五种颜色的球若干个,每次从口袋中取三个不同颜色的球,统计并输出所有的取法。
2.8 输入输出文件简介 使用文件的步骤如下: (1) 说明一个文件流对象(内部文件)。文件流类型ifstream支持从输入文件提取数据的操作。而文件流类型ofstream完成数据写入输出文件的各种操作。 ifstream ifile; //定义输入文件,ifile为文件名,可用任意标识符 ofstream ofile; //定义输出文件,ofile为文件名,可用任意标识符 (2) 打开文件。 ifile.open(”d:\\my_in_file.txt”); ofile.open(”d:\\my_out_file.txt”); 引号中的”d:\\my_in_file.txt” 和”d:\\my_out_file.txt”为磁盘文件路径名,这样在文件流对象和磁盘文件名之间建立了联系。
(3) 对文件进行读写操作。最常见的文件读写是顺序的,所谓“顺序”指的是从文件头开始进行读写。顺序读写可用C++的提取运算符(>>)和插入运算符(<<)进行。也可以用读字符的get()和读字符串的getling()等函数。读写是在文件缓冲区中进行。 (4) 关闭文件。当打开一个文件进行读写后,应该显式地关闭该文件。与打开文件相对应: ifile.close(); ofile.close(); 关闭文件时,系统把与该文件相关联的文件缓冲区中的数据写到磁盘文件中,保证文件的完整;同时把磁盘文件名与文件流对象之间的关联断开,可防止误操作修改了磁盘文件。 【例2.25】将百鸡问题计算结果存入文件。 【例2.26】读出存放百鸡问题计算结果的文件。
第二章 基本控制结构程序设计 结束 欢迎再来!
if语句【例2.4】 【例2.4】 输入一个年份,判断是否闰年。 算法分析:假定年份为year, 闰年的条件是 : year%4==0&&year%100!=0||year%400==0。 int main( ){ int year; cout<<"输入年份:"<<endl; cin>>year; if (year%4==0&&year%100!=0 ||year%400==0) cout<<year<<“年是闰年"<<endl; else cout<< year<<“年不是闰年"<<endl; return 0; } ok
输入三个数a,b,c 是 a>=b? 否 图2.2 例2.5流程图 max=a max=b 否 c>max? 是 max=c 输出max if语句【例2.5】 【例2.5】 从键盘上输入三个整数,输出其中的最大数。 分析:读入三个数,先求出两个数中较大者,再将该大数与第三个数比较,求出最大数。 int main(){ int a, b, c, max; cout<<"输入三个正数:"; cin>>a>>b>>c; cout<<"a="<<a<<'\t'<<"b="<<b<<'\t‘ <<"c="<<c<<endl; if(a>b) max=a; else max=b; if(c>max) cout<< “最大数为:”<<c<<endl; else cout<< “最大数为:”<<max<<endl; return 0; } ok
if语句【例2.6】 【例2.6】用嵌套if语句完成【例2.5】的任务。 //方法1:采用if中嵌套形式 int main(){ int a, b, c, max; cout<<"输入三个正数:"; cin>>a>>b>>c; cout<<"a="<<a<<'\t'<<"b="<<b <<'\t'<<"c="<<c<<endl; if(a>b) if(a>c) max=a; //a>b且a>c else max=c; //a>b且a<c elseif(b>c) max=b; //a<=b且b>c else max=c; //a<=b且b<c cout<<"最大数max="<<max; return 0; } ok
if语句【例2.6】 //方法2:采用else中嵌套形式 int main(){ int a,b,c,max; cout<<"输入三个正数:"; cin>>a>>b>>c; cout<<"a="<<a<<'\t'<<"b="<<b <<'\t'<<"c="<<c<<endl; if(a>b&&a>c) max=a; elseif(b>a&&b>c) max=b; else max=c; cout<<"最大数为:max="<<max; return 0; } ok