循环结构
什么是循环
代码的重复执行,就叫做循环。
循环的分类
- 无限循环:程序设计中尽量避免无限循环,其实就是死循环。程序中的无限循环必须是可控的。
- 有限循环:循环限定循环次数或者循环的条件。
循环的构成:
- 循环条件
- 循环体
当型循环的实现
特点:先判断,后执行,如果条件不满足,一次都不执行
代表:while和for
while
语法:
while (循环
{
循环语句
})
说明:
- 循环条件的返回值必须是布尔类型(条件表达式之能是关系表达式或逻辑关系,还可以是具体的值(0,非0,true,false)在C语言中,布尔类型为真使用非0,布尔类型为假使用0/如果引入
#include <stdio.h>
,也可以用true和false表示。 - {}包起来的内容整体称之为
循环体
- 我们要在
循环体
中控制循环条件
的变化,否则会产生死循环。
执行过程:
特点:先判断,后执行,循环体语句有可能一次都不执行。
案例:
#include <stdio.h>
/**
*需求:while循环案例:如何让编程来计算1+2+3+..+100?(累加求和)
*\
int main(int argc,char *argv[])
{
// 定义一个变量,用来保存累加的和
int sum = 0;
// 定义一个循环变量
int i = 1;
while(i <= 100)// 循环条件,这里可以有关系表达式、逻辑表达式、整型常量(非0)
{
// 累加运算
// sum = sum + i;
sum += i;
// 给循环变量赋值,用来影响循环条件
i++;
}
printf("1~100的累加和是:%d\n",sum);
return 0;
}
死循环
while(1) // 我们会在死循环进行必要的控制
for
原则上,,for循环能实现,while循环一定也可以实现,for循环可以看作是while循环的一种特殊写法。
语法:
for(①表达式1;②表达式2;③表达式3)
{
④循环语句; -- 如果是单语句,可以省略{};如果是复合语句,必须保留{}
}
说明:
()
中可以只保留两个;;
,举例:(;;)
- ①(表达式1)是循环变量,我们需要赋初值,循环变量可以是列表,多个循环变量使用逗号分割,举例:
int i = 0,j = 0
- ②(表达式2)是循环条件,用来限制循环的次数,循环条件支持关系表达式,如果加入逻辑表达式,会变成符合表达式,举例:
i < 10 && j <= i
- ③(表达式3)改变循环条件,支持列表,这里可以使用赋值表达式,举例:
i++,j++
- 执行顺序:①②④③ → ②④③ → ②④③ → … → ②
执行过程:
特点:
先判断,后执行,循环体语句有可能一次都不执行。
案例:
#include <stdio.h>
/**
*需求:while循环案例:如何让编程来计算2+4+6+..+100?(偶数累加求和)
*\
int for_test2()
{
// 定义一个变量,用来保存累加的和
int sum = 0;
// 定义一个循环变量
int i = 1;
for(;i <= 100;)// 循环条件,这里可以有关系表达式、逻辑表达式、整型常量(非0)
{
if(i % 2 == 0)
{
sum += i;
}
i++;
}
printf("1~100的累加和是:%d\n",sum);
}
int main(int argc,char *argv[])
{
for_test2();
return 0;
}
#include <stdio.h>
#include <math.h>
int main (int argc,char *argv)
{
// 需求:for循环案例-用户可以通过键盘输入一个整数n,用来作为阶乘的最高位
// 创建一个变量,用来接收控制台输入一个整数,作为阶乘的位数
int n;
int r = 1;
printf("请输入一个整数:\n");
scanf("%d",&n);
for(int i = 1;i <= fabs(n);i++)
{
// r = r * i;
r *= i;
}
printf("1~%d之间的阶乘的结果是%d\n",(int)fabs(n),r);
return 0;
}
总结
- for语句使用语法规则上,降低/避免因为忘记循环条件更新操作,而引起的产生无限循环的几率。
- 应用场合:for语句往往应用于循环次数事先可以确定的场景
死循环
for(表达式1;;表达式3)
for(;;);
循环实现的三要素:
- 循环变量的初始化
- 循环条件
- 循环变量的更新
案例:
/**
* 需求:for循环案例-求斐波拉契数列前20个数
* 分析:1,1,2,3,5,8...
*/
int main(int argc,char *argv[])
{
int f1 = 1;前一个数,默认是1,因为第一个是1
int f2 = 1;
int i =1;// 循环变量
for(;i <= 10;i++)
{
printf("%12d%12d\n",f1,f2);
//if(i % 2 == 0)
//{
// printf("\n");
//}
f1 += f2;
f2 += f1;
}
}
直到型循环的实现
特点:先执行,后判断,不管条件满不满足,至少执行一次。
代表:do…while
do…while
语法:
do
{
循环体;
} while(循环条件);
说明:
- 循环条件的返回值必须是布尔类型,在C语言中,布尔类型为真使用
非0
来表示,为假使用0
来表示 {}
包起来的内容整体称之为循环体
- 我们要在
循环体
中控制循环条件
的变化,否则就会产生死循环
执行过程:
特点:先执行,后判断,不管条件满不满足,循环体语句至少执行一次。
案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建一个变量,用来存储累加的和
int sum = 0;
// 创建一个循环变量,默认值是1
int i = 1;
do
{
if(i % 2 != 0)
{
sum +=i;
}
// 改变循环变量,防止死循环
i++;
} while(i <= 100)
printf("1~100之间的奇数和是:%d\n",sum);
return 0;
}
循环的嵌套
3中循环(while、do…while、for)可以互相嵌套。在前一个循环结构的内部又存在一个完整的循环机构。如:
#include <stdio.h>
int main(int argc, char *argv[])
{
// 创建一个变量,存放100~200之间的自然数
int num = 100;
// 循环变量,默认从2开始,因为子认输数以
int i = 2;
// 定制标志位:用来表示1~自身之间的能整除的次数,用来校验该自然数是否为素数
int is_flag = 1;
for (; num <= 200; num++)
{
// 每个自然数在判别之前需要重置标志位
is_flag = 1;
// 第二层for循环验证该自然数能否被除了1~自身之间的数整除,能整除就改变is_flag的值
for (i = 2; i < num - 1; i++)
{
// 校验是否能整除
if (num % i == 0)
{
is_flag = 0;
break;// 只校验第一个能整除的数
}
}
// 根据标志位,判断该自然数是否是素数
if (is_flag) // 条件判断:is_flag == 1 缩写 is_flag(推荐)
{
printf("%-4d", num);
}
}
printf("\n");
return 0;
}
循环结构的典型应用场景
-
求累和:举例
1+2+3+..+100的和
-
求累乘:举例
1*2*3*..*100的乘积
-
求均值:举例
(1+2+3+..+100)/100的值
-
求极值:举例
12,34,56,67中的最大值或最小值
-
元素遍历:常用于数组元素的遍历
-
…
基础算法模型
- 累加和
- 定义一个变量(sum),并赋初值为0;
- 该变量累加(+=),每一个数据项(i);
- 当访问完每一个数据项,此时该变量的取值就是累加和的结果。
- 累乘积
- 定义一个变量,并赋初值为1;
- 用该变量累乘(*=),每一个数据项;
- 当访问完每一个数据项,此时改变量的取值就是累乘的结果。
- 极值(多应用于数组)
- 定义一个变量,并赋初值为第一个数据项;
- 从第二个数据项开始依次与改变了进行比较,如果大于/小于该变量,则将当前数据项的数据赋值给该变量;
- 当访问完每一个数据项,此时该变量的取值就是求极值的结果。
break和continue
- break
功能:
①用在switch中,用来跳出switch的case语句;如果case没有break,可能会产生case穿透。
②用在循环中(while、do…while、for),提前结束循环,也就是跳出整个循环。
说明:
①break不能用于循环语句和switch语句之外的任何语句之中。
②break只能终止并跳出最近一层的循环结构。
for(){
for(){
for(){
break;//只会跳出当前循环
}
}
}
图示:
案例:
#include <stdio.h>
/**
* 需求:break案例-输出1~100以内的偶数,只能输出前10个
*/
int break_test()
{
for (int i = 1, count = 1; i <= 100; i++)
{
if (i % 2 == 0)
{
if (count > 10)
{
break;
}
count++; // 用来计数,循环次数
printf("%d\t", i);
//printf("%d\n", i);
}
}
printf("\n");
}
int main(int argc, char *argv)
{
break_test();
return 0;
}
- continue
功能:continue语句不会结束整个循环,而是跳出本次循环尚未执行的语句,进入下一次循环
说明:
①仅用于循环语句中
②在嵌套循环的情况下,continue语句只对包含他的最近的一层循环起作用
图示:
案例:
#include <stdio.h>
/**
* continue案例:1~100以内的偶数和
*/
int continue_test()
{
int sum = 0;
for (int i = 1; i <= 100; i++)
{
if (i % 2 != 0)
{
continue;
}
sum += i;
}
printf("1~100以内的偶数和是%d\n",sum);
}
int main()
{
continue_test();
return 0;
}
- 跳出多层循环
跳出多层循环是不能直接使用break和continue实现的,因为它们只能跳出单层循环,跳出多层循环,需要我们自定义标志位跳出(标志位也可以配合break跳出使用)。
案例:
#include <stdio.h>
int fun0()
{
// 定义一个标志位
int is_flag = 1; // 默认循环成立
// 定义一个变量,用来接收控制台输入
char fu;
// 循环
while (is_flag)
{
printf("外层循环执行的内容..\n");
while (is_flag)
{
printf("内存循环执行的内容..\n");
scanf("%c", &fu);
if (fu == 'Y' || fu == 'y')
{
is_flag = 0;
}
}
}
}
int fun1()
{
// 定义一个标志位
int is_flag = 1; // 默认循环成立
// 定义一个变量,用来接收控制台输入
char fu;
// 循环
while (is_flag)
{
printf("外层循环执行的内容..\n");
while (is_flag)
{
printf("内存循环执行的内容..\n");
scanf("%c", &fu);
if (fu == 'Y' || fu == 'y')
{
is_flag = 0;
break;
}
}
}
}
int main()
{
fun0();
fun1();
return 0;
}
注意:如果是多层循环(嵌套循环),==进的时候是从外到内,跳出的时候是从内到外==。