文章目录
前言
C语⾔是结构化的程序设计语⾔,在C语言的程序中,主要由三种基本结构构成,它们分别是顺序结构、选择结构(也称分支结构)、循环结构。C语⾔是能够实现这三种结构的,其实,我们⽇常所⻅的事情都可以拆分为这三种结构或者这三种结构的组合。
1.顺序结构
顺序结构是程序中最简单的一种结构,它按照语句的编写顺序执行,没有条件判断和循环操作。在C语言中,每一条语句结束后都会按照从上到下、从前到后的顺序依次执行下一条语句,直到程序结束。顺序结构的特点是顺序执行,即每一条语句按照代码的逻辑顺序执行,不会出现跳转或重复执行的情况。
2.选择结构
对于要先做判断再选择的问题就要使用选择结构,选择结构的执行是依据一定的条件选择执行,而不是按照严格的逻辑顺序。C语言中有两种常见的分支语句来实现这种结构,if语句和switch语句,它通过判断表达式的真假来决定执行哪一段代码。
3.循环结构
循环结构是指在满足一定条件的情况下,反复执行某个功能。C语言中有while循环语句,for循环语句,do-while循环语句,它们都是由循环体中的条件判断继续执行某个功能还是退出循环,根据不同的应用场景,我们可以根据三种语句的特点选择适合的语句解决问题。
顺序结构很简单我们不做过多讲解,接下来让我们开始学习选择结构和循环结构中的分支和循环语句。
一、分支语句
1.if 语句
1.1 if
if的语法形式如下
if(表达式)
语句;
表达式成立(为真),则语句执行;表达式不成立(为假),则语句不执行。
在C语言中,0为假,非0为真。 意思是表达式结果为0,则语句不执行,表达式的结果不是0,则语句执行。
用流程图表示就是:
下面我们来看一个示例。
输入一个整数,判断是否为奇数。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 2 == 1)//判断是否为奇数的条件表达式
printf("%d是奇数\n",num);
return 0;
}
1.2 if…else…
看完判断奇数的示例后,我们会发现其实if语句很简单,但是大家有会有疑问:如果我输入的是奇数,那么它会执行语句打印“num是奇数”,那如果是偶数呢?
上面的代码编译运行之后,如果我们输入偶数比如2,程序将直接结束,没有任何输出,这其实和我们想要的答案有些许偏差,如果我们输入偶数屏幕上也像输入奇数那样打印“num是偶数”就好了。怎么做呢?
这个时候就要用到 "if…else…"语句了,语法形式如下:
if(表达式)
语句1;
else
语句2;
让我们使用这个语句来将我们上面的代码进行优化。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 2 == 1)
printf("%d是奇数\n", num);
else
printf("%d是偶数\n", num);
return 0;
}
通过这个代码相信大家对 if…else… 语句的用法有了简单的了解。其实含义就是:表达式成立(为真),则执行语句1;表达式不成立(为假),执行语句2。
1.3 分支中包含多条语句
看完上面的代码后,不难发现,在if或是else后都只跟着一条语句,在C语言中,默认在 if 和 else 语句中都只控制⼀条语句。比如:
#include <stdio.h>
int main()
{
int clock = 0;
scanf("%d",&clock);
if (clock >= 8 && clock <= 22)
printf("学习");
printf("工作");
printf("吃饭");
else
printf("睡觉");
return 0;
}
这是一个错误的代码,在if后面跟了三条语句后才出现else,如果我们编译运行这串代码,编译器会报错"没有匹配if的非法else"。
意思是这里的else没有if与它匹配,这是不符合C语言语法的,那为什么if和else明明都存在,反而上面的if没有与else匹配呢?
前面我们说了,在C语言中,默认在 if 和 else 语句中都只控制⼀条语句。那么if和else后是不是只能跟一条语句呢?很明显不是的,如果真是这样的话,那**if…else…**的功能有点太弱了。
这时候,我们需要使用一个{ },将想要执行的语句放在同一个大括号内形成一个代码块,因为在C语言中,一个代码块等同于一条语句。这样我们就可以在if和else后面跟多条语句,实现我们想要的功能了!
#include <stdio.h>
int main()
{
int clock = 0;
scanf("%d", &clock);
if (clock >= 8 && clock <= 22)
{
printf("学习");
printf("工作");
printf("吃饭");
}
else
{
printf("睡觉");
}
return 0;
}
1.4 嵌套 if 实现多分支
通过上面的学习我们已经学会了使用if,if…else…解决单个分支和两个分支的问题,但我们生活中不只有两个选择的问题,我们常常面对的是多个分支。其流程图:
试想一下如果我们要统计一批人的年龄并将它们归类,
如果年龄小于18输出少年,
如果年龄在18到39输出青年,
如果年龄在40到59输出中年,
如果年龄在60到90输出老年,
年龄大于90输出老寿星。
对于这样的问题,仅仅是使用 if 或 if…else…是无法解决的。
这个时候,我们就需要将 if 嵌套使用。在 if…else… 语句中,else 可以与另⼀个 if 语句连用,构成多重判断。
模板如下:
if(表达式1)
语句1;
else
{
if(表达式2)
语句2;
else
{
if(表达式3)
语句3;
else
{
......//if...else...语句嵌套
}
}
}
像这样,把if…else…语句放在else后作为一条语句的方法叫做嵌套,这样多层嵌套,就可以实现多重判断,解决多分支问题。
上面的代码这只是一种表示方法,当else后嵌套使用if…else…时,{ }可以省略,形成下面的这种代码。
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
else
......//if...else...语句嵌套
相比两次的代码,我们发现下面的代码更加简单,所以我推荐大家使用下面的这种写法。
现在我们已经学会了 if 的嵌套使用,让我们来解决上面遗留的年龄归类问题吧!
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num < 18)
printf("少年");
else if (num >= 18 && num < 40)
printf("青年");
else if (num >= 40 && num < 60)
printf("中年");
else if (num >= 60 && num < 90)
printf("老年");
else
printf("老寿星");
return 0;
}
1.5 悬空else问题
上面我们提到了if 和 else 的匹配,每个 else 只能和一个 if 匹配,这样构成if… else… 语句,也说了 if 和 else 后都只能跟一条语句(或一个大括号包含多条语句构成的代码块)。那如果有多个 if 该如何和 else 匹配呢?
请看下面的代码:
if(表达式1)
if(表达式2)
语句1;
else
语句2;
这里我们给了两个 if 和一个 else 那么这个 else 该和谁去匹配呢,聪明的人发现了,哦这里第一个 if 和 else 对齐了,是不是说 else 和第一个 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;
}
答案是:什么都不输出!
我们判断 else 与第二个 if 匹配组成一个 if…else… 语句作为第一个 if 语句的执行语句。当我们判断表达式a==1为假时,则语句不执行,程序结束。
2. switch语句
2.1 switch
除了 if 语句外,C语言还提供了 switch 语句来实现分支结构。
switch 语句是⼀种特殊形式的 if…else 结构,用于判断条件有多个结果的情况。它把多重
的 else if 改成更易用、可读性更好的形式。它的语法形式为:
switch (表达式)
{
case value1:
语句1;
case value2:
语句2;
default:
语句3;
}
上面的代码中,根据表达式的不同的值,执行相应的 case 分支。如果找不到对应的值,
就执行 default 分支。
注意:
• switch 后的表达式必须是整型表达式
• case 后的值,必须是整形常量表达式
与 if 不同的是,siwtch 就像是一个开关,下面的哪个case(钥匙)能和它匹配,开关就打开,从这个case进入,执行后面的所有语句。
下面我们用一个例子对其进行理解。
输入任意一个正整数,计算除以3以后的余数。
使用 if 语句实现是这样的:
#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;
}
上述的代码中,我们要注意的点有:
- case 和后边的数字之间必须有空格
- 每⼀个 case 语句中的代码执行完成后,需要加上 break ,才能跳出这个switch语句。
2.2 switch语句中的break
当大家初步了解 switch 以后,一定会对上面所出现的 break 产生疑问,什么是break呢?break有什么作用呢?
上面我着重强调过,switch 像是一个开关,要找到与其匹配的 case 才能打开“开关”然后从所匹配的case开始执行后面的所有语句,注意是所有语句,而不是只执行该 case 后的语句。
以上面的例子参考,想象一下,如果没有break,程序又将如何运行呢?
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch(n%3)
{
case 0:
printf("整除,余数为0\n");
case 1:
printf("余数是1\n");
case 2:
printf("余数是2\n");
}
return 0;
}
编译运行后得到三种结果,观察发现,当我们输入9时,被三整除,n%3结果为0,与case 0: 匹配,switch从case 0: 进入开始执行后面的语句,并且是全部执行!当输入8,7时同理。很明显这并不是我们想要的结果,这个时候 break 的出现就很有必要了。在switch语句中,程序遇到 break 会立刻跳出 switch ,不再继续向下执行,这可以帮助我们当执行完我们想要的语句后结束 switch ,避免后面多余的语句被执行 。如果某⼀个 case 语句的后边没有 break 语句,代码会继续往下执行,有可能执行其他 case 语句中的代码,直到遇到 break 语句或者 switch 语句执行结束。这下大家知道 switch 语句中break的重要性了吧!
当然,并不是说每个case后面都需要 break 语句,这得根据实际情况来定了。比如下面的示例。
输入1 ~ 7的数字,1 ~ 5 打印“工作日”,6,7打印“休息日”。
#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;
}
return 0;
}
上面的示例中,我们发现应该根据实际的情况,来在代码中觉得是否使⽤ break ,或者在哪里使用break ,才能正确完成实际的需求。
2.3 switch 语句中的default
现在我们设想一种情况,在使用switch语句时,switch 后的表达式的值与任何一个case匹配,这种情况要么不做处理,要么在 switch 中加上 default 子句。
switch (表达式)
{
case value1:
语句1;
case value2:
语句2;
default:
语句3;
}
当 switch 后的表达式的值既不是value1,也不是value2时,就会执行 default 子句。比如前面做的打印星期的练习,如果 day 的输⼊不是1~7的值,如果我们要提示:输入错误,则可以这样完成代码:
#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("输入错误!");
}
return 0;
}
2.4 switch语句中的case和default的顺序问题
在 switch 语句中 case 子句和 default 子句有要求顺序吗?default 只能放在最后吗?其实,在 switch 语句中 case 语句和 default 语句是没有顺序要求的,只要你的顺序是满足实际需求的就可以。
不过我们通常是把 default 子句放在最后处理的。
看下面的代码:
#include <stdio.h>
int main()
{
switch(10)
{
default:
printf("错误\n");
case 1:
printf("1\n");
case 2:
printf("2\n");
}
return 0;
}
程序编译运行后得到
我们看到,下面的任何一个case都不能和10匹配,即使我们进入了default子句,后面的case由于default和case都没有break,都一一被执行。所以我们通常都会把 default 放在最后。
分支语句到这里就介绍完了,本次的分享就到这里,下篇博客我将继续介绍循环语句。