第3章 结构化程序设计12-07

更新时间:2023-11-23 09:34:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

博学谷——让IT教学更简单,让IT学习更有效

第3章 结构化程序设计

学习目标

? 理解算法的概念

? 能够使用流程图画出顺序、选择、循环三种语句的执行流程 ? 要求熟练使用if、switch语句判断各种选择情况以及嵌套使用 ? 熟练运用while、do-while、for三种循环结构的思想解决实际问题 ? 熟练应用break、continue、goto语句与循环语句的搭配使用

前面的章节一直在介绍C语言的基本语法知识,然而仅仅依靠这些语法知识还不能编写出完整的程序。在程序中,通常需要加入业务逻辑,并根据业务逻辑关系对程序的流程进行控制。本章将针对程序设计的灵魂——算法以及C语言中最基本的三种程序流程进行讲解。

3.1 算法——程序设计的灵魂

3.1.1 算法的概念

假如有一张对称的桌子和无限多大小相同的硬币,有两个人轮流往桌子上放硬币,规定硬币不可以重叠,但可以边贴边放置。最后谁放不下谁就输了。假设让你第一个放置,你如何做才能保证自己肯定赢呢?明确了“做什么”,接下来就是寻求解决办法。首先自己赢的话需要在自己没地方放硬币之前,对方就应该没有地方放硬币了,从这分析可以想到,我们的行为和对方的行为应该有一定的联系性。于是可以得到一个解决办法,首先在桌子中央,放置硬币,接下来等对方放置硬币后,只需要在他的对称位置放就可以了,只要他可以放,那么对称位置一定还有空间,直至他没地方放了,我们就赢了。

这是生活中一个运用智慧解决问题的例子,学习编程也是为了解决问题的。那么程序是什么?程序是为完成一项特定任务而用某种语言编写的一组指令序列。一个程序应当包含以下两方面的内容:

(1)对数据的描述:在程序中指定用到哪些数据以及这些数据的类型和数据的组织形式,这就是数据结构(data structure)。

(2)对数据操作的描述:即操作步骤,也就是算法(algorithm)。 著名计算机科学家沃思(Nikiklaus Wirth)提出了一个程序公式:

程序 = 数据结构 + 算法

其中算法是一个程序的灵魂,直到今天,这个公式对于过程化程序来说依然是适用的。

算法有三种种较为常用的表示方法:伪代码法、N-S结构化流程图和流程图法。在以后的学习中,本书较多地用到了流程图这种描述方法。

1

博学谷——让IT教学更简单,让IT学习更有效

3.1.2 流程图

流程图是描述问题处理步骤的一种常用图形工具,它是由一些图框和流程线组成的。使用流程图描述问题的处理步骤形象直观、便于阅读。画流程图时必须按照功能选用相应的流程图符号,常用的流程图符号如图3-1所示。

起止框输入/输出框判断框处理框

流程线连接点

图3-1 流程图符号

图3-1所示的流程图符号中,列举了四个图框、一个流程线和一个连接点,具体说明如下: ? 起止框用于表示流程的开始或结束;

? 输入/输出框用平行四边形表示,在平行四边形内可以写明输入或输出的内容;

? 判断框用菱形表示,它的作用是对条件进行判断,根据条件是否成立来决定如何执行后续

的操作;

? 处理框用矩形表示,它代表程序中的处理功能,如算术运算和赋值等;

? 流程线用实心单向箭头或直线表示,可以连接不同位置的图框,流程线的标准流向是从左

到右和从上到下,可用直线表示,非标准流向的流程线应使用箭头指示方向; ? 连接点用圆形表示,用于流程图的延续。

通过上面的讲解,读者对流程图符号有了简单的认识,接下来先来看一个简单的流程图,如图3-2所示。

2

博学谷——让IT教学更简单,让IT学习更有效

结束结束输入三个不同变量输入三个不同变量x,y,z x,y,z 的值的值YesYes判断判断x>yx>y是否成立是否成立NoNo判断判断y>zy>z是否成立是否成立判断判断x>zx>z是否成立是否成立YesYes最小数最小数是是zzNoNoYesYes最小数最小数是是yy最小数最小数是是zzNoNo最小数是x输出输出结束结束

