3.1 if语句及其易错点解析

在前面的代码中,读者已多次接触if语句,在讲解if语句的使用要点之前,先简单回顾一下if语句的定义和使用的一般形式。

if语句用来判断给定条件是否满足,根据判断结果决定是否执行某个操作。if语句使用的一般形式为:


if(表达式)

语句段;


当表达式的值为真时,执行接下来的语句段,否则跳过该语句段部分继续执行。if语句流程图如图3-1所示。

通常,if语句还会包含else语句部分,如:


if(表达式)

语句段1;

else

语句段2;


表达式的值为真时执行语句段1,否则执行语句段2。if-else语句流程图如图3-2所示。

3.1 if语句及其易错点解析 - 图1

图 3-1 if语句流程图

3.1 if语句及其易错点解析 - 图2

图 3-2 if-else语句流程图

多重if语句嵌套的一般形式为:


if(表达式1)

语句段1;

else if(表达式2)

语句段2;

else if(表达式3)

语句段3;

……

else

语句段n+1;


当表达式N(N=1,2,……,n)的值为真时,执行其后的语句段N,否则执行语句段n+1。多重if语句流程图如图3-3所示。

3.1 if语句及其易错点解析 - 图3

图 3-3 多重if语句流程图

了解了以上几种if语句结构,接下来看看在编程的过程中关于if语句的一些注意事项。

1.条件表达式

细心的读者在阅读之前代码中的if语句时会发现,在表达式中通常把常量放在“==”的左边。这样写的好处是如果在编写代码的过程中不小心少写了一个“=”,那么编译时就会提示出现错误。因为在C语言中,赋值运算符的左值表示一个存储在计算机内存中的对象,不能是常量。看看下面的代码。


include<stdio.h>

void main()

{

int i,j;

i=1;

j=0;

if(1==i)

printf("i的值为1\n");

if(j=1)

printf("j的值为1\n");

return;

}


运行结果:


i的值为1

j的值为1


在上面的代码中,j的初始值为0,由于在if语句表达式中少写了一个“=”,导致结果显示“j的值为1”的错误信息,并且在编译代码时没有给出任何提示信息。如果写成如下的代码:


include<stdio.h>

void main()

{

int i;

i=1;

if(1=i)

printf("i的值为1\n");

return;

}


编译代码时就会出现“error C2106:'=':left operand must be l-value”错误,提示常量不能作为左值。由此可知,在使用常量作为左值时,如果因为疏忽少写了一个“=”,编译时会给出错误提示,但是如果按照一般的方法,把常量放在右边,且少写了一个“=”,编译器则不会给出任何提示,而是默认为一个赋值操作,将赋值操作的最终结果作为表达式的值。所以读者在平时编程时要牢记条件表达式中常量写在左边的语法规则,以防因为疏忽造成难以查找的错误。

2.嵌套if语句

嵌套if语句的使用中最易出错的莫过于多个表达式之间的关系,在生活中经常会遇到类似下面的问题:将一个学生的数学成绩归类为优(90<=score<=100)、良(80<=score<90)、中(70<=score<80)、及格(60<=score<70)、差(score<60)。不少人会按照下面这两种方法来解决。

方法一:


if(score<60)

printf("该学生的数学成绩类别为:差\n");

else if(score<70)

printf("该学生的数学成绩类别为:及格\n");

else if(score<80)

printf("该学生的数学成绩类别为:中\n");

else if(score<90)

printf("该学生的数学成绩类别为:良\n");

else if(score<=100)

printf("该学生的数学成绩类别为:优\n");

else

printf("输入出错!\n");


方法二:


if(score<=100)

printf("该学生的数学成绩类别为:优\n");

else if(score<90)

printf("该学生的数学成绩类别为:良\n");

else if(score<80)

printf("该学生的数学成绩类别为:中\n");

else if(score<70)

printf("该学生的数学成绩类别为:及格\n");

else if(score<60)

printf("该学生的数学成绩类别为:差\n");

else

printf("输入出错!\n");


