大家好,今天带大家认识C语言中的循环与分支语句 (编译器:VS2019)
——————————————————————————
一. 前言:什么是语句?
C语句可分为以下五类:
- 表达式语句
- 函数调用语句
- 控制语句
- 复合语句
- 空语句
博主这次将根大家分享的是我们的控制语句 控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句。 可分成以下三类:
- 条件判断语句也叫分支语句:if语句、switch语句;
- 循环执行语句:do while语句、while语句、for语句;
- 转向语句:break语句、goto语句、continue语句、return语句。
二.分支语句(选择结构)
2.1 if语句
if语句的结构
1.if(表达式)
语句;
2.if(表达式)
语句1;
else
语句2;
3.
if(表达式1)
语句1;
else if(表达式2)
语句2;
else
语句3;
举例
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if(age<18)
{
printf("未成年\n");
}
}
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if(age<18)
{
printf("未成年\n");
}
else
{
printf("成年\n");
}
}
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if(age<=18)
{
printf("少年\n");
}
else if(age>=18 && age<30)
{
printf("青年\n");
}
else if(age>=30 && age<50)
{
printf("中年\n");
}
else if(age>=50 && age<80)
{
printf("老年\n");
}
else if(age>=80 && age<100)
{
printf("老寿星\n");
}
else if(age>=100)
{
printf("仙人\n");
}
当条件成立,需要执行多条语句时,需要将这些语句放在代码块里 (一个{}就是一个代码块)
2.1.1 悬空else
我们来看一下这个代码的运行结果会是什么呢?
#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;
}
可能你会这么想:判断第一个if语句中的表达式为假,所以不会进入第二个if语句直接跳到else语句中打印haha。即最终的运行结果会在屏幕上打印haha。
但实际的运行却是 什么都没有
这是因为else的匹配符合一个原则:else语句是和它离的最近的if匹配的 所以在判断第一个if语句中的表达式为假后,直接return 0;因此什么也没有打印
更改后
#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;
}
更改后我们就能很明显的看出运行结果,这也同样提醒我们在打代码时要注意格式风格,避免出现类似的情况让自己混淆不清。
2.2 switch语句
switch语句也是一种分支语句。 常常用于多分支的情况。 如果我们想打印 输入1,输出星期一 输入2,输出星期二 输入3,输出星期三 输入4,输出星期四 输入5,输出星期五 输入6,输出星期六 输入7,输出星期日 而使用if…else if…else if…else…的形式会非常复杂麻烦。 这个时候我们就可以使用switch语句。
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:printf("今天是星期一\n"); break;
case 2:printf("今天是星期二\n"); break;
case 3:printf("今天是星期三\n"); break;
case 4:printf("今天是星期四\n"); break;
case 5:printf("今天是星期五\n"); break;
case 6:printf("今天是星期六\n"); break;
case 7:printf("今天是星期日\n"); break;
}
return 0;
}
结合上面的例子我们可以更好理解switch语句的语法形式。
switch(整型表达式)
{
语句项;
}
而语句项又是什么呢?
//是一些case语句:
//如下:
case 整形常量表达式:
语句;
而整形常量表达式又是啥子嘞?
整形常量表达式指的是表达式中的操作数都是整数类型的, 这里的整数类型不仅仅是int类型, 还包括char, (unsigned) short, (unsigned) long等类型. 整型常量表达式中的操作数在编译时就已经确定了他的值。
因此只需要关注哪些值在编译时确定就可以了. 这包括以下几种情况:
- 单个字符, 比如’A’, ‘a’
- 单个整数数字以及由整数数字构成的表达式, 如123, 123 + 345
- 枚举常量
- 有sizeof 运算法返回的值, 如sizeof(int)
- NULL指针值
- 地址常量. 如0X12345678, 以及地址常量加上一个偏移
2.2.1 switch语句中的break
在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。 以刚刚输出星期几的代码举例:
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:printf("今天是星期一\n");
case 2:printf("今天是星期二\n");
case 3:printf("今天是星期三\n");
case 4:printf("今天是星期四\n");
case 5:printf("今天是星期五\n");
case 6:printf("今天是星期六\n");
case 7:printf("今天是星期日\n");
}
return 0;
}
没有break语句后,输入1后输出的结果是星期一到星期日,与我们期望的星期一并不相同,这就是break语句的作用。 break语句的实际效果是把语句列表划分为不同的分支部分 (在完成对应分支后遇到break才会停止)
2.2.2 default子句
当我们输入的值与所有的case标签的值都不匹配怎么办?
其实也没什么,结果就是所有的语句都被跳过而已。 程序并不会终止,也不会报错,因为这种情况在C语言中并不认为是个错误。但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢? 你可以在语句列表中增加一条default子句,把下面的标签 default: 写在任何一个 case 标签可以出现的位置。 当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。 所以,每个switch语句中只能出现一条default子句。 但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:printf("今天是星期一\n"); break;
case 2:printf("今天是星期二\n"); break;
case 3:printf("今天是星期三\n"); break;
case 4:printf("今天是星期四\n"); break;
case 5:printf("今天是星期五\n"); break;
case 6:printf("今天是星期六\n"); break;
case 7:printf("今天是星期日\n"); break;
default:printf("输出错误,请重新输入\n");break;
}
return 0;
}
这次当我们输入一个与case标签的值都不匹配的值时 屏幕上就会打印“输出错误,请重新输入” 可能这个时候有人会想default子句后面的break有必要吗? 正如上面所说,default子句是可以出现在语句列表的任何位置的。 那当我们去掉default后面的break并把它放在第一排。 我们发现在输入一个不匹配的值后,直到完成打印“今天是星期一”后才结束
总结:也就是说如果我们把default子句放在语句项的最后一行,是可以省略break的,但是如果想把default子句放在其他位置,要注意在后面加上break,避免出现错误。
2.2.3 小练习
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
}
n=1 m=2—>进入switch语句 n=1 执行case 1—>m=3 无break 执行case 2—>n=2 m=3 没有break进入case 3—>执行case 2 m=4 n=3 break跳出第二个switch语句 无break—>执行case 4 m=5 n=3 遇到break 跳出打印结果。
即最后结果为m=5 n=3
三.循环语句
3.1 while循环
我们已经了解了if语句,当条件满足的情况下,if语句后的语句执行,否则不执行。 但是这个语句只会执行一次。 由于我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。 那我们怎么做呢? C语言中给我们引入了: while 语句,可以实现循环。
while语句的执行流程:
(注意:在while语句中进入循环条件的次数要比进入循环体多一次)
举例:在屏幕上打印1~10 的数字
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ", i);
i = i+1;
}
return 0;
}
由上面的代码我们可以得到while语句的基本语法
while(表达式)
语句;
其中表达式是循环条件,语句为循环体。
3.1.2 while语句中break和continue的作用
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)
break;
printf("%d ", i);
i = i+1;
}
return 0;
}
我们可以看到 当i=5时直接跳出循环 总结: break在while循环中的作用: 在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的break是用于永久终止循环的 接下来我们将break换成continue continue示例1
可以看到最后的结果是1 2 3 4 但仍没有结束进程变成了死循环
当i=5时,遇到continue语句直接跳过了余下为执行的语句,又返回进行下一次循环条件判定,由于此时i仍等于5又满足了if语句的条件判定,再次遇见continue语句进入死循环。
continue示例2
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
i = i + 1;
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
观察示例2的结果,当i=5时,跳过余下尚未执行的语句,又重新进入循环判定条件,从6开始打印到10。
总结: continue语句的作用是跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为仅结束本次循环。 注意:continue语句并没有使整个循环终止。
3.2 for循环
for(表达式1; 表达式2; 表达式3)
循环语句;
表达式1为初始化部分,用于初始化循环变量的。 表达式2为条件判断部分,用于判断循环时候终止。 表达式3为调整部分,用于循环条件的调整。 示例
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
printf("%d ", i);
}
return 0;
}
for语句的循环流程图: 我们来对比一下实现相同的功能,while循环和for循环的差距。
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ",i);
i = i+1;
}
printf("\n");
for(i=1; i<=10; i++)
{
printf("%d",i);
}
}
可以发现在实现某些功能时,while循环中依然存在循环的三个必须条件,但显然使用for语句更加简洁,修改和查找也更加方便,这也是为什么for循环是循环中使用频率最高的原因。
3.2.1 for循环中的break和continue作用
我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。 但是还是有些差异:
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
break;
printf("%d ",i);
}
return 0;
}
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
continue;
printf("%d ",i);
}
return 0;
}
建议:
- 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
- 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0;
for(i=0; i<10; i++)
{}
for(i=0; i<=9; i++)
{}
3.2.2 for循环的一些变种
#include <stdio.h>
int main()
{
for(;;)
{
printf("hehe\n");
}
int i = 0;
int j = 0;
int count=0;
for(i=0; i<10; i++)
{
for(j=0; j<10; j++)
{
printf("hehe\n");
}
printf("一共打印%d次",count);
}
运行后在屏幕上打印了100行hehe,count=100,所以在进入第一个for循环后里面嵌套的for循环作为第一个for循环的循环体,因此一共打印了100次。
int i = 0;
int j = 0;
int count = 0;
for (; i < 10; i++)
{
for (; j < 10; j++)
{
printf("hehe\n");
count++;
}
}
printf("打印的次数为%d", count);
3.3 do…while循环
do
循环语句;
while(表达式);
do…while的循环流程图 do…while循环的特点:循环至少执行一次 示例
#include <stdio.h>
int main()
{
int i = 10;
do
{
printf("%d\n", i);
}while(i<10);
return 0;
}
3.3.1 do…while循环中的break和continue
#include <stdio.h>
int main()
{
int i = 10;
do
{
if(5 == i)
break;
printf("%d\n", i);
}while(i<10);
return 0;
}
#include <stdio.h>
int main()
{
int i = 10;
do
{
if(5 == i)
continue;
printf("%d\n", i);
}while(i<10);
return 0;
}
3.4 goto语句
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。 从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。 例如:一次跳出两层或多层循环。 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。 goto语言真正适合的场景如下:
for(...)
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
…
error:
if(disaster)
四.练习
1.判断一个数是否为奇数
#include <stdio.h>
int main()
{
int n = 0;
printf("请输入:>");
scanf("%d", &n);
if (n % 2 == 1)
{
printf("%d是奇数\n", n);
}
else
{
printf("%d是偶数\n", n);
}
return 0;
}
2.输出1~100之间的奇数
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 100; i++)
{
if (i % 2 == 1)
{
printf("%d ", i);
}
}
return 0;
}
3.输入两个整数及运算符,进行运算后输出运算结果
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
char c = 0;
scanf("%d%c%d", &a, &c, &b);
switch (c)
{
case '+':printf("%d\n", a + b); break;
case '-':printf("%d\n", a - b); break;
case '*':printf("%d\n", a * b); break;
case '/':
if (b == 0)
printf("除数不能为0");
else
printf("%f", a * 1.0 / b);
break;
case '%':printf("%d\n", a % b); break;
default:printf("输出错误\n"); break;
}
return 0;
}
4.计算n的阶乘
#include <stdio.h>
int main()
{
int n = 0;
int i = 0;
int ret = 1;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
printf("%d\n",ret);
return 0;
}
5. 计算 1!+2!+3!+……+10!
#include <stdio.h>
int main()
{
int n = 0;
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 10; n++)
{
ret = 1;
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
6.编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序。)
#include <stdio.h>
#include <string.h>
int main()
{
int i = 0;
char password[20] = "";
for (i = 0; i < 3; i++)
{
printf("请输入密码:>");
scanf("%s", password);
if (strcmp(password, "123456") == 0)
{
printf("登录成功\n");
break;
}
else
{
printf("密码错误\n");
}
}
if (i == 3)
{
printf("密码错误超过三次,登录失败\n");
}
return 0;
}
|