图3-2 求三个数中的最小值

图3-2表示的是一个求三个数中的最小值的流程图,下面针对该流程图中的执行顺序进行说明,具体如下:

第1步:程序开始;

第2步:进入输入/输出框,输入三个变量值x,y,z;

第3步:进入判断框,判断x>y是否成立,如果是成立,则进入左边的判断框,继续判断y>z

是否成立;否则进入右边的判断框,判断x>z是否成立;

第4步:进入下一层判断框。如果进入的是左边的判断框,判断y>z是否成立,如果成立,则进入左边的处理框,得出最小值是z;如果不成立,则进入右边的处理框,得出最小值为y。 如果进入的是右边的判断框,则判断x>z是否成立,如果成立,则进入左边的处理框, 得出最小值是z;如果不成立,则进入右边的处理框,得出最小值是x。 第5步:进入输出框,输出结果; 第6步:进入结束框,程序运行结束。

学习画流程图可以有效的进行结构化程序设计,基本的流程结构有3种,即顺序结构、选择结构和循环结构。它们可以编写各种复杂程序。在接下来的小节中,将分别讲解这3种基本流程结构,而流程图可以更好的理解和学习这些流程结构语句。

3.2 C语言的基本语句

经过图3-2的流程分析,理清了思路,那么编程就是信手拈来,但是,再简单的程序也得一句一句的写出。如果把写程序和写小说类比,变量常量等可以看成是字和词,函数可以看成是一个段落,运算符等可以看作是字词的组合方式(规则),那么,字词组成的句子就是小说的最小独立单元,表达了一定的意思,同样,程序的最小独立单元也是“语句”,每个语句表达出完整的意义。小说中有感叹句、疑问句等。同样,程序中也有各种各样的语句。C语言的语句类型如图3-3所示。

3

博学谷——让IT教学更简单,让IT学习更有效

图3-3 C语言的语句类型

接下来针对图3-3中的几个语句作简单介绍,具体如下:

? 表达式语句:在各种表达式的后面加上一个分号,就构成了表达式语句;如a = 5;就是一

个赋值表达式语句。

? 空语句:仅有一个分号构成的语句就是空语句。

? 流程控制语句:在程序中完成特定的控制功能的语句就是流程控制语句。其分类如图3-3。 ? 块语句:用一对{}括起来的若干语句称为块语句,也叫作复合语句。

在这些语句中,最重要的是流程控制语句,它是编写程序要掌握的最基本也最重要的语句类型。 接下来的几个小节就陆续学习这几种流程控制语句。

3.3 顺序结构语句

前面章节讲解的程序都有一个共同的特点,即程序中的所有语句都是从上到下逐条执行的,这样的程序结构称为顺序结构。顺序结构是程序开发中最常见的一种结构,它可以包含多种语句,如变量的定义语句、输入输出语句、赋值语句等。顺序结构流程图如图3-4所示。

处理语句1处理语句2处理语句3

图3-4 顺序语句流程图

顺序结构语句中,语句从上至下一句一句的执行,是最简单的一种结构语句。接下来通过 打印“我爱C语言”这句话为例来讲解顺序结构语句,如例3-1所示。

例3-1

1 #include 2 void main() 3 { 4 5 6

