目录
1. 什么是语句?
2. 分支语句(选择结构)
if语句
悬空else
if书写形式的对比
练习
switch语句
在switch语句中的 break
default子句
练习
1. 什么是语句?
C语句可分为以下五类:
1. 表达式语句
2. 函数调用语句
3. 控制语句
4. 复合语句
5. 空语句
我们这里说的分支语句和循环语句都是属于控制语句。
C语言有九种控制语句,可分成以下三类:
1. 条件判断语句也叫分支语句:if语句、switch语句;
2. 循环执行语句:do while语句、while语句、for语句;
3. 转向语句:break语句、goto语句、continue语句、return语句。
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成。
什么叫做结构方式呢,我们经常说C语言是【结构化】的程序设计语言,不仅仅是C语言,在生活中,万事万物都能抽象成成三种结构——顺序结构,选择结构,循环结构,或者这三种结构中几个的组合。
2. 分支语句(选择结构)
如何实现这种分支或者选择结构呢,这个我们在C语言基础语法概览中就曾提到过。
如果你好好学习,校招时拿一个好offer,走上人生巅峰。
如果你不学习,毕业等于失业,回家卖红薯。
这就是选择!
可以双分支,也可以有多分支。
if语句
if语句就能够实现上面我们想要的选择,那if语句的语法结构是怎么样的呢?
语法结构:
if(表达式)
语句;
int main()
{
int a = 5;
if (a == 3)
printf("hehen");
return 0;
定义一个数a,并赋值为5,如果a等于3,为真,打印hehe,a不等于3,为假,则不打印hehe
简单的if语句就是这么写的,当然你也可以让它具有某种意义
定一个年龄age>18,打印成年,不大于则不打印。
if语句除了上面的写法,还可以这么写:
if(表达式)
语句1;
else
语句2;
如果表达式为真,语句1执行,如果表达式为假,else里的语句2执行。
那我们可以把上面的代码改一下
int age = 10;//这里输入年龄
if (age < 18)
{
printf("未成年n");
}
else
{
printf("成年n");
}
age赋值10,小于18,表达式为真,执行语句1,打印未成年;age赋值20,大于18,表达式为假,执行语句2,打印成年。
注意:
很多初学if else语句的时候,很容易在if后面加;,else后面加;因为if控制的就是后面printf("未成年n");这一条语句,一个;就是一条语句,如果if后面加;那 if (age < 18);这就是空语句,什么都没有,else,同样如此。
我们上面说到有多分支的情况,那么就不仅仅是两种选择了
多分支
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
printf("青少年n");
else if (age >= 18 && age < 28)
printf("青年n");
else if (age >= 28 && age < 40)
printf("壮年n");
else if (age >= 40 && age < 60)
printf("中年n");
else if (age >= 60 && age <= 100)
printf("老年n");
else
printf("老寿星n");
return 0;
}
这里我们写的就是多分支了。定一个一个数age,输入数据,根据范围返回值,每一个if都代表着一种情况。
注意这里age大于等于18到小于28,并不能用18<=age<28;这样的写法,语句会先执行18<=age,这里应该用前面学的&&逻辑与操作符(并且):age >= 18 && age < 28。
注释:
在C语言中如何表示真假?
0表示假,非0表示真。
如果表达式的结果为真,则语句执行。
if语句后面,默认只能跟一条语句,如果想要跟多条语句一定要用{}括起来,else也是一样。
#include int main()
{
if(表达式)
{
语句列表1;
}
else
{
语句列表2;
}
return 0;
}
这里的一对 { } 就是一个代码块。
悬空else
我们观察下面这个代码,它会输出什么呢?
我们将代码拷贝到VS编译器中,运行,发现什么也不会输出,那为什么呢
因为else默认和离他最近的if匹配,所以代码应该是:
所以是如果a等于1,这个条件成立,if里面的语句才会执行,里面的if和else才有机会执行,但现在a是0,不等于1,压根就不会进去,里面的if else不会执行,所以什么也不会打印。
大家看到这么写,就会理解为,如果a等于1,打印hehe,否则打印haha。(注意:if里面的if else合起来才是一条语句,所以这里不加{}不算错)
这个代码告诉我们:
1.else和离他最近的if匹配
2.代码分隔对其就很重要
试想一下,如果让你分析这个代码,你能分析的清楚吗?
上面的代码如果这样写就很清晰了, else和哪个if匹配,一目了然。
if书写形式的对比
if (condition) {
return x;
}
return y;
if (condition) {
return x;
}
return y;
这个代码的意思是条件满足返回x;条件不满足返回y,是这样吗,就是这样,但在阅读的时候,会让你产生歧义,到底是不是这样呢?
比如下面这个代码
int test()
{
int a = 4;
if (a == 3)
return 1;
return 0;
}
int main()
{
int r = test();
printf("%dn", r);
return 0;
}
我们F10,调试看r的值,就能发现,r开始随机值,然后F11进入到函数里面,因为a赋值为4,等于3,所以r值返回0
这时a赋值为3,r返回值1
但是这个代码在阅读上,就容易让人产生歧义
这个代码要是改成这样,你还会把它读错吗
我想大概是不会了吧
if(condition)
{
return x;
}
else
{
return y;
}
这就是代码是书写上不同的写法,带来的不同的体验。
如果我们写下面这个代码
int main()
{
int num = 3;
if (num==5)
printf("hehen");
return 0;
}
赋值为3,如果num等于5,打印hehe
但如果我们在书写的时候,漏掉了一个=,写成if (num=5),这就变成了,num赋值为5
但运行发现编译器并不会报错,但这样运行的结果和我们想要的结果就不一样了
那我们有没有什么办法,来降低这个写错的可能性呢?
当num==5时,是可以写成,5==num的,而要是num=5,是不能写成5=num的(这个意思是把一个变量赋给常量,这是肯定不行的)
所以当等于时,写成5==num,能够有效避免写错的可能。
练习
1. 判断一个数是否为奇数
int main()
{
//判断一个数是否为奇数
int num = 0;
scanf("%d", &num);
//判断
if (num % 2 == 1)
printf("奇数n");
else
printf("Non");
return 0;
}
判断一个数是否为奇数的依据就是,看它除以二,如果余数为1,就为奇数,就是num%2==1
2. 输出1-100之间的奇数
首先要输出1—100之间的数,然后再判断是不是奇数,是奇数就打印,不是奇数,就不打印
//输出1-100之间的奇数
int main()
{
int i = 1;
while (i <= 100)
{
if (i % 2 == 1)
printf("%d ", i);
i++;
}
return 0;
}
还可以给i赋值为1,1是奇数,然后不断打印i+2的值,到100,也可以得到1-100之间的奇数
int main()
{
int i = 1;
while (i <= 100)
{
printf("%d ", i);
i+=2;
}
return 0;
}
switch语句
switch语句也是一种分支语句。 常常用于多分支的情况。
比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
用 if...else if ...else if 写可不可以呢,当然可以,只是很麻烦。
那有没有更简单的写法呢,那就是switch语句
switch(整型表达式)
{
语句项;
}
而语句项是什么呢?
//是一些case语句:
//如下:
case 整形常量表达式:
语句;
在switch语句中的 break
上面的代码就可以写成
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期1n");
case 2:
printf("星期2n");
case 3:
printf("星期3n");
case 4:
printf("星期4n");
case 5:
printf("星期5n");
case 6:
printf("星期6n");
case 7:
printf("星期日n");
}
return 0;
}
运行,输入3,发现确实是从3这里进来,打印星期三,但为什么3后面的也打印了呢?
因为在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。
case只是决定入口,并没有说在哪里出去啊
那switch语句如何跳出去呢,有个专门的跳转语句叫做break
在每句话后面加上break
这样就是一个完整的switch的工作原理:从case进入,break出来。
switch必须是整形表达式,那这里我们改成浮点型测试一下
改成浮点型不行,必须是整形表达式
case是整型常量表达式,我们换成变量测试一下
有时候我们的需求变了:
1. 输入1-5,输出的是“weekday”;
2. 输入6-7,输出“weekend”
那是把1~5后面都改成weekday,6~7后面都改成weekend吗?
那有没有更简单的方法呢
因为输入1~5都是weekday,就是说从1~5进入,都是从weekday出
输入6~7都是weekend。就是说从6~7进入,都是从weekend出
break语句 的实际效果是把语句列表划分为不同的分支部分。
这里有一个编程的好习惯 :
在最后一个 case 语句的后面加上一条 break语句。(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句,而出现错误)。
default子句
如果表达的值与所有的case标签的值都不匹配怎么办?
上面的代码是输入1~7,可要是输入的不是1~7怎么办
我们输入一个8,发现其实也没什么,结构就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在C中并不认为是个错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条default子句,把下面的标签 default:
写在任何一个 case 标签可以出现的位置。
当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
每个switch语句中只能出现一条default子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。
这里也有一个编程的好习惯:
在每个 switch 语句中都放一条default子句是个好习惯,甚至可以在后边再加一个 break 。
练习下面这个代码运行,会输出什么结果呢?
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:m++;
case 2:n++;
case 3:
switch (n)
{//switch允许嵌套使用
case 1: n++;
case 2: m++; n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %dn", m, n);
return 0;
}
逻辑:n是1,m是2,switch用n来判断,n是1,从case1进去,m++,m变成3,没有break,会继续到case2,n++,n变成2,又没有break,继续case3,switch用n来判断,此时n是2,从case2进入,m++,n++,m是4,n是3,此时break只会跳出自己所在的case语句,case3后面没有break,此时会从case4再进去,m++,m是5,然后break,这时这个break是外面这个(大的)switch语句的,然后就来到printf打印出结果。
注意:
1.switch语句是可以嵌套的
2.switch语句中的break只会跳出自己所在的switch语句。



