08-多层嵌套的if语句
7.2.5 多层嵌套的 if 语句
前面介绍的 if...else if...else 序列是嵌套 if 的一种形式,从一系列选项中选择一个执行。有时,选择一个特定选项后又引出其他选择,这种情况可以使用另一种嵌套 if 。例如,程序可以使用 if else 选择男女, if else 的每个分支里又包含另一个 if else 来区分不同收入的群体。
我们把这种形式的嵌套 if 应用在下面的程序中。给定一个整数,显示所有能整除它的约数。如果没有约数,则报告该数是一个素数。
在编写程序的代码之前要先规划好。首先,要总体设计一下程序。为方便起见,程序应该使用一个循环让用户能连续输入待测试的数。这样,测试一个新的数字时不必每次都要重新运行程序。下面是我们为这种循环开发的一个模型(伪代码):
提示用户输入数字
当 scanf() 返回值为 1
分析该数并报告结果
提示用户继续输入
回忆一下在测试条件中使用 scanf() ,把读取数字和判断测试条件确定是否结束循环合并在一起。
下一步,设计如何找出约数。也许最直接的方法是:
for (div = 2; div < num; div++)
if (num % div == 0)
printf("%d is divisible by %d\n", num, div);
该循环检查 2 ~ num 之间的所有数字,测试它们是否能被 num 整除。但是,这个方法有点浪费时间。我们可以改进一下。例如,考虑如果 144%2 得 0 ,说明 2 是 144 的约数;如果 144 除以 2 得 72 ,那么 72 也是 144 的一个约数。所以, num % div 测试成功可以获得两个约数。为了弄清其中的原理,我们分析一下循环中得到的成对约数: 2 和 72 、 3 和 48 、 4 和 36 、 6 和 24 、 8 和 18 、 9 和 16 、 12 和 12 、 16 和 9 、 18 和 8 ,等等。在得到 12 和 12 这对约数后,又开始得到已找到的相同约数(次序相反)。因此,不用循环到 143 ,在达到 12 以后就可以停止循环。这大大地节省了循环时间!
分析后发现,必须测试的数只要到 num 的平方根就可以了,不用到 num 。对于 9 这样的数字,不会节约很多时间,但是对于 10000 这样的数,使用哪一种方法求约数差别很大。不过,我们不用在程序中计算平方根,可以这样编写测试条件:
for (div = 2; (div * div) <= num; div++)
if (num % div == 0)
printf("%d is divisible by %d and %d.\n",num, div, num / div);
如果 num 是 144 ,当 div = 12 时停止循环。如果 num 是 145 ,当 div = 13 时停止循环。
不使用平方根而用这样的测试条件,有两个原因。其一,整数乘法比求平方根快。其二,我们还没有正式介绍平方根函数。
还要解决两个问题才能准备编程。第1个问题,如果待测试的数是一个完全平方数怎么办?报告 144 可以被 12 和 12 整除显得有点傻。可以使用嵌套 if 语句测试 div 是否等于 num /div 。如果是,程序只打印一个约数:
for (div = 2; (div * div) <= num; div++)
{
if (num % div == 0)
{
if (div * div != num)
printf("%d is divisible by %d and %d.\n",num, div, num / div);
else
printf("%d is divisible by %d.\n", num, div);
}
}
注意 从技术角度看,
ifelse语句作为一条单独的语句,不必使用花括号。外层if也是一条单独的语句,也不必使用花括号。但是,当语句太长时,使用花括号能提高代码的可读性,而且还可防止今后在if循环中添加其他语句时忘记加花括号。
第2个问题,如何知道一个数字是素数?如果 num 是素数,程序流不会进入 if 语句。要解决这个问题,可以在外层循环把一个变量设置为某个值(如, 1 ),然后在 if 语句中把该变量重新设置为 0 。循环完成后,检查该变量是否是 1 ,如果是,说明没有进入 if 语句,那么该数就是素数。这样的变量通常称为标记(flag)。
一直以来,C都习惯用 int 作为标记的类型,其实新增的 _Bool 类型更合适。另外,如果在程序中包含了 stdbool.h 头文件,便可用 bool 代替 _Bool 类型,用 true 和 false 分别代替 1 和 0 。
程序清单7.5体现了以上分析的思路。为扩大该程序的应用范围,程序用 long 类型而不是 int 类型(如果系统不支持 _Bool 类型,可以把 isPrime 的类型改为 int ,并用 1 和 0 分别替换程序中的 true 和 false )。
程序清单7.5 divisors.c 程序
// divisors.c -- 使用嵌套if语句显示一个数的约数
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
unsigned long num; // 待测试的数
unsigned long div; // 可能的约数
bool isPrime; // 素数标记
printf("Please enter an integer for analysis; ");
printf("Enter q to quit.\n");
while (scanf("%lu", &num) == 1)
{
for (div = 2, isPrime = true; (div * div) <= num; div++)
{
if (num % div == 0)
{
if ((div * div) != num)
printf("%lu is divisible by %lu and %lu.\n",
num, div, num / div);
else
printf("%lu is divisible by %lu.\n",
num, div);
isPrime = false; // 该数不是素数
}
}
if (isPrime)
printf("%lu is prime.\n", num);
printf("Please enter another integer for analysis; ");
printf("Enter q to quit.\n");
}
printf("Bye.\n");
return 0;
}
注意,该程序在 for 循环的测试表达式中使用了逗号运算符,这样每次输入新值时都可以把 isPrime 设置为 true 。
下面是该程序的一个输出示例:
Please enter an integer for analysis; Enter q to quit.
123456789
123456789 is divisible by 3 and 41152263.
123456789 is divisible by 9 and 13717421.
123456789 is divisible by 3607 and 34227.
123456789 is divisible by 3803 and 32463.
123456789 is divisible by 10821 and 11409.
Please enter another integer for analysis; Enter q to quit.
149
149 is prime.
Please enter another integer for analysis; Enter q to quit.
2013
2013 is divisible by 3 and 671.
2013 is divisible by 11 and 183.
2013 is divisible by 33 and 61.
Please enter another integer for analysis; Enter q to quit.
q
Bye.
该程序会把 1 认为是素数,其实它不是。下一节将要介绍的逻辑运算符可以排除这种特殊的情况。
小结:用 if 语句进行选择
关键字: if 、 else
一般注解:
下面各形式中, statement 可以是一条简单语句或复合语句。表达式为真说明其值是非零值。
形式1:
if (expression)
statement
如果expression为真,则执行statement部分。
形式2:
if (expression)
statement1
else
statement2
如果expression为真,执行statement1部分;否则,执行statement2部分。
形式3:
if (expression1)
statement1
else if (expression2)
statement2
else
statement3
如果expression1为真,执行statement1部分;如果expression2为真,执行statement2部分;否则,执行statement3部分。
示例:
if (legs == 4)
printf("It might be a horse.\n");
else if (legs > 4)
printf("It is not a horse.\n");
else /* 如果legs < 4 */
{
legs++;
printf("Now it has one more leg.\n");
}