6.1.2 复合条件测试
到目前为止,本章使用过的if语句都只是两个数之间的简单条件测试。代码清单6-1将number的值与0做了比较,而代码清单6-2则将分数的分母与0做了比较。有时候即使不是必需的,也需要设置多个复杂测试。例如,假设要计算一次考试中分数介于70到79之间的分数个数,包括70和79在内。在这种情况下,不是根据一个界限比较考试分数的值,而是根据两个界限70和79进行比较,以确保一个考试分数位于指定的范围之内。
Objective-C语言提供了用于执行这种复合条件测试所必需的机制。复合条件测试仅仅是用逻辑与或者逻辑或运算符中的一个连接起来的一个或多个简单条件测试。这两个运算符分别使用字符对&&和||(两个竖线字符)来表示。举一个例子,Objective-C语句
if(grade>=70&&grade<=79)
++grades_70_to_79;
只在grade的值大于等于70或小于等于79时才对grade_70_to_79的值加1。使用类似的方式,语句
if(index<0||index>99)
NSLog(@“Error-index out of range”);
在index小于0或大于99时会执行NSLog语句。
在Objective-C中,复合运算符可用于形成极其复杂的表达式。Objective-C向程序员提供了在构成表达式时极大的灵活性,这种灵活性经常被滥用。比较简单的表达式往往更容易阅读和调试。
形成复合条件表达式时,可大量使用圆括号来加强表达式的可读性,并避免由于错误假设表达式中的运算符优先级而陷入麻烦之中(与任何算术运算符或关系运算符相比,&&运算符有更低的优先级,但比||运算符的优先级要高)。在表达式中还应该使用空格以加强表达式的可读性。&&和||运算符两旁的空格将在视觉上把用这些运算符连接起来的表达式与运算符分隔开。
要在实际的程序例子中说明复合条件测试的用途,编写一个程序来测试某个年份是不是闰年。我们知道,如果某个年份能被4整除,它就是闰年。然而,你可能没有认识到,能被100整除的年份并不是闰年,除非它能同时被400整除。
试着考虑,如何为这样的条件设置测试。首先,计算某个年份除以4、100和400所得的余数,并将这些值分别指派给名称合适的变量,如rem_4、rem_100和rem_400。然后,可以继续测试这些余数,以确定是否满足闰年的标准。
如果重新表达上述的闰年定义,可将它表示为:如果某个年份能被4整除但不能被100整除、或某个年份能被400整除,这一年就是闰年。暂停一会儿思考最后一个句子,并自己验证这个句子等价于前面陈述的定义。现在,已经用这些条件重新阐述了闰年的定义,将这些句子转换成以下程序语句的过程变得相对简单和直观,如下所示:
if((rem_4==0&&rem_100!=0)||rem_400==0)
NSLog(@“Its a leap year.”);
子表达式
rem_4==0&&rem_100!=0
两边的圆括号不是必需的,因为表达式就是以这种方式求值的,记住,&&比||有更高的优先级。
事实上,在这个特定的例子中,测试
if(rem_4==0&&(rem_100!=0||rem_400==0))
将运作良好。
如果在测试之前添加几条语句,声明变量并允许用户从终端键入年份,最终就会生成一个用来确定某个年份是不是闰年的程序,如代码清单6-5所示。
代码清单6-5
//This program determines if a year is a leap year
import<Foundation/Foundation.h>
int main(int argc, char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
int year, rem_4,rem_100,rem_400;
NSLog(@“Enter the year to be tested:);
scanf(“i”,&year);
rem_4=year%4;
rem_100=year%100;
rem_400=year%400;
if((rem_4==0&&rem_100!=0)||rem_400==0)
NSLog(@“Its a leap year.”);
else
NSLog(@“Nope, its not a leap year.”);
[pool drain];
return 0;
}
代码清单6-5输出
Enter the year to be tested:
1955
Nope, its not a leap year.
代码清单6-5输出(重新运行)
Enter the year to be tested:
2000
Its a leap year.
代码清单6-5输出(重新运行)
Enter the year to be tested:
1800
Nope, its not a leap year.
上述例子使用了3个年份:一个并非闰年(1955),因为它不能被4整除;一个闰年(2000),因为它能被400整除;一个并非闰年(1800),因为它能被100整除但不能被400整除。要使测试用例完整,还应改检验能被4整除但不能被100整除的年份是否是闰年。这将作为练习由你来完成。
我们提到Objective-C在创建表达式方面为程序员提供了极大的灵活性。例如,在前一个程序中,不必计算中间结果rem_4、rem_100和rem_400,可能直接在if语句中进行了计算,如下所示:
if((year%4==0&&year%100!=0)||year%400==0)
用于分隔各种运算符而使用的空格还加强了上述表达式的可读性。如果决定不添加空格并删除非必需的圆括号,将会获得以下表达式:
if(year%4==0&&year%100!=0||year%400==0)
这个表达式是完全合法的,运行结果将等价于(不管你是不是相信)前面刚刚显示的表达式。显然,这些额外的空格在帮助理解复杂表达式方面起到很大作用。