分支与循环

发布时间 2023-05-19 23:53:52作者: 来颗维C

在C语言中,语句可分为以下五类:
? 1. 表达式语句
? 2. 函数调用语句
? 3. 控制语句
? 4. 复合语句
? 5. 空语句

而今天我们要探讨的就是控制语句里面的分支和循环。
控制语句:控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句。可分成以下三类:
? 条件判断语句也叫分支语句:if语句、switch语句;
? 循环执行语句:do while语句、while语句、for语句;
? 转向语句:break语句、goto语句、continue语句、return语句。

一、分支语句
✒️ ✒️ 流程图:

? (1)if
? ? 1、概念
if语句:指编程语言中用来判定所给定的条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。

? ? 2、if的使用方法

? if(表达式)
语句1

? if(表达式)
语句1
else
语句2

? if(表达式)
语句1
else if(表达式)
语句2
else
语句3
(else if的数量无限制)

? ? 代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
int a = 0;

if (a==0)//表达式
{
	printf("hehe\n");//语句1
}
else if(a>0)//表达式
{
	printf("haha\n");//语句2
}
else
{
	printf("GG\n");//语句3
}

return 0;

}

注意❗️ ❗️

?(1)悬空else⬇️ ⬇️ :

//如下程序的结果是什么?

include<stdio.h>

int main()
{
int a = 1;
int b = 3;

if (a == 0)
	if (b == 3)
		printf("hehe\n");
else
	printf("haha\n");
return 0;

}

输出结果为haha,这里要注意else的就近原则,即else会和最近的if进行匹配。不良的代码风格会造成悬空else,使得程序的可读性下降,甚至造成误会。

? ? 修改后(代码⬇️ ⬇️ ):

include<stdio.h>

int main()
{
int a = 1;
int b = 3;

if (a == 0)
{
	if (b == 3)
		printf("hehe\n");
}
else
{
	printf("haha\n");
}

return 0;

}

?(2)关于判断条件⬇️ ⬇️ :

include<stdio.h>

int main()
{
int a = 1;
int b = 3;

if (0 == a)
{
	if (3 == b)
		printf("hehe\n");
}
else
{
	printf("haha\n");
}

return 0;

}

注意❗️ ❗️

一般我们将常量写在等式的左边,当我们因为疏漏把”==“写成了”=“时,程序会报错(因为变量不能进行赋值)。但是当我们将常量写在等式的右端时,程序不一定会报错,将常量赋值给变量在计算机看来是没有问题的。

? (2)switch
? ? 1、概念(+关键字)
switch是一种分支语句,常用于多分支的情况。
关键字:case、break、default、switch

? ? 2、用法

? (1)switch
switch(整形表达式)
{
语句项;
}

? (2)case
语句项的内容:
case 整形常量表达式:
语句:

? (3)break
switch中的break,能帮助我们实现真正的分支。switch语句执行时会从上到下根据括号中表达式的值作比较,当某个case语句中的表达式与此值相同时,就执行这个case语句或语句序列,直到遇到break为止。 break语句是必须有的,它用来结束switch语句的执行。

? (4)default
当所有case语句后面的表达式都不等于switch语句项中case后面整型常量表达式的值,就执行default后面的默认语句序列。不过,default部分是可选的。如果没有这一部分,并遇到所有case语句都不匹配,那么,就不作任何处理而进入后续程序段的执行。

? ? 例如判断星期几,代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
int day = 1;

switch (day)
{
case 1:
	printf("Monday\n");
	break;
case 2:
	printf("Tuesday\n");
	break;
case 3:
	printf("Wednesday\n");
	break;
case 4:
	printf("Thursday\n");
	break;
case 5:
	printf("Friday\n");
	break;
case 6:
	printf("Saturday\n");
	break;
case 7:
	printf("Sunday\n");
	break;
default:
	break;
}

return 0;

}

注意❗️ ❗️ (default)

✏️ 写在任何一个 case 标签可以出现的位置。
✏️ 当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
✏️ 所以,每个switch语句中只能出现一条default子句。
✏️ 但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。

二、循环语句
✒️ ✒️ 流程图:

? (1)while
? ? 概念
while是计算机的一种基本循环模式。当满足条件时进入循环,进入循环后,当条件不满足时,跳出循环。while语句的一般表达式为:****while(表达式){循环体}。

? ? 代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
int a = 0;

while (a < 10)
{
	//语句内容
	a++;
	printf("%d\t", a);
}

return 0;

}

? (2)for
? ? 1、概念
for循环:编程语言中一种循环语句,而循环语句由循环体及循环的判定条件两部分组成。

? ? 2、用法

? for(表达式1; 表达式2; 表达式3)
循环语句;
表达式1:
表达式1为初始化部分,用于初始化循环变量的。
表达式2:
表达式2为条件判断部分,用于判断循环时候终止。
表达式3:
表达式3为调整部分,用于循环条件的调整。

? ? 代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
//i可以定义在外面
for (int i = 0; i < 10; i++)
{
printf("%d\t", i);
}

