概览
控制语句用于控制程序的执行流程,以实现程序的各种结构方式
C语言支持三种结构:顺序结构、选择结构(分支)、循环结构 :
(其实显示中的事件也都是由这三者混合合成的)
它们由特定的语句定义符组成,C语言有九种控制语句。
可分成以下三类:
1. 条件判断语句也叫分支语句:if 语句、switch 语句;
2. 循环执行语句:do while 语句、while 语句、for 语句;
3. 转向语句:break 语句、goto 语句、continue 语句、return 语句。
C语言中的真/假
不累子提醒你 : 在讲下面的内容前 , 请一定要看完这一节哦~
这里就有小伙伴要问了 : 哎呀不累子 , 那 C 语言中什么是真呀?
在 C 语言中 : 0(包括 0.0 , -0 , +0) 为假 , 一切非 0 都为真 .
对于 C99 新增的布尔值 , 如果我们翻找 true 和 false 的定义不难得知 :
frue 就是值为 1 的常量 , false 则是值为 0 的常量
也就是说 : 该表达式 / 常量的值只要不等于 0 , 它就为真 .
补充
在 C 语言中 , 如果一个表达式为真 , 它的值默认是 1
如果一个表达式为假 , 它的值默认是 0
这些都是 C 语言的执行标准中规定的
实例
我们先定义两个变量 :
int a = 1;
int b = 0;
接着思考 : 下面括号内的语句是否为真?
(a)
(b)
(a == 0)
(b == 0)
(a + b)
(a = 0)
(b = 1)
解析 :
(a)//真,因为 a 就是 1
(b)//假,因为 b 就是 0
(a == 0)//假,这里是判断语句,因为 a 不等于 0,所以这个表达式的值默认为 0
(b == 0)//真,因为 b 确实等于 0,这个表达式的值默认为 1
(a + b)//真,因为 a + b = 1
(a = 0)//假,这里是赋值表达式,赋值表达式的值等于赋给变量的值
(b = 1)//真,和上面的道理一样
分支语句(选择结构)
if 语句
语法
//语法结构:
if(表达式)
语句;
当表达式为真时 , 执行语句
if 默认只能控制一条语句,如果想同时执行多个语句则需要用代码块(即一对花括号)创建一个复合语句
什么意思呢?
就是说如果你这样写 :
#include <stdio.h>
int main()
{
if (0)//括号里的 0 表示假
printf("1\n");
printf("2\n");
return 0;
}
只会打印 2
即使你将语句对齐 :
if (0)
printf("1\n");
printf("2\n");
也不会改变输出结果 (想也知道这和对齐没关系吧)
那么怎么使一个 if 可以控制多条语句呢?如下 :
if(0)
{//一对大括号表示一个代码块
printf("1\n");
printf("2\n");
...//其他语句
}
这样 if 就可以控制多条语句了 .
不累子建议 : 即使在 if 后只有一条语句时 , 也尽量使用代码块 , 这样可以使得代码清晰易懂 .
使用 if 和 else 创造多个分支
#include <stdio.h>
int main()
{
if (a)//这里的 a 可以为表达式/变量/值
{
printf("1\n");
}
else
{
printf("2\n");
}
return 0;
}
我们知道 , 英语中的 else 是 "除...之外" 的意思 , 以上代码的用意也很明显 :
如果 a 为真则打印 1 , 为假则打印 2 .
这是两个分支的情况 , 那么如果有 3 个或更多分支呢?
我们可以再把一条 if 语句写进 else 里 :
#include <stdio.h>
int main()
{
if (a)//情况 a
{
printf("1\n");
}
else
{
if (b)//情况 b
{
printf("2\n");
}
else//除了上面的情况外
{
printf("3\n");
}
}
return 0;
}
以上代码 : 如果 a 为真则打印 1 , a 不为真但 b 为真则打印 2 , a b 都不为真则打印 3 .
实际上我们在使用时并不会像上面那样写 , 而是直接在 else 后接 if :
if (a)
{
printf("1\n");
}
else if (b)
{
printf("2\n");
}
else if(c)
{
printf("3\n");
}
else if(d)
...
else
{
}
以上为什么不用多个 if ?
你也许会问 : 为什么不用多个 if 判断不同情况?
确实 , 下面这样也可以实现我们的目的 :
#include <stdio.h>
int main()
{
if (a)
{
printf("1\n");
}
if (b)
{
printf("2\n");
}
if (c)
{
printf("3\n");
}
return 0;
}
但如果这样写 , 则每个 if 语句都要进行一次判断 , 降低了代码的执行效率
在顺序结构中 , 多增加几次判断造成的影响并不明显 , 但在循环结构中 , 使用这样的结构会使得代码的执行效率成倍下降
悬空else
思考 : 以下代码的执行结果是什么?
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("BLZ\n");
else
printf("dL\n");
return 0;
}
屏幕前未来的大佬们也许会拍案而起 : "这我知道 ! a 不等于 1 , 不就走 else 输出 dL 么"
其实这是个陷阱 , 本质上代码是这样的 :
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("BLZ\n");
else//这里的 else 和第二个 if 对应
printf("dL\n");
return 0;
}
所以该程序什么都不会输出!!!
在没使用代码块的情况下 : else 是和上方最近的 if 配对的!!!
这里就能深刻体现出勤用代码块的好处了 , 如果你听不累子的 , 以上代码就会是下面这样 :
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if (a == 1)
{
if (b == 2)
{
printf("BLZ\n");
}
else//这里的 else 和第二个 if 对应
{
printf("dL\n");
}
}
return 0;
}
这样是不是就清晰明了?
当然你也可以改成这样 :
if (a == 1)
{
if (b == 2)
{
printf("BLZ\n");
}
}
else//这样 else 就和第一个 if 配对了
{
printf("dL\n");
}
这样就会输出 dL 了
if 的不同书写形式
//代码1
if (某种情况) {
return x;
}
return y;
//代码2
if (某种情况)
{
return x;
}
else
{
return y;
}
实际上代码 1 和 2 是等价的 , 但我们推荐使用代码 2 的形式 , 因为代码 2 显而易见地显而易懂
//代码3
int num = 1;
if (num == 5)
{
printf("hehe\n");
}
//代码4
int num = 1;
if (5 == num)
{
printf("hehe\n");
}
实际上代码 3 和代码 4 也是等价的 , 但我们推荐使用代码 4 的形式
因为如果你不小心漏了一个 = (这种情况很常见) , 在代码 3 中 , 这会使得原本的判断语句变成赋值语句 , 但编译器并不会报警告
但如果是代码 4 , 由于 5 不能被赋值 , 在编译时编译器就无法通过并会报警告 , 这可以提示你出错了
除非你确实有这种在 if 的括号内赋值的需求
switch 语句
语法
switch (整型表达式)//short | int | long | long long | char -->字符类型也可以
{
语句项;
}
语句项是什么呢?
//语句项:
//是一些case/default语句:
//如下:
case 整形常量表达式://不能是变量、浮点型
语句;
什么?难懂?1 2 3 , 上实例!!!
实例 / 运行方式
int main()
{
int a = 0;
scanf("%d", &a);
switch (a)
{
case 1:
printf("1\n");
case 2:
printf("2\n");
case 3:
printf("3\n");
case 4:
printf("4\n");
case 5:
printf("5\n");
case 6:
printf("6\n");
default:
printf("7\n");
}
return 0;
}
以上 switch 语句先从上往下进行判断,假如符合情况 a = 1 则会运行 printf("1\n");
然后再运行 case 1 下方的所有语句 , 即输出 :
1
2
3
4
5
6
7
如果输入 3 ,则输出:
3
4
5
6
7
default 在英文中的意思是 "默认"
如果所有情况都无法匹配,则输出 default 后的语句
比如如果输入字符 a , 则输出 :
7
为了使 switch 语句能造多个独立的分支,需搭配 break 语句使用 :
int main()
{
int a = 0;
scanf("%d", &a);
switch (a)
{
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
case 3:
printf("3\n");
break;
case 4:
printf("4\n");
break;
case 5:
printf("5\n");
break;
case 6:
printf("6\n");
break;
default:
printf("7\n");
break;
}
return 0;
}
case 决定入口,break 决定出口
多种情况对应一个输出
由上面的例子可知 : case 语句在执行完后如果后续无 break 语句,则会继续执行下一个 case 语句的输出 , 直到遇到 break
于是我们可以写出一个判断是否是工作日的程序 :
int main()
{
int a = 0;
scanf("%d", &a);
switch (a)
{
case 1:
case 2:
case 3:
case 4:
case 5:
{
printf("工作日");
break;//前 5 种情况直到这里才遇到 break , 故都会输出"工作日"
}
case 6:
case 7:
{
printf("休息日");
break;
}
default://如果前面的情况都匹配不了 , 则进入 default
{
printf("输入错误");
break;
}
}
return 0;
}
break 语句的补充
break 语句只会跳出其对应的 switch 语句
如 :
下方实例 a 处的 break 语句执行完后只会跳出 b 处的 switch 语句 :
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)//b 处
{//switch允许嵌套使用
case 1:
n++;
case 2:
m++;
n++;
break;//a 处
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
}
goto 语句
语法
goto (自定义的字符串);
...
自定义的字符串:
...
示例
用 goto 语句实现的一个打印 1 2 3 的死循环
#include<stdio.h>
int main()
{
a:
printf("1\n");
printf("2\n");
printf("3\n");
goto a;//去往 a 处
return 0;
}
应用场景
理论上 goto 语句是不必要的,实践中没有goto语句也可以很容易的写出代码。
并且滥用 goto 语句还会导致代码可读性降低
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环:
for (...)
{
for (...)
{
for (...)
{
if (disaster)//错误情况的判断
goto error;//发生错误 , 一步跳转至对应错误的处理处
}
}
}
...
error :
if (disaster)
// 处理错误情况
使用 goto 语句编写关机程序
这部分不累子先搁着啦 , 不久后出了文章这里会贴链接滴~
点点关注下次能更快地找到哦
循环语句
种类
while
for
do while
while 循环
语法
while (表达式)//括号内为判断部分
循环语句;//循环部分
//使用代码块创造多语句循环
while (表达式)
{
循环语句 1;
循环语句 2;
...
循环语句 n;
}
while 和 if 类似 , 只不过 if 是执行一次 , 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 循环中的 break
结合本节开头的流程图 , 想想下面的代码运行后输出什么 :
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
break;
printf("%d ", i);
i = i + 1;
}
return 0;
}
上方的示例执行结果为 :
1 2 3 4
因为当 i 等于 5 时,满足 if 后的条件,执行下方的 break 语句,后续的语句(包括判断部分)被忽略。
while 中的 break 是用于直接跳出循环的。
while 循环中的 continue
再结合本节开头的流程图 , 思考下面的代码运行后输出什么?
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)//a 处
{
if (i == 5)
continue;//b 处
printf("%d ", i);
i = i + 1;
}
return 0;
}
实际上输出的是 :
1 2 3 4
且输出上述后程序并没结束 , 却也永远没有后续输出 , 这是为什么呢?
这是由于当 i 加到 5 时,if 语句的条件满足,执行 continue 语句
此后代码将不断从 b 处跳到 a 处 , 再运行到 b 处再跳到 a 处 ......
当部分更改后可以更直观地表现出上面的说法:
while (i <= 10)
{
if (i == 5)
{
printf("BLZ\n");
continue;
}
每一次跳转都会输出 BLZ
总结 : while 循环中 continue 的作用为忽略 continue 后续的语句,返回判断部分。
for 循环
最常用 , 一定要熟练掌握
语法
for (表达式1; 表达式2; 表达式3)
{
循环语句 1;
循环语句 2;
...
循环语句 n;
}
表达式 1 为初始化部分
表达式 2 为判断部分
表达式 3 为调整部分
示例
#include<stdio.h>
int main()
{
for (int a = 1; a <= 10; a++)
{
printf("%d ", a);
}
return 0;
}
输出结果 :
1 2 3 4 5 6 7 8 9 10
同样是打印 1 ~ 10 , for 循环的写法比 while 不知道简单了多少 :
while 循环的缺陷
刚讲完 while , 这里不累子就背刺一下 while
从上面的实例不难看出 , for 循环可以方便我们管理循环变量(控制循环的变量)
因为 for 循环中,初始化、判断、调整部分放到了一处
如果后续循环中的代码量十分庞大 , 使用 for 循环无疑更易于我们管理
for 循环中的 continue
实例 :
结合本节开头的流程图 , 思考以下代码输出什么
#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//没有 5
可知在 for 循环中遇到 continue 时 , 也会直接忽视后续语句 , 直接跳转到表达式 3 , 并进行判断
也就是说 , continue 不会跳过 for 循环中的表达式 3
for 循环中的 break
break 在 for 循环内的作用与在 while 循环中的作用一致
都是直接跳出循环,不执行表达式 3
for 循环的变种
for 循环的三个表达式可以省略一个或多个。
省略了判断表达式的 for 循环
#include<stdio.h>
int main()
{
for (;;)
{
printf("1\n");
}
return 0;
}
以上实例在运行后会重复打印 1 ,不会终止。
原因:for 默认循环中没有判断条件时,判断恒为真
省略了初始化表达式的 for 循环
思考以下代码输出什么 :
#include<stdio.h>
int main()
{
int i = 0;
int j = 0;
for (; i < 3; i++)
{
for (; j < 3; j++)
{
printf("1\n");
}
}
return 0;
}
输出结果 :
1
1
1
原因:
在最初进入最外层 for 循环时,i < 3;故进入第二层 for 循环
在第二层循环中,一共进行 3 次循环打印操作
离开第二层 for 循环后,j 的值仍为 3
而由于第二层 for 循环没有初始化部分
故此后 j 的值永远为 3
再也不会进入第二层 for 循环进行打印操作
如果加上第二层 for 循环的初始化部分,则打印 9 个 :
for (; i < 3; i++)
{
for (j = 0; j < 3; j++)//加上了初始化部分,每次进入循环前都会先初始化
{
printf("1\n");
}
}
使用多个循环变量控制 for 循环
在使用 for 循环时,循环变量可以有多个(应该很容易理解吧) :
#include<stdio.h>//没必要细看,知道就行
int main()
{
int x, y;
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)//由两个变量控制的循环
{
printf("1\n");
}
return 0;
}
一道笔试题
据(不累子)说 99% 的初学者这道题都错了
当然 , 不累子就是 99% 中的一个
以下代码运行后输出什么 :
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
k++;
return 0;
}
以上代码运行后一次都不会循环
因为判断部分并不是一个判断语句
而是一个赋值语句
赋值语句的值为赋的值:即为 0
(0 为假 , 不进入循环 , 这出题人真会坑人 , 对吧)
实际上这只是坑我们初学者 , 相信大家这么错过几次之后都能发现问题
(应该?)
这里就知道不累子给你的提醒有什么用了吧 :
//代码3 int num = 1; if (num == 5) { printf("hehe\n"); } //代码4 int num = 1; if (5 == num) { printf("hehe\n"); }
实际上代码 3 和代码 4 也是等价的 , 但我们推荐使用代码 4 的形式
因为如果你不小心漏了一个 = (这种情况很常见) , 在代码 3 中 , 这会使得原本的判断语句变成赋值语句 , 但编译器并不会报警告
但如果是代码 4 , 由于 5 不能被赋值 , 在编译时编译器就无法通过并会报警告 , 这可以提示你出错了
所以这么细心宠粉(根本没什么粉丝555)的不累子你忍心不关注嘛...qwq
do while 循环
很少用 , 知道就行
语法
do
{
循环语句 1;
循环语句 2;
循环语句 3;
...
循环语句 n;
}
while (表达式);
先执行一次循环语句,如果 while 的条件满足则返回再执行循环语句
也就是说 do while 循环中,循环语句至少执行一次
do while 循环中的 continue
作用和 while 中的 continue 一样嘛
当运行到 continue 时,跳过后续循环语句,直接执行判断语句
#include<stdio.h>
int main()
{
int i = 1;
do
{
if (5 == i)
{
continue;
}
printf("%d ", i);
i++;
}
while (i < 10);
return 0;
}
以上语句在输出 1 2 3 4 后进入无输出死循环。
do while 循环中的 break
break 在 do while 循环内的作用与在 while 循环、for 循环中的作用一致
都是直接跳出循环,不执行后续语句。
练习
计算 n 的阶乘
写一个程序 , 要求输入一个值 n , 输出 n! (n 的阶乘) 的值
注 : n! = 1 * 2 * 3 * 4 * 5 * 6 * ... * n
答案 :
#include<stdio.h>
int main()
{
int a, b = 1;
printf("n!\nn = ");//打印提示信息
scanf("%d", &a);//输入一个值,并存放到 a 里
for (int i = 1; i <= a; i ++)//每次循环 i 都加 1
{
b *= i;//等效于 b = b * i;
}
printf("n! = %d", b);//输出值
return 0;
}
计算 1!+2!+3!+……+10!
写一个程序 , 输出从 1 的阶乘加到 10 的阶乘的值
有了上面的例子 , 这个应该也能做出来吧
答案 :
#include<stdio.h>
int main()
{
long long a, b=1, i= 1;//定义类型为 long long,防止数据溢出
for (a = 10; a >= 10; a--)
{
for (i = 1; i <= a; i++)
{
b *= i;
}
}
printf("%lld", b);//输出结果
return 0;
}
拓展 : 打印 1! + 2! + ... + n!
(怎么就跟阶乘过不去呢)
这个就留给大家自己实现啦 , 不累子真的很累啦 , 饶了我吧qwq
答案 : 都说了自己实现 , 那哪来的答案嘛
总结
有了以上这些知识 , 相信以后 C 语言里的这些分支语句和循环语句就难不倒你啦...
如果你觉得在本文学到了点东西 , 不妨点点关注点点赞 , 将来不累子会更新更多知识
积少成多 , 希望你我都能学到属于自己的东西!!!
敲这么多真的很累的啊...可怜可怜不累子吧qwq
如果你能关注我 , 那是再好不过了 , 如果不想关注 , 至少也留下两句鼓励的话再走吧 , 让我知道有人在看我的文章并学到了东西
标签:语句,do,int,case,while,循环,printf From: https://blog.csdn.net/Blaze_dL/article/details/143088864