选择、循环结构
最简单的结构是
if-else
(类比日常生活中 如果…否则…)
其次,
switch,
最后是三大循环结构,
while
do-while
for
选择、循环结构是后续学习的基石,
尤其是与数组和指针
关联性很强
一、选择结构
if语句
1. if单分支语法结构
if (表达式){
语句;
}
举例:
int a = 10;
int b = 20;
if (a < b) {
printf("a is less than b.\n");
}
2. if双分支语法结构
if (表达式){
语句1;
}
else{
语句2;
}
举例:
int score = 75;
if (score > 70) {
printf("Pass\n");
} else {
printf("Fail\n");
}
- 最好加代码块{ },若不加代码块则默认只执行if语句后面一条语句
- else与它最近的if相匹配
- 其中表达式:
- A) 必须是逻辑表达式
- B) 必须是关系表达式
- C) 必须是逻辑表达式或关系表达式
- D) 可以是任意合法的表达式`
解释:if
语句中的“表达式”可以是任意合法的表达式,
意味着它可以是逻辑表达式、关系表达式,
或者是任何其他能够产生一个
可以被解释为布尔值(真或假)的表达式。
在计算时,
如果结果为非零值(真),
则会执行if
语句中的代码块;
如果结果为零(假),
则跳过if
语句中的代码块。
以下是一些合法的if
语句中的“表达式”:
- 逻辑表达式:
if(a && b)
- 关系表达式:
if(a > b)
- 算术表达式:
if(a + b)
- 单值表达式:
if(a)
(这里a
可以是任何值,如果a
非零,则为真)
C语言中,
任何非零值都被视为真,
而零值被视为假。
因此,
if
语句中的表达式可以非常灵活,
不仅限于逻辑或关系表达式。
3. if多分支语法结构
if (表达式1)
{ 语句 1 ; }
else if (表达式2)
{ 语句 2 ; }
else if (表达式3)
{ 语句3 ; }
else
{ 语句4 ; }
举例1:成绩分类
int score = 85;
if (score >= 90) {
printf("A\n");
} else if (score >= 80) {
printf("B\n");
} else if (score >= 70) {
printf("C\n");
} else {
printf("D or F\n");
}
举例2:检查年龄范围
int age = 25;
if (age < 13) {
printf("Child\n");
} else if (age < 20) {
printf("Teenager\n");
} else if (age < 65) {
printf("Adult\n");
} else {
printf("Senior Citizen\n");
}
举例3:判断闰年
int year = 2024;
if (year % 4 != 0) {
printf("%d is not a leap year.\n", year);
} else if (year % 100 != 0) {
printf("%d is a leap year.\n", year);
} else if (year % 400 != 0) {
printf("%d is not a leap year.\n", year);
} else {
printf("%d is a leap year.\n", year);
}
举例4:温度范围
float temperature = 36.5;
if (temperature < 35.0) {
printf("Below normal body temperature.\n");
} else if (temperature < 37.5) {
printf("Normal body temperature.\n");
} else if (temperature < 38.5) {
printf("Above normal body temperature.\n");
} else {
printf("Fever detected.\n");
}
举例5:用户输入验证
char input;
printf("Enter 'A' for apple or 'B' for banana: ");
scanf(" %c", &input); // 注意前面的空格,用于消耗前面的换行符
if (input == 'A') {
printf("Chosen: Apple\n");
} else if (input == 'B') {
printf("Chosen: Banana\n");
} else {
printf("Invalid input.\n");
}
举例6:检查文件状态
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
} else if (fscanf(file, "%d", &number) != 1) {
fprintf(stderr, "Error reading number from file.\n");
} else {
printf("Number read from file: %d\n", number);
}
fclose(file);
- 如果 表达式 的结果为真,则语句执行。
- 0表示假
- 非0表示真
switch(多分支语句)语法结构:
常应用于多分支的情况
switch语法结构:
switch (整型表达式)
{
case 整形常量表达式 :
语句1 ;
break ;
case 整形常量表达式 :
语句2 ;
break ;
default :
语句n;
break ;
}
举例1:
int month = 3;
switch (month) {
case 1:
printf("January\n");
break;
case 2:
printf("February\n");
break;
default:
printf("Not a valid month\n");
break;
}
举例2:switch
语句处理数值范围
int score = 85;
switch (score / 10) {
case 9:
case 10:
printf("A\n");
break;
case 8:
printf("B\n");
break;
case 7:
printf("C\n");
break;
case 6:
printf("D\n");
break;
default:
printf("F\n");
break;
}
- 若不加break,则会向下执行后面的语句,直到遇见break
- 每个 switch 语句中只能出现 一条 default 子句。 但是它可以出现在语句列表的任何位置
嵌套语句
switch语句和if-else语句都可以嵌套使用
- if-else嵌套语法结构
if (表达式)
{
if (表达式)
{
语句;
}
else if (表达式)
{
语句;
}
else
{
语句;
}
}
else
{
语句;
}
if (表达式) {
if (表达式)
{
语句;
}
else
{
语句;
}
举例:
#include <stdio.h>
int main() {
int x = 10;
int y = 5;
// 外层if-else结构
if (x > y) {
// x大于y的情况
if (x > 10) {
// x不仅大于y,还大于10
printf("x is greater than y and also greater than 10.\n");
} else {
// x大于y,但不大于10
printf("x is greater than y but not greater than 10.\n");
}
} else {
// x不大于y的情况
printf("x is not greater than y.\n");
}
// 另一个独立的if-else结构
if (y < 10) {
// y小于10
printf("y is less than 10.\n");
} else {
// y不小于10
printf("y is not less than 10.\n");
}
return 0;
}
说明:
首先检查变量x
是否大于变量y
。
如果是,进一步检查x
是否还大于10。
根据这些条件,
打印出相应的消息。
如果x
不大于y
,
打印出x
不大于y
的消息。
然后,
用一个独立的if-else
结构
来检查变量y
是否小于10,
并打印相应的消息。
请注意,
第二个if-else
结构是独立的,
它不属于第一个if-else
结构的内层。
如果需要将第二个if-else
结构作为第一个结构的内层,
你需要将它放在第一个if-else
结构的花括号内部。
但第二个if-else
结构是与第一个并列的,
而不是嵌套的。
- switch嵌套语法结构
switch (整形表达式)
{
case 整形常量表达式:
语句;
break;
case ?:
语句;
switch (整形表达式)
{
case 整形常量表达式:
语句;
break;
default:
语句;
break;
}
break;
default:
break;
}
举例:
#include <stdio.h>
int main() {
int month = 3;
int day = 14;
switch (month) {
case 1:
case 2:
case 11:
case 12:
printf("These months have 31 days.\n");
break;
case 4:
case 6:
case 9:
case 11:
printf("These months have 30 days.\n");
break;
case 3:
case 5:
case 7:
case 8:
printf("Switching to another switch for February.\n");
// 开始嵌套的 switch 语句
switch (day) {
case 14:
printf("Valentine's Day is on February 14th.\n");
break;
case 29:
printf("Leap year detected!\n");
break;
default:
printf("February has 28 or 29 days.\n");
break;
}
break;
default:
printf("Invalid month.\n");
break;
}
return 0;
}
说明:在这个例子中,外层的 switch
语句根据 month
变量的值来决定执行哪个 case
。
当 month
为 3(即三月)时,程序会打印一条消息,然后进入内层的 switch
语句。
内层的 switch
语句根据 day
变量的值来决定执行哪个 case
。
例如,如果 day
为 14,程序会打印情人节的消息。
请注意,内层 switch
语句的 default
部分是可选的,就像外层 switch
语句的 default
部分一样。
如果某个 case
匹配成功,执行完相应的语句后,break
语句会跳出当前的 switch
结构。
如果没有找到匹配的 case
,并且没有 default
部分,
程序会继续执行下一个 switch
结构中的代码,直到遇到 break
语句或者到达 switch
结构的末尾。
二、三大循环语句
(1)while语句
while 语句的语法结构和 if 语句⾮常相似。
注意:
结构中会包含三大要素:初值、条件、增量
while(表达式)
{
语句;
}
在这个结构中,
while通过判断表达式的真假来执行语句,
这里的语句就是循环体,
循环体呢可以是一个语句,
也可以是复合语句({}括起来的语句),
执行循环体的次数是由循环条件控制的,
这个循环条件就是表达式,
它也称为循环条件表达式,
当值为非0就执行循环体,
当值为0就不执行循环体。
while语句特点,
先判断表达式,
再执行循环体语句。
while语句可简单记为:
只要循环条件表达式为真,
就执行循环体语句。
- 举例:求1+2+3+…+100的和
#include<stdio.h>
int main()
{
int i = 1,sum = 0; //初值
while(i<=100) //条件
{
sum += i;
i++; //增量
}
printf("%d",sum);
return 0;
}
说明:
(1)如果循环体是复合语句要用花括号括起来,
如果没有花括号则和if语句配对类似,
都只选择最近的一个语句为循环体语句。
(2)while先判断i是否小于等于100,
如果是则执行sum+=i,i++,
如果不是则执行printf语句。
(3)不要忽略给i或者sum赋值,
如果不赋值则系统会自动赋值,
从而导致程序结果错乱。
(4)在循环体中最好有一个让循环趋于结束的语句,
否则循环会进入死循环,
死循环就是无限执行循环体 ,
在该例子中循环体用了i++让循环表达式有一个判断真假的情况。
- if和while的类比
#include <stdio.h>
int main()
{
if(1)
printf("hello world\n"); //if后边条件满⾜,打印⼀次hello world
return 0;
}
include <stdio.h>
int main()
{
while(1)
printf("hello world\n"); //while后边的条件满⾜,死循环的打印hello world
return 0;
}
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
while(n)
{
printf("%d ", n%10);
n / = 10;
}
return 0;
}
程序分析:该程序主要考察%和/的用法,
如果想得到一个整数的最低为就让它%10,
如果想去掉它就用/10。
(2)do…while语句
do
{
语句;
}
while(表达式);
在 do while 循环中先执⾏“语句”,执⾏完语句,在去执⾏“判断表达式”,判断表达式的 结果是!=0,则继续循环,执⾏循环语句;判断表达式的结果为0,则循环结束。 所以在 do while 语句中循环体是⾄少执⾏⼀次的,这是 do while 循环⽐较特殊的地⽅。
do…while语句的特点:先无条件执行循环体,然后判断循环条件是否成立。
- 举例:求1+2+3+…+100的和
#include<stdio.h>
int main()
{
int i = 1, sum = 0;
do
{
sum += i;
i++;
} while (i <= 100);
printf("%d", sum);
return 0;
}
我们可以看到两个程序无论是while和do…while的结果都一样,但二者存在一定区别。其次do…while中while后有个分号不能遗漏了**
(3)for语句
for语句的形式如下
for(表达式1(初值):表达式2(条件):表达式3(增量)
{
语句;
}
//但其实它和while语句等价
表达式1;
while(表达式2)
{
语句;
表达式3;
}
先求解表达式1然后到表达式2判断条件,为真就执行语句,然后到表达式3,然后继续执行表达式1,接着判断表达式2,要是假直接出循环。
for循环注意的点:
-
(1)表达式1可以省略但后面的分号不能省略,例如:for(;i<=100;i++)
-
(2)表达式2如果省略即认为该循环为死循环
(4)循环的嵌套
到这里,你已经知道了上述三种循环 while , do while , for ,这三种循环往往会嵌套在⼀起才能更好的解决问题
举例:求100~200的素数
#include<stdio.h>
#include<math.h> //数学库,用于后面的开方运算
int main() //程序入口
{
int n = 0, k = 0, i = 0, m = 0; //定义变量
//这个循环从101开始,逐个检查每个奇数,直到200。每次循环`n`增加2,确保只检查奇数
for (n = 101; n <= 200; n += 2)
{
k = sqrt(n); //使用`math.h`库中的`sqrt`函数计算当前奇数`n`的平方根,存储在变量`k`中
for (i = 2; i <= k; i++)
{
if (n % i == 0)
break;
}
if (i >= k + 1)
{
printf("%d\t", n);
}
m = m + 1;
if (m % 10 == 0)
printf("\n");
}
printf("\n");
return 0;
}
说明:
- 定义了四个整型变量,分别用于:
- n:存储当前检查的奇数。
- k:存储
n
的平方根。 - i:用于内层循环,检查
n
是否有除了1和它自身之外的因数。 - m:用于计数,每打印10个素数就换行。
-
内层循环:
for (i = 2; i <= k; i++)
这个循环从2开始,检查
n
是否有除了1和它自身之外的因数。如果n
不是素数,那么它必定有一个因数不大于它的平方根。 -
检查因数:
if (n % i == 0)
如果
n
能被i
整除(即余数为0),则n
不是素数,内层循环通过break
语句提前结束。 -
判断素数:
if (i >= k + 1)
如果内层循环正常结束(即没有找到因数),则
i
的值会大于k
(k
的值是n
的平方根),这时n
是一个素数。 -
打印素数:
printf("%d\t", n);
如果
n
是素数,就打印出来,后面跟一个制表符(\t
)用于分隔。 -
计数并换行:
m = m + 1; if (m % 10 == 0) printf("\n");
每打印一个素数,
m
就加1。当m
是10的倍数时,意味着已经打印了10个素数,此时打印一个换行符,以便下一行继续打印。
整个程序通过两层循环嵌套,外层循环控制检查的数,内层循环用于判断这个数是否为素数。如果一个数是素数,它将被打印出来,每打印10个素数,输出会自动换行,以便于阅读。
循环注意的点:
1.在while和do…while循环中,只在while后面的括号内指定循环条件,为了使循环结束,应在循环体中包含能使循环结束的语句。而在for循环中应该在表达式3中包含。
2.用while和do…while循环时,循环变量的初始化应该在while或者do…while语句之前,而for循环可以在表达式1,但还是最好要在for语句之前。
三、循环结构中break和continue语句的使用
在循环执⾏的过程中,如果某些状况发⽣的时候,需要提前终⽌循环,这是⾮常常用的操作。这时候我们会使用 break 和 continue 两个关键字,下面来介绍它们的作用
break语句的介绍
break语句不仅可以流程跳出switch结构,继续执行switch语句后的内容,还可以让流程跳出循环体,即提前跳出循环体。
switch(整形表达式)
{
case 整型常量表达式:
break;
}
while()
{
语句;
break;
}
for()
{
语句;
break;
}
break语句的一般形式就是break;它的作用就是让流程跳出循环体之外,结束本次循环。
while语句中的break
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
break;
printf("%d", i);
i++;
}
return 0;
}
说明:
这段代码将打印从1到4的整数,当i
等于5时,break
语句将终止循环,因此数字5不会被打印。程序随后结束,返回值为0。
举例:使用while
循环和计数器来控制重复执行的次数
#include <stdio.h>
int main() {
int count = 0; // 初始化计数器
while (count < 5) { // 当计数器小于5时循环继续
printf("Hello, World!\n"); // 打印 "Hello, World!" 和换行符
count++; // 每次循环后计数器递增
}
return 0; // 程序结束,返回0
}
最后,我们可以得到结论,如果遇到break语句,这个循环体就不执行啦,这个循环也结束了,
那如果是continue呢?
while语句中的continue
#include<stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
continue;
printf("%d", i);
i++;
}
return 0;
}
奇怪的是这次没有出现按任意键继续了,为什么呢?
因为这里是进入了死循环,当i=5的时候,后面i++语句没有执行,然后返回循环,接着判断,然后又不执行i++语句,就相当于当i=5的时候,循环结束的条件就不存在了,所以一直循环。
可以对比上面的代码:
int main()
{
int i=1;
while (i <= 10)
{
i++;
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
至此break和continue的区别在while中你应该非常清楚啦,那么基于此,在for循环中又会出现什么新花样呢?
for循环里的break语句
#include<stdio.h>
int main()
{
int i=1;
for(i=1;i<=10;i++)
{
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
结果和while中没有太大区别,一遇到break,循环就结束了。
for循环中的continue语句
#include<stdio.h>
int main()
{
int i=1;
for(i=1;i<=10;i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
那么虽然continue不执行后面的printf代码了,但是仍然执行i++语句,也就是说for和while最大的区别就在于此,continue不会影响for()中的表达式。
在do…while中的break
int main()
{
int i=1;
while (i <= 10)
{
i++;
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
在do…while语句中,循环会先执行一次然后判断条件,所以第一次就先打印了2,最后5打印完的时候,执行到break语句循环就结束了
do…while语句中的continue
#include<stdio.h>
int main()
{
int i = 1;
do
{
if (i == 5)
continue;
i++;
printf("%d ", i);
} while (i<=10);
return 0;
}
思考:上面的代码是否会陷入死循环?
最后来总结一下
-
break 的作⽤是⽤于永久的终⽌循环,只要 break 被执⾏,直接就会跳出循环,继续往后执⾏。一句话:结束本次循环
-
continue 的作⽤是跳过本次循环 continue 后边的代码,在 for 循环和 while 循环中有所差异的。一句话:结束当前循环