return 0;

}

? ? 3、for循环变种:

? (1)三个表达式都可以省略(初学时不建议省略)⬇️ ⬇️

include<stdio.h>

int main()
{
int i = 0;

for (;;)
{
	//死循环
	printf("hehe\t");
}

return 0;

}

? (2)双重循环(用while也可以实现)⬇️ ⬇️

include<stdio.h>

int main()
{
for (int i = 0; i < 10; i++)
{

	for (int j = 0; j < 10; j++)
	{
		printf("hehe\t");
	}
	
	printf("\n");
	
}
return 0;

}

? (3)表达式里面的内容可以不止一条⬇️ ⬇️

include<stdio.h>

int main()
{
int i = 0;
int j = 0;

for (i = 0, j = 0; i < 10 && j < 10; i++, j++)
{
	printf("hehe\t");
}

return 0;

}

建议:
? 1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
? 2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
⬇️ ⬇️ :

for (int i = 0; i < 10; i++)
{}

for (int i = 0; i <= 9; i++)
{}

? (3)do while
? ? 概念
do…while 循环: while 循环的变体。在检查while()条件是否为真之前,该循环首先会执行一次do{}之内的语句,然后在while()内检查条件是否为真,如果条件为真的话,就会重复do…while这个循环,直至while()为假。

? ? 代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
int a = 0;

do 
{
	printf("%d\t", a);
	a++;
} while (a < 10);

return 0;

}

总结:
? 1、区别while和for。

? ?代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
int i = 0;

while (i++ < 10)
{
	printf("hehe\t");
}
printf("\n");

for (int j = 0; j < 10; j++)
{
	printf("hehe\t");
}
printf("\n");

return 0;

}

可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

? ? 代码⬇️ ⬇️ :

include<stdio.h>

int main()
{
int i = 0;

while (i++ < 10)
{
	printf("%d\t",i);
}
printf("\n");
//输出结果1、2、3、4、5、6、7、8、9、10
for (int j = 0; j < 10; j++)
{
	printf("%d\t", j);
}
printf("\n");
//输出结果0、1、2、3、4、5、6、7、8、9
return 0;

}

注意❗️ ❗️
while和for里面的自增(自减)不同,while里面的自增(自减)会在判断过后就进行,而for里面的会在本次循环结束后再进行。(曾跌进这个坑里)⬇️ ⬇️

? 2、区别continue、break、return

continue结束的是本次循环,break结束的是本层循环,而return可以跳出所有循环。

? ? 代码⬇️ ⬇️:

//下面程序的运行结果是什么?

include<stdio.h>

int main()
{
int i = 0;

while (i<10)
{
	if (5 == i)
	{
		continue;
	}
	printf("%d\t", i);
	i++;
}
//结果为0、1、2、3、4后面死循环
return 0;

}

结果为1、2、3、4后面死循环,因为i==5时会进入判断语句,continue跳出,下面的打印和自增都不会进行,所以i等于5后一直死循环。

? ? 代码⬇️ ⬇️ :

//下面程序的运行结果是什么?

include<stdio.h>

int main()
{
int i = 0;

while (i<10)
{
	if (5 == i)
	{
		break;
	}
	printf("%d\t", i);
	i++;
}
//结果为0、1、2、3、4
return 0;

}

结果为0、1、2、3、4,当i==5时进入判断,break直接跳出这个循环。当在双层循环的内层循环里面使用break时,会跳出里面那层循环。

注意❗️ ❗️
break、continue用于循环语句,但break还可以用于分支语句的switch。

三、goto语句
? ? 概念
goto语句:也可以称为无条件转移语句,其一般格式如:goto 语句标号; 其中语句标号是按标识符规定书写的符号, 放在某一语句行的前面,标号后加半角冒号“:”。语句标号起标识语句的作用,与 goto 语句配合使用。

? ? ⬇️ ⬇️ :

for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}

error:
if(disaster)
// 处理错误情况

✏️ C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
✏️ 从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
✏️ 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。 例如:一次跳出两层或多层循环。
✏️ 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。

? ? 代码(关机程序)⬇️ ⬇️ :

include <stdio.h>

int main()
{
char input[10] = {0};
system("shutdown -s -t 60");
again:
printf("电脑将在1分钟内关机,如果输入:
我是猪,就取消关机!\n请输入:>");
scanf("%s", input);
if(0 == strcmp(input, "我是猪"))
{
system("shutdown -a");
}
else
{
goto again;
}
return 0; }

? ? 不使用goto,使用循环⬇️ ⬇️ :

include <stdio.h>

include <stdlib.h>

int main()
{
char input[10] = {0};
system("shutdown -s -t 60");
while(1)
{
printf("电脑将在1分钟内关机,如果输入:
我是猪,就取消关机!\n请输入:>");
scanf("%s", input);
if(0 == strcmp(input, "我是猪"))
{
system("shutdown -a");
break;
}
}
return 0; }