第三部分:流程控制
一、选择结构
1.if…else
选择结构
在高中数学中,我们学过这样的程序结构:
图:选择结构流程图
这个流程图的程序运行过程是:当表达式为真,则沿着左侧的箭头向下执行,否则沿着右侧的箭头向下执行。例如:
#include<stdio.h>
int main()
{
int a;
printf("请输入你的性别,1为男,2为女:\n");
scanf("%d",&a);
if(a = 1)
{
printf("你是男生\n");
}
if(a = 2)
{
printf("你是女生\n");
}
else
{
printf("你确定没有输入错?\n");
}
return 0;
}
上述程序运行时,先提示用户输入数字,然后按照要求输出男或女。这是一个选择结构的典例。选择结构的一般形式如下:
if(表达式 1)
语句 1;
if(表达式 2)
语句 2;
if(表达式 3)
语句 3;
…
if(表达式 n)
语句 n;
else
语句 n + 1;
需要注意的是,表达式 1 ~ 表达式 n 都是逻辑表达式,即能判断正误的表达式。当表达式的值为1
(TRUE
)则执行此 if
下的语句,否则继续执行下一个 if
的判断。当语句 1 ~ 语句 n 为多条语句时,则要用花括号将其括在一起变成语句体。
2.switch
多分支选择结构
switch-case-default
结构可以实现多分支选择。例如要编写一个程序,根据学生的成绩等级来输出成绩区间:
int main()
{
char grade;
printf("输入你的成绩等级:\n");
scanf("%c", &grade);
switch(grade)
{
case 'A' : printf("80~100\n"); break;
case 'B' : printf("60~80\n"); break;
case 'C' : printf("40~60\n"); break;
case 'D' : printf("0~40\n"); break;
default : printf("输入错误");
}
return 0;
}
当程序遇到 switch
关键字时,会将括号中的变量与 switch
语句体中的每个 case
匹配,执行对应的语句。每个 case
语句后都有一个 break
,它的作用是跳出这个 case
转到 switch
语句体结束。如果没有 break
的话,会在匹配到的 case
依次向下执行。
3.选择结构的嵌套
if
和 switch
两种选择结构可以互相嵌套,形成嵌套结构。例如:
#include<stdio.h>
int main()
{
int x, y;
scanf("%d", &x);
if(x < 0)
y = -1
else
if(x == 0)
y = 0;
else
y = 1;
printf("x = %d, y = %d\n", x, y);
return 0;
}
如上程序的流程如下图:
图:
if
的选择结构嵌套示意图
这个程序体现了 if
语句的嵌套结构。当我们在设计程序算法,遇到分支的情况时,需要合理设计选择结构的嵌套。这将会在日后的编程中渐渐体会到。
4.改变选择结构的状态 break
在 switch
选择结构中,如果在每一个分支后面没有特定的说明,默认会在此分支执行结束之后跳转到下一个分支。例如在第三部分、一、2 的 switch
例程中,如果输入 A
,且每一个 case
语句结束的位置都没有 break
的话,输出结果是:
80~100
60~80
40~60
0~40
输入错误
进行算法设计时,要根据具体需要来使用 break
来改变程序运行状态,来使算法适合要解决的问题。
二、循环结构
首先要讲到为什么要使用循环结构。例如当我们需要求 1 ~ 100 自然数之和,这个时候是不能用常规方法手工输入 1 ~ 100 个整数然后让计算机去进行计算的。如果那样的话,有 1000 或者更多的数字需要计算时怎么办?这个时候就需要用到循环结构。例如上面的问题有这样的解决方法:
#include<stdio.h>
int main()
{
int i, s;
s = 0;
for(i = 1; i <= 100; i ++)
{
s = s + i;
}
printf("%d", s);
return 0;
}
这个程序的运行结果是:
5050
常用的循环结构有:for
、while
、do…while
三种,三种循环结构的功能相同,但各有各的特点,所以它们各自能实现不同的功能。同时它们各自可以互相嵌套,还可以改变循环的状态,所以,善用循环结构往往能减少巨大的工作量,让电脑代替人脑完成一些人脑无法完成的工作。
1.while
与 do…while
循环结构
while
结构的一般形式是:
while(表达式)
语句;
这个结构的运行过程是,首先判断表达式的真假,如果为真,则执行语句。语句可以为语句体,此时需要用花括号将语句体括起来。在 while
后面执行的语句(体)称为循环体。
do…while
结构的一般形式是:
do
语句;
while(表达式)
这个程序的运行过程是,首先执行语句(体),再判断表达式真假,如果表达式为真,再进行循环。
2.for
循环结构
除了上述的两种循环结构外,C 语言还提供了另外一种更加灵活的 for
循环结构。它完全可以代替 while
和 do…while
语句。for
语句的一般形式是:
for(表达式1 ; 表达式2 ; 表达式3)
语句;
三个表达式的作用都不相同。表达式1设置初始条件,执行一次,可以没有、一个、或者多个;表达式 2 为判断是否执行循环的条件,当表达式2的值为真时,执行循环体;表达式 3 为循环的变化量,可以没有、一个或多个,执行一次。所以 for
语句的一般形式可以理解为:
for(赋初值 ; 循环条件 ; 增量)
语句;
for
语句的一种极端形式是:
for( ; ; )
这句语句与
while(1)
是等价的,代表无条件循环。
for
循环体的执行过程是,先执行表达式 1,然后判断表达式 2 的真假,如果为真,执行语句,语句可以为语句体。语句(体)执行过后,执行表达式 3,for
的循环体到此执行完一次循环。整个过程如下图:
图:
for
循环结构示意图
可以将 for
循环结构改写为 while
循环结构:
表达式 1;
while (表达式 2)
{
语句;
表达式 3;
}
上述结构与 for
一般形式的循环结构完全等价。基于这种原理,我们可以将之前提到的求 1 ~ 100 自然数和的程序改写:
int i, s = 0;
while(i <= 100)
{
s = s + i;
i ++;
}
int i, s = 0;
do
{
s = s + i;
i ++;
}
while(i <= 100)
3.循环结构的嵌套
上述三种循环结构的优缺点各不相同,在解决程序设计问题时各自能解决不同特征的问题。三种结构可以互相嵌套,实现更强大的功能。当进行设计比较复杂的循环问题时,应该注意代码的规范性,即每层嵌套之间有一个 Tab 键的缩进,这样的话代码看上去有层次感,一眼望去能看出都哪几行代码属于一个层次。便于别人阅读也便于自己修改。
具体的循环嵌套问题还要在日后解决问题中慢慢理解。
4.改变循环结构的状态
当我们解决问题时,往往会遇到需要提前终止循环的情况。例如我们想要求1~一个很大的自然数中所有质数的和,这样我们设置一个1~很大的数的循环,每次遇到质数就把这个数加在和变量中,判断不是质数的话就跳过本次循环。这种方式叫做改变循环的状态。
在 C 语言中,有两种改变循环状态的方式:break
与 continue
。为了讲解这两种方式,我们分别举不同的例子。
例如,我们在全校 1000 名同学范围内筹集资金,当资金数累计到十万元的时候就停止筹集。统计此时捐款人数。我们可以这样编写程序:
#include<stdio.h>
int main()
{
float num, sum = 0;
int i;
for(i = 0 ; i < 1000 ; i ++)
{
printf("输入捐款金额:");
scanf("%f" , &num);
printf("\n");
sum = sum + num;
if(sum >= 100000)
break;
}
printf("有%d人参加捐款。\n", i);
return 0;
}
在程序中可以看出,在第 13 行程序判断 sum >= 100000
是否成立,成立的话程序遇到 break
,跳出整个循环。再看下面的例子。输出 1~100 之间可以被 3 整除的数,程序如下:
#include<stdio.h>
int main()
{
int i;
for(i = 0; i <= 100; i ++)
{
if(i % 3 != 0)
continue;
printf("%d\t", i);
}
printf("输出完毕!\n");
return 0;
}
在程序中可以看出,当程序遇到 continue
时,跳过本次循环,但循环还在继续。这时候需要自己体会二者的差别。
三、练习题
输出 1 ~ 1000 整数范围内所有的“水仙花数”。“水仙花数”即其各位数字的立方和等于其本身。例如 153 = 1 ^ 3 + 5 ^ 3 + 3 ^ 3 = 153,
153
为一个水仙花数。求
1! + 2! + 3! + … + 20!
的值。输出以下图形:
*
***
*****
*******
*****
***
*