if语句是c语言最常见的条件判断语句,它可以根据表达式的真假来做出逻辑判断,实现“选择”。它的语法如下:
if (表达式)
语句
如果表达式为真,则会执行下面的语句,否则这条语句就不执行。而其中的“真假”在c语言中使用0和非0表示的。0表示假,非0表示真。
以下是一个例子:
#include <stdio.h>
int main()
{
int a = 0;
if(a == 0)
{
printf("Yes\n");
}
return 0;
}
上述代码中a等于0的值为真,所以输出“Yes”。
如果你想要在一个表达式不满足if条件的情况下执行一条语句,就需要和else语句配合使用。
if--else语句的使用方法如下:
if(表达式)
(语句块)
else
(语句块)
接下来是一个判断奇偶数的程序:
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if (n % 2 == 0)
{
printf("是偶数\n");
}
else
{
printf("不是偶数\n");
}
return 0;
}
以上程序中,如果输入的n满足if后的表达式,就会执行if后的语句,否则就会执行else后的语句。
如果if和else之后的执行语句中无大括号,则只会默认执行其后的一条语句。例如:
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if (n == 1)
printf("hello\n");
printf("OK\n");
return 0;
}
运行结果:
无论n是否为1,“OK”都会打印在屏幕上。这是因为如果if条件为真,则会执行其后的一条语句,如果为假,就不执行。但是“OK”的打印相对于if语句是独立的,无论条件是否满足都会输出。
在条件判断中,可以使用else if语句,形成多重判断。例如:
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if (n == 0)
{
printf("输入的数字是0\n");
}
else if (n > 0) //此处语法与if语句相同
{
printf("输入的数字是正数\n");
}
else
{
printf("输入的数字是负数\n");
}
return 0;
}
以上代码用于判断输入数字的三种情况。当有三种及以上分支条件时,我们就可以使用它。
if语句也可以使用嵌套,来实现更加复杂的逻辑判断。例如:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num >= 0)
{
if (num % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
}
else
{
printf("负数\n");
}
return 0;
}
当输入的数是非负数时,再判断是否是奇数或偶数。如果输入一个负数,就输出“负数”。这其中有if--else语句在另一个if语句块当中,这就构成了嵌套if语句。
程序中如果有多个if--else语句,则else总是和最近的if相匹配。阅读以下代码:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
你可能会认为a等于0不满足条件,会执行下面的else语句输出“haha”,其实这段代码的结果是:什么都不输出。
这就是典型的悬空else问题。上述代码当中,由于第二个if存在缩进,所以让我们误以为else会与第一个if匹配,从而在不满足a==1的条件下执行else语句。但是实际上,它与离它最近的if语句匹配,a==1条件不满足,接下来的整段代码都不会执行。
为了避免上述情况,我们只需要使用大括号包含其中的语句块来体现其逻辑:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
{
if (b == 2)
printf("hehe\n");
}
else
{
printf("haha\n");
}
return 0;
}
所以一般情况下,为了保持良好的代码风格和逻辑,我们在条件判断语句当中无论有多少行代码,都用大括号括起来。
在if--else语句的条件判断当中,常出现带有逻辑运算符的语句,接下来让我们了解各种逻辑运算符。
c语言中用于比较的表达式就称为关系表达式,而其中所使用的操作符就是关系操作符。以下是常见的关系操作符:
> //大于
< //小于
>= //大于等于
<= //小于等于
== //等于
!= //不等于
这些操作符都是双目操作符,用于比较两个数值的关系。如果满足条件,则表达式的值为1,否则为0。例如:5 > 4这个表达式的值是1,5==4的值是0。
注意:相等== 和赋值= 是两个不同的运算符,如果不慎将相等写成赋值,会出现意料之外的结果。
if (x==5)
if (x=5)
第二个语句当中,不慎将相等写成了赋值,此时x被赋值为5,这个条件表达式的值就是5,5是非0,所以这个条件永远为真。
条件操作符是一种三目操作符,能够实现类似if--else语句的逻辑分支。它的语法是:
exp1 ? exp2 : exp3
它的计算逻辑是:先判断exp1的真假。如果exp1为真,则执行exp2语句,否则执行exp3语句。整个表达式的值是最终执行语句的值。例如:
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d", &a);
b = a > 5 ? 3 : -3;
printf("%d\n", b);
return 0;
}
以上代码中,如果输入a的值大于5,b的值就是3,否则就是-3。
当表达式较为复杂时,就需要使用逻辑操作符用于复杂的逻辑判断。逻辑操作符主要有三个:
1. && (逻辑与)就是并且的意思,是一个双目操作符,当其两侧的表达式都为真时,整个表达式为真。其两侧有一个表达式为假,整个表达式为假。
2. ||(逻辑或)就是或者的意思,是一个双目操作符,当其两侧的表达式有一个为真时,整个表达式为真。其两侧的表达式都为假,整个表达式才为假。
3. !(逻辑取反)是一个单目操作符,用于反转表达式的真假。
当我们要连续使用多个关系运算符时,可能会出现连用的情况。
3 < x < 5
注意:这种写法是错误的,往往会出现意料之外的结果。以上这个表达式的实际意义是:先判断3是否小于x,如果为真,则前半段的值为1,否则为0。再将1或者0与5相比较,整个表达式的值是恒为真的。这不是我们预期的效果。
对于这种逻辑判断,我们就需要使用逻辑操作符。例如:
x > 3 && x < 5
当x大于3和x小于5的条件同时满足时,整个表达式的值就是1(真)。这样就能达到预期效果。
c语言的双目逻辑运算符有一个特性:它先计算左边表达式,再计算右边表达式。如果说左边的表达式已经满足逻辑运算符的条件,那么右边的表达式不再计算。这个情况称之为“短路”。
例如:
a>=3 && a<=5
如果a<3,则左边的表达式为假,整个表达式肯定为假,右边的式子就不再计算。
a<=3 || a>=5
如果a<=3,左边的表达式就为真,整个表达式肯定为真,右边的式子就不再计算。
让我们判断以下代码的输出结果:
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
return 0;
}
运行结果如下:
以上代码当中,由于逻辑运算符的运算特性,先对a++进行运算。由于这是后置++,先操作再自增,所以就对a的值先进行判断。a的值为0,也就是假,整个表达式的值就是假,就不会再计算后边的两个式子。此时逻辑判断完成后,a才会进行自增运算,所以a就编程了1。而b,c,d的值都不变。
除了if--else语句之外,switch语句也可以实现分支结构。当出现多重分支的情况,if--else语句的使用就会略显麻烦,switch语句可以解决这个问题。
示例:判断一个数除以3后的余数
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if(n % 3 == 0)
printf("余数是0\n");
else if(n%3 == 1)
printf("余数是1\n");
else
printf("余数是2\n");
return 0;
}
以上代码也可以改为使用switch语句:
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch(n % 3)
{
case 0:
printf("余数是0\n");
break;
case 1:
printf("余数是1\n");
break;
case 2:
printf("余数是2\n");
break;
}
return 0;
}
程序计算switch后的表达式,将其值与case后的数值进行比较,如果相同则执行相应的语句。这里要注意:1.switch后必须是整形表达式。2.case后必须是整形常量表达式。3.case与数字之间必须有空格。4.每一个case语句执行后,要写break。
如果上述代码中不写break,会发生什么情况?让我们运行代码:
结果三条语句都被执行。这是为什么呢?
原因是在switch语句中使用break才能跳出switch语句。如果某一个case语句之后没有break,程序会继续往下执行,有可能执行其他case语句中的代码,直到遇到break或者switch语句结束。所以在switch语句当中使用break才能提前其分支效果。当然,是否在每一个case语句后加入break语句也要根据实际情况而定。
在switch语句中,如果遇到所有case都无法与表达式匹配的情况,那么就要对这些情况做一些处理。这时使用default语句就恰到好处。例如:
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch(day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("⼯作⽇\n");
break;
case 6:
case 7:
printf("休息⽇\n");
break;
default:
printf("输⼊错误\n");
break;
}
return 0;
}
以上代码用于判断周内的某一天是工作日还是休息日。当输入的值不再1-7的范围内时,就进入default语句,提示“输出错误”。
有人可能有以下疑问:default一定要写在最后吗?实际上,default语句的位置是随意的,不会影响程序的结果,但是一般我们为了提升代码的可读性,default语句是写在最后的。