前言
在刚刚进入C的世界后,有很多同学对C语言的分支循环结构的语句不是很了解,所以我借着这次机会,想具体讲一下分支和循环,最后还是想让伙伴们在看完之后能真正将这些语句运用到编程中去。学会这些语句,其实已经可以解决编程世界的很多问题了。
介绍语句
C的分支语句分为两种:if语句和switch语句
C的循环语句分为三种:while循环,for循环和do...while循环
接下来我将按顺序分别讲述一下这些语句的用法规则
if语句
if(条件1)//只有在满足条件时才会从一个语句中进入,执行完相应模块然后再整个跳出
{
操作语句;
}
else if(条件2)//这里的else if ,else等都是可以省略的,而且else if的个数不限,可以有多个
{
操作语句;
}
else if(条件3)
{
操作语句;
}
else //else在一个分支语句中最多只能有一个,且在不符合以上所有条件时执行
{
操作语句;
}
以上时if语句的基本用法,一个大括号里面对应的是和他匹配的相应条件,在一组操作语句执行完之后不会再执行其他语句,直接跳出if语句。
那么大家可能会问:能不能把大括号去掉呢,像以下代码这样
if(条件1)
操作语句;
else if(条件2)
操作语句;
else if(条件3)
操作语句;
else
操作语句;
当然可以,但是这里有一个限制条件就是一个if只能控制一条语句像以下这样
if(a==b)//像这样一个if或else控制两个语句的写法都是错误的
a++;
b=a;
else
a--;
a+=b;
一个if或者else如果没有大括号就只能控制其下方一条与其最靠近的语句
接下来,想问大家一个初学者常犯的错误,大家先看看以下代码运行后将输出什么?
#include <stdio.h>
int main()
{
int a = 1;
if (a == 0)
if (a == 1)
printf("haha\n");
else printf("hehe\n");
return 0;
}
也许你会说:这不就是一个打印hehe的代码嘛,有什么可问的,但是我还是再建议大家还是动手打以下以上代码运行一下看看将输出什么
最终结果是,将什么都不会输出,在表面上来看其实第一个if和else是对齐的,但是实际上这样看与if else的匹配法则不符。else ,else if是于其最近的if相匹配的,正真与else匹配的是第二个if,这就取决于一开始能否走进第一个if的分支语句后才能进一步判断是否输出hehe。
讲到这,大家是否对分支语句if有了一定的了解呢?接下来,我将给大家介绍第二种分支语句:switch。
switch语句
现在邀请大家用编程解决一个这样的问题:
输入一个小于8的数字分别打印对应一周的七天。
也许大家会写以下代码
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
if (a == 1)
printf("周一\n");
else if (a == 2) {
printf("周二\n");
}
else if//以下省略
。。。。。
return 0;
}
但是,这样会不会有些繁杂了呢?于是就有了switch这样的语句来解决以上问题
看以下switch语句运用代码
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
switch (a) {
case 1://如果a==1
printf("day1\n");
case 2://如果a==2
printf("day2\n");
case 3:
printf("day3\n");
case 4:
printf("day4\n");
case 5:
printf("day5\n");
case 6:
printf("day6\n");
case 7:
printf("day7\n");
default://在输入在前7个都不存在时就会从这进入
printf("wrong\n");
}
return 0;
}
那么输入5后输出结果会是什么呢?
可以看到在输出day5之后又连续输出了day6,直至wrong ,这是怎么回事呢?
原来,在switch语句中,case只代表一个满足条件的入口,在执行完当前语句后会顺着继续往下执行,那么怎么避免此种情况呢?再来看以下代码
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
switch (a) {
case 1:
printf("day1\n");
break;
case 2:
printf("day2\n");
break;
case 3:
printf("day3\n");
break;
case 4:
printf("day4\n");
break;
case 5:
printf("day5\n");
break;
case 6:
printf("day6\n");
break;
case 7:
printf("day7\n");
break;
default:
printf("wrong\n");
}
return 0;
}
break语句的运用可以解决这一问题,让程序从switch语句中直接跳出,这样就不会再出现上面那种情况了。
现在我将再问一个问题:
如果输入1-5时打印工作日,6-7时打印休息日时,应该怎么处理程序呢?
你可能会说,这又什么难的,把前五个输出都改成workday,后两个改成weekend
但是实则可以更加简化,看以下以下代码
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
switch (a) {
case 1:
case 2:
case 3:
case 4:
case 5:
printf("workday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
default:
printf("wrong\n");
}
return 0;
}
以上代码便很好的解决了这个问题
最后再介绍以下switch,里面的case,default之间的顺序都是可以互换的 ,同时case后面所跟的一定是一个字符(要用单引号引起来如:‘a’)或者数字,浮点型放到后面是会报错的
while循环
while(循环条件){
执行语句;
}
当满足循环条件时,将会执行下方大括号内语句
在循环条件返回非0时才会运行
主要要注意的地方就是在执行循环时不要忘记调整条件,防止陷入死循环。
for循环
先来看看for循环格式
for (初始化;条件;调节语句) {
执行语句;
}
for循环也是编程中用到的比较多的一种循环了
想先通过一张图来让大家基本的了解for循环
由于博主目前不太会用画图工具,所以直接用了书写来展示for循环的运行过程,其实如果你再仔细观察for循环和while循环,也许不难发现,其实for是对循环所需要必要条件的一个集合,里面包含了变量初始化,条件判断以及变量每次循环后的调整,大大简洁了代码,也是在实际运用和做题中运用相对比较多的一个语句。
还有就是要提醒一点,就是for后面小括号中的初始化,条件改变和条件判断是可以省略的,但条件改变和条件判断省略之后很容易导致死循环,所以建议初学者开始不要随意省略这些内容,到后期熟练运用后再根据需要调整
do...while语句
这个语句其实和while语句差不多,while语句是先判断条件是否符合再运行语句,而do...while是先运行语句再判断是否继续循环运行语句,运用如下
do {
执行语句;
} while (执行条件);
do...while语句其实在实际编程中运用的还是比较少的,大多数问题运用while和for循环语句都能够解决。
到这里其实以及把分支和循环语句介绍的差不多了,再往下其实还有一点要告诉你,这些分支和循环之间都是可以嵌套的,这样其实就大大提高了代码的灵活性
语句之间的嵌套
接下来我将用一个筛选100-200之间素数的代码来介绍嵌套
#include <stdio.h>
int main()
{
for (int i = 100; i <= 200; i++) { //初始化i将100-200每个数都枚举一遍
int flag = 1;//初始化一个flag当flag==1时表示此时i为质数
for (int j = 2; j <= i - 1; j++) {//检验i是否为质数
if (i % j == 0) {
flag = 0;//如果不是质数设置为0
break;
}
}
if (flag == 1)//华丽打印
printf("%d ", i);
}
return 0;
}
此代码不但嵌套了循环,还嵌套了分支语句,很完美的展现了语句的灵活性,大家可以自己手打或者偷偷CV一下我的代码去试试。
其实在质数判断那一块其实还可以进一步优化,想问问你是否发现在j试到根号i之前其实就已经可以把质数都筛出来了,咱们可以把i-1换成sqrt(i),这个函数的作用是将一个数字开平方,最终返回开出来的值,不过在调用此函数前别忘了头文件#include<math.h>,不然此函数是无法调用的。
关于对循环的控制语句
大家是否在前面注意到我使用了break这样的语句,其实这是一种对循环的控制语句,类似这样的语句还有continue,goto,接下来给大家分别再介绍一下
break
break在程序中运用相对来说其实比较多,当你想直接从一个循环中跳出时可以调用此语句,可以看看我刚才放在上面那个筛质数的代码,里面就用到了break,可以让其从for(int j=2;j<=i-1;j++)这个循环中直接跳出,对于while,do...while等循环运用也是如此
continue
continu在循环中的作用是直接结束当前循环进入下一次循环,可以看看以下代码
#include <stdio.h>
int main()
{
for (int i = 0; i < 10; i++) {
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
该程序运行的结果是0 1 2 3 4 6 7 8 9,是应为在当i==5时,通过continue直接跳过了后面的语句直接运行i++判断i<10后进入下一次循环,while和do...while也是同理,只不过少了i++这一项语句而已。
goto
goto是一种在程序中可以任意调整跳转的语句,看看下方代码
#include <stdio.h>
int main()
{
printf("hehe\n");
goto jump1;//此处jump1只是一个跳转标签,取什么名看你心情
printf("lala\n");
jump1:;//这里是跳转的出口
printf("haha\n");
return 0;
}
最后打印的结果如下
可以看到程序运行时直接跳过了lala,这样的跳转便是goto的一种基本用法
合理运用goto和滥用goto
最后再聊聊goto,其实在当今有许多书籍和技术人员批判goto的低逻辑性,并且容易把一个代码的思路和调理打乱,我这里的建议是goto经量避免去用,但有时候用于跳出多层循环时还是相对高效的。
想给大家展示下滥用goto产生的效果,这是我做的一道洛谷的1205题,我对这乱用goto表示抱歉,不过最后题目还是成功AC了,不多说看看源码吧
#include <stdio.h>
char primitive[11][11];
char trans[11][11];
char ultimate[11][11];
int main()
{
int n;
scanf("%d\n", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%c", &primitive[i][j]);
}
scanf("\n");
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%c", &ultimate[i][j]);
}
scanf("\n");
}
for(int i=1;i<=n;i++)
for (int j = 1; j <= n; j++) {
if (primitive[i][j] != ultimate[j][n - i + 1]) { goto end1; }
}
printf("%d", 1);
return 0;
end1:;
for(int i=1;i<=n;i++)
for (int j = 1; j <= n; j++) {
if (primitive[i][j] != ultimate[n - i + 1][n - j + 1]) { goto end2; }
}
printf("%d", 2);
return 0;
end2:;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (primitive[i][j] != ultimate[n-j+1][i]) { goto end3; }
}
printf("%d", 3);
return 0;
end3:;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (primitive[i][j] != ultimate[i][n-j+1]) { goto end4; }
}
printf("%d", 4);
return 0;
end4:;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
trans[i][j] = primitive[i][n - j + 1];
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (trans[i][j] != ultimate[j][n - i + 1]) { goto out1; }
}
goto end5;
out1:;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (trans[i][j] != ultimate[n - i + 1][n - j + 1]) { goto out2; }
}
goto end5;
out2:;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (trans[i][j] != ultimate[n - j + 1][i]) { goto out3; }
}
end5:;
printf("%d", 5);
return 0;
out3:;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (primitive[i][j] != ultimate[i][j]) { goto end6; }
}
printf("%d", 6);
return 0;
end6:;
printf("%d", 7);
return 0;
}
题目就不再这里展示了,如果感兴趣可以去洛谷搜搜看看哈。
结尾
感谢能用心看我博客的友友们,一篇博客真的太耗费心力了,整个人都要爆炸,如果这篇博客对你有帮助的话还请点个小小的赞加个收藏,是我前进的巨大动力。不多说了,写高数作业去了呜呜。。。