printf(\我\\n\printf(\爱\\n\printf(\

4

博学谷——让IT教学更简单,让IT学习更有效

7 8 9 }

printf(\语\\n\printf(\言\\n\

运行结果如图3-5所示。

图3-5 运行结果

在例3-1中,使用了5个printf()语句,从上往下依次输出字符“我、爱、C、语、言”。从运行结果可以看出,程序是按照语句的先后顺序依次执行的,这就是一个顺序结构的程序。

3.4 选择结构语句

在实际生活中做什么事情都不是一帆风顺的,经常需要对一些情况做出判断,比如开车来到一个十字路口,这时需要对红绿灯进行判断,如果前面是红灯,就停车等候,如果是绿灯,就通行。同样,在C语言中也经常需要对一些条件做出判断,从而决定执行哪一段代码,这时就需要使用选择结构语句。选择结构语句又可分为if条件语句和switch条件语句,本节将对它们进行详细地讲解。

3.4.1 if条件语句

if条件语句有三种语法格式,每一种格式都有其自身的特点,我们分别来学习。 1、if语句——单分支结构

if语句是指如果满足某种条件,就进行相应的处理。例如,小明妈妈跟小明说“如果你考试得了100分,星期天就带你去游乐场玩”,这句话可以通过下面的一段伪代码来描述。

如果小明考试得了100分 妈妈星期天带小明去游乐场

在上面的伪代码中,“如果”相当于C语言中的关键字if,“小明考试得了100分”是判断条件,需要用()括起来,“妈妈星期天带小明去游乐场”是执行语句,需要放在{}中。修改后的伪代码如下:

if (小明考试得了100分) {

妈妈星期天带小明去游乐场 }

上面的例子描述了if语句的用法,在C语言中,if语句的具体语法格式如下:

if (判断条件) { }

代码块

上述语法格式中,判断条件的值只能是0或非0,若判断条件的值为0,按“假”处理,若判断

5

博学谷——让IT教学更简单,让IT学习更有效 值为0时,整个循环过程才会结束。

while循环的执行流程如图3-18所示。

开始循环条件真执行语句假

图3-18 while循环的流程图

接下来通过while语句来实现1~4之间自然数的打印,如例3-8所示。 例3-8

1 #include 2 void main() 3 { 4 5 6 7 8 9 10 }

int x = 1; { }

printf(\条件成立,打印x的值 x++; // x进行自增

//定义变量x,初始值为1

结束while (x <= 4) // 循环条件

运行结果如图3-19所示。

图3-19 运行结果

例3-8中,x的初始值为1,在满足循环条件x <= 4的情况下,循环体会重复执行,打印x的值并让x进行自增。因此,打印结果中x的值分别为1、2、3、4。需要注意的是,例3-8中的第8行代码用于在每次循环时改变变量x的值,直到循环条件不成立,如果没有这行代码,整个循环会进入无限循环的状态,永远不会结束。

?脚下留心:语句后的分号”;”

在编程时会经常性的在结尾加上分号,在使用while循环语句时,一定要记得勿在()后面加分号,这样就造成了循环条件与循环体的分离。如下面的代码:

while(1); {

printf(“无限循环”);

16

博学谷——让IT教学更简单,让IT学习更有效

}

像这样的代码在while()循环条件后加了分号,这就会造成无法循环的错误,而且这种小错误在排查时很难发现,读者在编写程序时要留心。

3.5.2 do-while循环语句

do…while循环语句和while循环语句功能类似,区别是while语句需要先判断循环条件,然后根据判断结果来决定是否执行大括号中的代码,而do…while循环语句先要执行一次大括号内的代码再判断循环条件,其具体语法格式如下:

do {

执行语句 ………

} while(循环条件);

在上面的语法格式中,关键字do后面{}中的执行语句是循环体。do…while循环语句将循环条件放在了循环体的后面。这也就意味着,循环体会无条件执行一次,然后再根据循环条件来决定是否继续执行。

do…while循环的执行流程如图3-20所示。

开始执行语句真循环条件假结束

图3-20 do…while循环的执行流程

接下来使用do…while循环语句将例3-8进行改写,如例3-9所示。 例3-9

1 #include 2 void main() 3 { 4 5 6 7 8 9 10 }

int x = 1; do {

printf(\条件成立,打印x的值 x++; // x进行自增

//定义变量x,初始值为1

} while (x <= 4); // 循环条件

运行结果如图3-21所示。

17

博学谷——让IT教学更简单,让IT学习更有效

图3-21 运行结果

例3-9和例3-8的运行结果一致,这说明do …while循环和while循环能实现同样的功能。然而在程序运行过程中,这两种语句还是有差别的。如果循环条件在循环语句开始时就不成立,那么while循环的循环体一次都不会执行,而do…while循环的循环体还是会执行一次。若将例中的循环条件x<=4改为x < 1,例3-9会打印x=1,而例3-8什么也不会打印。

3.5.3 for循环语句

在前面的小节中分别讲解了while循环和do…while循环。在程序开发中,还经常会使用另一种循环语句,即for循环,它通常用于循环次数已知的情况,其具体语法格式如下:

for(初始化表达式; 循环条件; 操作表达式) { }

执行语句 ………

在上面的语法格式中,for关键字后面()中包括了初始化表达式、循环条件和操作表达式三部分内容,它们之间用“;”分隔,{}中的执行语句为循环体。

for循环语句的流程图如图3-22所示。

开始初始化表达式循环条件假真执行语句操作表达式结束

图3-22 for循环语句流程图

因为for循环语句中表达式较多,接下来就以图3-22为主对for循环的执行逻辑进行详细讲解。 第一步,初始化表达式确定初始条件。

第二步,进入到循环条件,判断初始化的条件是否成立,如果成立,则执行{}内的语句;如果

不成立就结束。

第三步,执行完{}内的语句后,执行操作表达式,将条件改变。

第四步,改变条件后,再去执行循环条件,判断条件改变后是否成立,重复第二步。就这样依

次循环,直到条件不成立。

18

博学谷——让IT教学更简单,让IT学习更有效

例如,对自然数1~4求和,实现方式如例3-10所示。 例3-10

1 #include 2 void main() 3 { 4 5 6 7 8 9 10 }

int sum = 0; //定义变量sum,用于记住累加的和 for (int i = 1; i <= 4; i++) //i的值会在1~4之间变化 { }

printf(\打印累加的和

sum += i; //实现sum与i的累加

运行结果如图3-23所示。

图3-23 运行结果

例3-10中,变量i的初始值为1,在判断条件i<=4为真的情况下,会执行循环体sum+=i,执行完毕后,会执行操作表达式i++,i的值变为2,然后继续进行条件判断,开始下一次循环,直到i=5时,条件i<=4为假,结束循环,执行for循环后面的代码,打印“sum=10”。

为了让读者能熟悉整个for循环的执行过程,现将例3-10运行期间每次循环中变量sum和i的值通过表3-1列举出来。

表3-1 sum和i循环中的值

循环次数 第一次 第二次 第三次 第四次 sum 1 3 6 10 i 1 2 3 4 3.5.4 循环的嵌套

有时为了解决一个较为复杂的问题,需要在一个循环中再定义一个循环,这样的方式被称作循环嵌套。在C语言中,while、do…while、for循环语句都可以进行嵌套,并且它们之间也可以互相嵌套。 常用的几种嵌套语句如表3-2所示。

表3-2 常用的几种循环嵌套 常用的循环嵌套形式 while() { while() {….} } while() { do { do{…} while(); }while(); for( ; ;) { … for( ; ;) {… for( ; ;) {…} } do {… 19

博学谷——让IT教学更简单,让IT学习更有效

do{…} while(); } while(){…} … } for( ; ;) {…} … } 其中for循环中嵌套是最常见的循环嵌套,其语法格式如下所示:

for(初始化表达式; 循环条件; 操作表达式) { }

……

for(初始化表达式; 循环条件; 操作表达式) { } ……

执行语句; ……

接下来使用循环嵌套来打印出九九乘法表,如例3-11所示。 例3-11

1 #include 2 void main() 3 { 4 5 6 7 8 9 10 11 12 13 }

int i, j;

for (i = 1; i <= 9; i++) { }

for (j = 1; j <= i; j++) { }

printf(\

printf(\后面有一个空格,间隔开每一列的距离

运行结果如图3-24所示。

图3-24 运行结果

在例3-11中定义了两层for循环,分别为外层循环和内层循环,外层循环用于控制打印的行数,内层循环用控制每一行有几列,每一行的列数逐行增加,最后输出一个直角三角形的九九乘法表。该嵌套循环的流程图如图3-25所示。

20

博学谷——让IT教学更简单,让IT学习更有效

开始i <= 9假假j <= i真真printf(“i*j=i*j”);

图3-25 九九乘法表流程图

由于嵌套循环程序比较复杂,下面分步骤进行详细地讲解,具体如下: 第一步,在第4行代码中定义了两个循环变量i和j,其中i为外层循环变量,j为内层循环变量。 第二步,在第5行代码中将i初始化为1,条件i <= 9为真,即一共打印9行。程序将首次进入

外层循环的循环体。

第三步,在第7行代码中将j初始化为1,由于此时i的值为1,条件j <= i为真,程序将首次

进入内层循环的循环体,打印第一行的数值相乘结果:1*1 = 1。

第四步,执行第7行代码中内层循环的操作表达式j++,将j的值自增为2。

第五步,执行第7行代码中的判断条件j<=i,判断结果为假,内层循环结束。执行后面的代码,

打印换行符。

第六步,执行第5行代码中外层循环的操作表达式i++,将i的值自增为2。

第七步,执行第5行代码中的判断条件i<=9,判断结果为真,程序将进入外层循环的循环体,

继续执行内层循环。

第八步,由于i的值为2,内层循环会执行两次,即在第2行打印两列相乘结果:2*1=2 2*2 =4。

在内层循环结束时会打印换行符。

第九步,以此类推,在第3行会打印3列相乘结果,逐行递增,直到i的值为10时,外层循环

的判断条件i <= 9结果为假,外层循环结束,整个程序也就结束了。

除了用for循环来实现乘法表,读者也可以尝试用while和do…while()循环来实现。这里就不再 赘述。

结束3.5.5 跳转语句(break、continue、goto)

跳转语句用于实现循环执行过程中程序流程的跳转,在C语言中,跳转语句有break语句、goto语句和continue语句。接下来分别进行详细地讲解。

1、break语句

在switch条件语句和循环语句中都可以使用break语句。当它出现在switch条件语句中时,作用是终止某个case并跳出switch结构。当它出现在循环语句中,作用是跳出当前循环语句,执行后面的代码。接下来通过一个具体的案例来演示break语句如何跳出当前循环,如例3-12所示。

例3-12

1 #include 2 void main() 3 { 4

int x = 1; //定义变量x,初始值为1

21

博学谷——让IT教学更简单,让IT学习更有效

5 6 7 8 9 10 11 12 13 14 }

while (x <= 4) //循环条件 { }

printf(\条件成立,打印x的值 if (x == 3) { }

x++; //x进行自增

break;

运行结果如图3-26所示。

图3-26 运行结果

例3-12中,通过while循环打印x的值,当x的值为3时使用break语句跳出循环。因此打印结果中并没有出现“x=4”。需要注意的是,break语句不能用于循环语句和switch语句之外的任何其他语句。

2、continue语句

在循环语句中,如果希望立即终止本次循环,并执行下一次循环,此时就需要使用continue语句。求1~100之内的奇数之和就可以使用continue语句来实现,如例3-13所示。

例3-13

1 #include 2 void main() 3 { 4 5 6 7 8 9 10 11 12 13 14 }

int sum = 0; //定义变量sum,用于记住和 for (int i = 1; i <= 100; i++) { }

printf(\

if (i % 2 == 0) //如果i是一个偶数,执行if语句中的代码 { }

sum += i; //实现sum和i的累加

continue; //结束本次循环

运行结果如图3-27所示。

图3-27 运行结果

22

博学谷——让IT教学更简单,让IT学习更有效

例3-13使用for循环让变量i的值在1~100之间循环,在循环过程中,当i的值为偶数时,将执行continue语句结束本次循环,进入下一次循环。当i的值为奇数时,sum和i进行累加,最终得到1~100之间所有奇数的和,打印“sum = 2500”。 注意:break与continue的区别

? break终止当前循环,执行循环体外的第一条语句;而continue是终止本次循环,继续执行

下一次循环。

? break语句可以用于switch语句,而continue不可以。 3、goto语句

当break语句出现在嵌套循环中的内层循环时,它只能跳出内层循环,如果想要跳出外层循环则需要对外层循环添加标记,然后使用goto语句。通过一个案例来演示如何使用goto语句,如例3-14所示。

例3-14

1 #include 2 #include 3 int main() 4 { 5 6 7 8 9 10 11 12 13 14 15 16 17

int i, j; //定义两个循环变量 for (i = 1; i <= 9; i++) //外层循环 { }

for (j = 1; j <= i; j++) //内层循环 { }

printf(\换行

if (i > 4) //判断i的值是否大于4 { }

printf(\输出*

goto end; //跳至标识为end的语句

18 end: system(\让运行结果界面暂停,system()包含在stdlib.h头文件中 19 return 0; 20 }

运行结果如图3-28所示。

图3-28 运行结果

例3-14中,在system()语句前面增加了标记“end”。当i>4时,使用“goto end;”语句跳出外层循环。因此程序只打印了4行“*”。

需要注意的是,结构化程序设计方法主张限制使用goto语句,goto语句可以跳转到指定的任意语句,滥用该语句将使程序流程无规律、可读性差。

23

博学谷——让IT教学更简单,让IT学习更有效

3.6 进阶案例(一)——打印水仙花数

学完了C语言程序设计的流程,接下来通过一个打印水仙花数的案例来加深对C语言流程控制程序的理解。所谓的水仙花数是指一个n位数(n ≥ 3),它的每个位上的数字n次幂之和等于本身。例如,3位数153是水仙花,各位数字的立方和13+53+33=153。

例3-15

1 #include 2 void main() 3 {

4 int num; 5 6 7 8 9 10 11 12 13 14 15 }

int a, b, c;

for (num = 100; num < 1000; num++) { }

a = num % 10; //num的个位数字 b = num / 10 % 10; //num的十位数字 c = num / 100; //num的百位数字

if (num == (a*a*a + b*b*b + c*c*c))

printf(\

运行结果如图3-29所示。

图3-29 运行结果

例3-15中,水仙花数是一个三位数,所以要遍历100-1000之间的数,要求这个三位数的每个数字的立方和,则先要求出其每个位上的数字,第7、8、9行代码分别求出了其个、十、百位上的数字,第11行代码判断三个数字的立方和是否与原来的数相等,相等则打印,不相等则进行下一次循环。

3.7 进阶案例(二)——查找100以内的素数

打印完水仙花后,接下来紧追一步打印出1-100之间的所有素数。所谓素数,是只能被1和它本身整除的数。代码示例如例3-16所示。

例3-16

1 void main() 2 { 3 4

int num = 2; //num从2开始 int i, j = 1;

24

博学谷——让IT教学更简单,让IT学习更有效

5 6 7 8 9 10 11 12 13 14 15 16 17 19 20 21 22 24

}

}

if (count % 5 == 0) //每5个换一行

printf(\

if (num == i) //如果跳出内层循环后,num == i成立,即2-num之间的数都不能整除num {

printf(\则num就是一个素数,就打印出来

while (num < 100) //遍历1-100之间的数 {

for (i = 2; i < num; i++) //用2-num之间的所有数去除num { }

if (num % i == 0) //如果模等于0,也就是能被整除 { }

break; //就跳出这层循环,执行num++

18 count++; //记录素数的个数

23 num++; //num++不要忘记

25 printf(\之间的素数一共有%d个\\n\ 26 27 }

system(\让运行结果界面暂停

运行结果如图3-30所示。

图3-30 运行结果

如图3-41所示,1-100之间一共有25个素数。素数只能被1和它本身整除,则在求素数时,要用num与2-num之间的所有数相除,如果没有能整除num的数,则num就是一个素数。

例3-15与例3-16中结合了循环、选择语句之间的嵌套。关于这几种结构语句的使用,读者要多加练习,熟练掌握。

3.8 本章小结

本章首先讲解了程序的运行流程图,然后讲解了C语言中最基本的三种流程控制语句,包括顺序结构语句、选择结构语句和循环语句。通过本章的学习,读者应该能够熟练的运用if判断语句、switch判断语句、while循环语句、do-while循环语句以及for循环语句。掌握本章的内容就能够编写逻辑比较复杂的C语言程序并且有助于后面章节的学习。

25

本文来源:https://www.bwwdw.com/article/p6yt.html

Top