分析上面的两种实现方法,首先看方法一,如果输入的学生成绩在正常的范围内,那么能得到正确的结果。但是由于方法一的条件表达式范围并不严格,因此当输入一个负数时,将会视其为不及格。对于方法二,只会出现两种信息,一种就是输入的学生成绩为优,另一种就是输入出错,因此这种方法是错误的。这里建议在采用嵌套if语句的时候,对于条件表达式中的变量采用完整的范围限制,即解决上面的问题可以采用下面的方法。


include<stdio.h>

void main()

{

int score;

printf("请输入学生的数学成绩:");

scanf("%d",&score);

if(score<60&&score>=0)

printf("该学生的数学成绩类别为:差\n");

else if(score<70&&score>=60)

printf("该学生的数学成绩类别为:及格\n");

else if(score<80&&score>=70)

printf("该学生的数学成绩类别为:中\n");

else if(score<90&&score>=80)

printf("该学生的数学成绩类别为:良\n");

else if(score<=100&&score>=90)

printf("该学生的数学成绩类别为:优\n");

else

printf("输入出错!\n");

return;

}


运行结果:


请输入学生的数学成绩:98

该学生的数学成绩类别为:优


分析上面的代码,在使用多重if语句的时候,如果表达式N的值为真,那么执行表达式N后面的语句段N,在没有一个表达式的值为真的情况下,如果有else语句,那么就执行else后面的语句段,如果没有else语句,那么就执行if语句下面的语句段。

3.else子句的配对

在讲解else子句的配对之前,先来看下面一段代码,其代码功能为按照先后顺序输入A、B、C三个数,如果A<B<C,那么打印输出“输入数据呈现递增规律”的信息,否则打印输出“输入数据呈现非递增规律”的信息,代码如下:


include<stdio.h>

int main(void)

{

int A,B,C;

printf("请依次输入A、B、C的值:");

scanf("%d%d%d",&A,&B,&C);

if(A<B)

if(B<C)

printf("输入数据呈现递增规律\n");

else

printf("输入数据呈现非递增规律\n");

return 0;

}


先来看一种输入:


请依次输入A、B、C的值:3 2 1


可以发现运行结果中并没有输出“输入数据呈现非递增规律”,这是为什么呢?对if语句很了解的读者应该很快就发现问题的所在,代码中else配对出现了问题,程序的本意是将else与第一个if语句配对,但是按照if语句的标准,else应该与它前面最近的if语句配对。因此配对的if和else必须在同一个作用域内,在不同作用域内的if和else是不可以配对的。知道了错误的原因,修改上面的代码就很简单了。修改后的代码如下:


include<stdio.h>

int main(void)

{

int A,B,C;

printf("请依次输入A、B、C的值:");

scanf("%d%d%d",&A,&B,&C);

if(A<B)

if(B<C)

printf("输入数据呈现递增规律\n");

else

printf("输入数据呈现非递增规律\n");

else

printf("输入数据呈现非递增规律\n");

return 0;

}


运行结果:


请依次输入A、B、C的值:3 2 1

输入数据呈现非递增规律


此时就能够得到正确的结果。其实,完全可以将A、B、C的大小比较放到一个表达式中,为了讲解else的配对问题,这里特地写成上面的形式。代码中第一个else与第二个if语句配对,第二个else与第一个if语句配对。在使用if语句的过程中要清楚else和if语句的配对关系。可以通过图3-4来了解if-else语句的配对关系。

3.1 if语句及其易错点解析 - 图4

图 3-4 if-else语句的配对

if和else的配对准则是:else与距离它最近的在同一个作用域内的没有被配对的if进行配对。对于图3-4中右边的多重if嵌套语句,由于最后一个if和第一个else不在同一个作用域内,因此不能进行配对。而图3-4中左边的第二个else没有与离它最近的if配对,因为这个if已经进行了配对,所以第二个else只能与第二个if进行配对。在写代码的过程中也要养成将那些配对的if和else起始位置放在同一列的习惯。