C语言入门(4/100)
在Day 3的学习,我们对于Day 2 的部分基本语法进行了补充,尤其是针对性地讨论了变量
、常量
、运算符号
等话题。
Day 4 的学习中,将首次开始接触到简单的结构
和语句
:
- 分支结构 :
if
语句if-else
语句:简单、多重、嵌套switch
语句:break
、case
、default
一、结构与语句
1.1 结构
- 默认情况下,程序运行后,系统会按书写顺序从上至下依次执行程序中的每一行代码。
- 但显然,这并不能满足我们所有的开发需求。
- 为方便控制程序的运行流程,就涉及到了
流程控制结构
,不同的流程控制结构可以实现不同的运行流程。- 顺序结构
- 分支结构(选择结构)
- 循环结构
1.2 语句
C语言语句可分为以下五类:
(1)表达式语句(例如 y=x+3;假设变量y和x均已定义)
(2)函数调用语句(MAX(x,y);假设函数MAX()已经定义)
(3)控制语句
(4)复合语句(把多种语句复合在一起形成的语句)
(5)空语句(例如 ;分号本身就可以作为一条语句,称为空语句,至于空语句的作用,后续会讲到 )
无论上述哪一种语句,都必须以分号结束!
今天介绍的分支和循环语句就是控制语句。
1.3 分支结构(单分支)
1.3.1 简单 if
语句
简单 if
条件语句的基本结构如下:
if(表达式)
{
执行代码块;
}
其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句。
if(age >= 18) {
printf("开网卡\n");
}
printf("买烟\n");
注意
:
if()
后面没有分号,直接写{}
1.3.2 简单 if-else
语句
简单 if-else
语句的基本结构如下:
if(表达式)
{
执行代码块1;
}
else
{
执行代码块2;
}
语义是: 如果表达式的值为真,则执行代码块1,否则执行代码块2。
注意
:
else
后面也没有分号,直接写{}
#include<stdio.h>
int main()
{
int n = 0;
if (n == 0)
{
printf("hello\n");
}
else
{
printf("world\n");
}
return 0;
}
最后得到打印结为hello。
1.3.3 多重 if-else
语句
多重 if-else
语句的基本结构如下:
if(表达式1)
{
执行代码块1;
}
else if(表达式m)
{
执行代码块m;
}
else
{
执行代码块n;
}
语义是:依次判断表达式的值,当出现某个值为真时,则执行对应代码块,否则执行代码块n。
注意
:
当某一条件为
真
的时候,则不会再向下执行该分支结构的其他语句。
int main()
{
int a = 1, b = 0;
if (a == 1)
{
printf("a\n");
}
else if (b == 0) //这里改变了变量
{
printf("b\n");
}
else
{
printf("no\n");
}
return 0;
在最后得到打印结果为a。
1.3.4 嵌套 if-else
语句
嵌套 if-else
语句的意思,就是在 if-else
语句中,再写 if-else
语句。
其一般形式为:
if(表达式1)
{
if(表达式2)
{
执行代码块2;
}
else
{
执行代码块3;
}
}
else
{
执行代码块4;
}
1.3.5 if
语句注意点
- 当
if else
后面只有一条语句时,if else
后面的{}
可以省略。
// 极其不推荐的写法
int age = 17;
if (age >= 18)
printf("开网卡\n");
else
printf("喊家长来开\n");
-
当
if else
后面的{}
被省略时,else
会自动和距离最近的一个if
匹配。
如下图所示的代码,请给出输出结果。
最后的打印结果是“hehe”?还是“haha”?
在此先告诉大家结果,输出结果是空白。
原因就是,else
总是跟最近的if
进行匹配!
让我们再看一遍代码。
-
首先对
if(a==1)
进行判断,不成立,然后后面的if(b==2)
与else
语句均不执行了 -
如果进一步优化这段代码,结果就更加清晰了
所以,代码规范很重要! -
如果if else省略了大括号, 那么后面不能定义变量
#include <stdio.h>
int main()
{
if(1)
int num = 10; // 系统会报错
printf("number = %i\n", num);
}
#include <stdio.h>
int main()
{
if(0)
{
int num = 10;
}
else
int value = 20; // 系统会报错
printf("value = %i\n", value);
}
- C语言中分号(
;
)也是一条语句, 称之为空语句
// 因为if(10 > 2)后面有一个分号, 所以系统会认为if省略了大括号
// if省略大括号时只能管控紧随其后的那条语句, 所以只能管控分号
if(10 > 2);
{
printf("10 > 2");
}
// 输出结果: 10 > 2
1.4 分支结构(多分支)
1.4.1 switch
语句
switch
语句也是一种分支语句。 常常用于多分支的情况。
例如,
给出下面的情况,让你写出相应的代码!
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
- 如果用if …else if 进行多分支的话形式太复杂,代码太过于冗长
- 因此,
switch
就应运而生了,他跟if
else if
互为补充关系。 switch
语句的语法形式:
switch(控制表达式)
{
case 常量:
语句;
case 常量:
语句;
default:
语句;
}
注
:
switch
语句后面的()
内可以跟整型变量、整型常量、整形表达式(当然这些也可以是字符型,不过字符型的本质仍然是整型),- 而
case
后面只能跟整型常量,或者字符型常量,必须是常量const
修饰的常变量是不可以的,因为其本质上仍是变量
switch case
条件表达式的类型必须是整型int
, 或者可以被提升为整型的值(char
、short
);case
的值只能是常量, 并且还必须是整型, 或者可以被提升为整型的值(char
、short
);case
后面常量表达式的值不能相同- 常量可以是常数,也可以是常数计算的表达式。
1.4.2 switch case
语句
- 首先计算表达式的值;
- 然后,和case的值依次进行比较,遇到相对应的值就会匹配对应的结果,遇到break,就会退出整个循环;
- 如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉
简言之,就是根据表达式的结果,寻找匹配的
case
,并执行case
后面的语句,一直到break
为止
注
:
- 如果没有遇到
break
,那就接着执行下面的语句。- 如果所有的
case
都不匹配,那么就执行default
后面的语句; - 如果没有
default
,那么程序就什么都不会执行,直接跳过switch case
语句。
- 如果所有的
switch(表达式){
case 常量表达式1:
语句1;
break;
case 常量表达式2:
语句2;
break;
case 常量表达式n:
语句n;
break;
default:
语句n+1;
break;
}
1.4.3 break
和case
首先,说出最终结论
case
相当于支路入口,break
相当于支路出口
break
在程序中是代表 “结束” 的意思
在 switch
语句中,我们没办法直接实现分支,搭配 break
使用才能实现真正的分支。
例如,
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一!");
break;
case 2:
printf("星期二!");
break;
case 3:
printf("星期三!");
break;
case 4:
printf("星期四!");
break;
case 5:
printf("星期五!");
break;
case 6:
printf("星期六!");
break;
case 7:
printf("星期天!");
break;
}
return 0;
}
执行截图:
如果去掉所有break
,运行结果为:
switch
语句可以看作是一种基于计算的跳转- 计算控制表达式的值后,程序会跳转到相匹配的
case
(分支标号)处。- case(分支标号)只是说明switch内部位置的路标
- 在执行完分支中的最后一条语句后,如果没有遇到
break
,那就接着执行下面的语句。- 直到遇到一个
break
就结束 ,或者直到switch
语句结束为止。
- 直到遇到一个
总结一下,
case
实现的是匹配功能,或者说是判定功能,而break
实现的是分支功能(当然,也可以说break
实现的是退出功能。)
有时候我们的需求变了:
- 输入1-5,输出的是“weekday”;
- 输入6-7,输出“weekend”;
所以我们的代码就应该这样实现了:
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday");
break;
case 6:
case 7:
printf("weekend");
break;
}
return 0;
}
break
语句 的实际效果是把语句列表划分为不同的分支部分!
注意
:
case
语句的后面不一定非要加break
!- 需求不同,代码不同!
switch
中只要任意一个case
匹配, 其它所有的case
和default
都会失效. 所以如果 case
和 default
后面没有 break
就会出现穿透问题
#include <stdio.h>
int main()
{
int num = 2;
switch(num)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n"); // 被输出
case 3:
printf("星期三\n"); // 被输出
default:
printf("回火星去\n"); // 被输出
break;
}
}
1.4.4 default
子句
如果表达的值与所有的case标签的值都不匹配怎么办呢?
case
相当于上帝给你开的门,default
相当于上帝把门都关上了后留下的窗
当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
- 每个switch语句中只能出现一条default子句。
- 但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。
注
:
default
语句可前可后,但我们一般习惯把它放在最后- 同时
case
最好按照从小到大来排,方便后续代码的查看和修改- 最好把执行频率高、容易被匹配的放在前面,在一定程度上能够提高代码的执行效率!
1.4.5 实际操作
实践一下switch
语句:
某学校毕业设计成绩评定等级的规则如下:
成绩 >= 90分,为优秀;
80分 <= 成绩 <90分,为良好;
70分 <= 成绩 <80分,为中等;
60分 <= 成绩 70<分,为及格;
成绩<60分,为不及格。
请编写程序,根据输入成绩,计算并输出成绩评定等级。
代码示例:
#include <stdio.h>
int main()
{
//定义一个grade变量用来存放成绩
int grade;
printf("请输入您毕业设计的成绩:");
scanf("%d",&grade);
//判断输入的成绩是否超过100
if(grade<=100){
//如果没有超过一百,据题意那就保留十位数部分去掉个位数部分
grade=grade/10;
switch(grade)
{
/* 因为不管是100还是90以上都是:优秀。所以根据switch case 语句的语法
如果没有遇到 break 那就接着执行下面的语句 */
case 10:
case 9:
printf("恭喜您!您的成绩为:优秀");
break;
case 8:
printf("您的成绩为:良好");
break;
case 7:
printf("您的成绩为:中等");
break;
case 6:
printf("您的成绩为:及格");
break;
default :
printf("很遗憾您的成绩为:不及格\n要加油啊!不要挂科。");
}
}else //如果输入的数超过100,则输出:输入错误
{
printf("输入错误!");
}
return 0;
}
运行结果: