【C语言复习】分支和循环
- 1. if语句
- 1.1 if
- 1.2 else
- 1.3分支中包含多条语句
- 1.4嵌套if
- 1.5悬空else问题
- 2.关系操作符
- 3. 条件操作符
- 4.逻辑操作符:&& 、|| 、!
- 4.1 逻辑取反运算符
- 4.2 与运算符
- 4.3或运算符
- 4.4 练习:闰年的判断
- 4.5短路
- 5.switch 语句
- 5.1 if语句与switch语句的对比
- 5.3 switch语句 中的default
- 5.4 switch语句中的case和default的顺序问题
- 6.while循环
- 6.2 while语句的执行流程
- 6.3 while循环的实践
- 6.4 练习
- 7.for循环
- 7.1 语法形式
- 7.2 for循环的执行流程
- 7.3for循环练习
- 7.4 while循环和for循环的对比
- 7.5练习
- 8. do while循环
- 8.1 语法形式
- do while循环执行流程图
- 8.3 do while循环实例
- 8.4练习
- 9. break和continue语句
- 9.1while循环中的break和continue
- 9.1.1 break举例
- 9.1.2 continue举例
- 9.2 for循环中的break和continue
- 9.2.1 break举例
- 9.2.2 continue举例
- 9.3 do while循环的break和continue
- 10.循环的嵌套
- 10.1 练习
- 10.2 解析
- 10.3代码实现
- 11. goto语句
C语言是结构化的程序设计语言,这里的结构指的是顺序结构、选择结构、循环结构,C语言是能够实现这三种结构的,其实我们如果仔细分析,我们日常所见的事情都可以拆分为这三种结构或者这三种结构的组合。我们可以使用if、switch 实现分支结构,使用for、while、 do while 实现循环结构。
1. if语句
1.1 if
if的语法形式如下:
if(expression)
语句
表达式成立(为真), 则语句执行,表达式不成立(为假),则语句不执行
在C语言中,0为假,非零为真,也就是表达式的结果如果是0,则语句不执行,表达式的结果如果不是0,则语句执行
eg:输入一个整数,判断是否为奇数
代码执行流程图
1.2 else
如果一个数不是奇数,那就是偶数了,如果任意一-个整数,我们要清楚的判断是奇数还是偶数怎么表示呢?
这里就需要if… .else…语句了,语法形式如下:
if(expression)
语句1;
else
语句2;
eg:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印数偶数。
eg:输入-一个年龄,>= 18岁就输出:成年,否则就输出:未成年
1.3分支中包含多条语句
默认情况下,if和else的后边只能跟一条语句
如果要跟多条语句的话,可以使用大括号
我们可以修改后得到想要的效果(在else后面加上大括号,把禁止谈恋爱包括里面)
1.4嵌套if
在if else 语句中,else 可以与另一个if语句连用,构成多重判断。
比如:要求输入一个整数,判断输入的整数是0,还是正数或者负数。请看如下代码:
上述的代码也可以进行简化,代码如下图所示:
练习:
输入一个人的年龄
如果年龄<18岁,打印"少年"
如果年龄在18岁至44岁打印"青年"
如果年龄在45岁至59岁打印"中老年"
如果年龄在60岁 至89岁打印"老年"
如果90岁以上打印"老寿星"
1.5悬空else问题
如果有多个if和else,可以记住这样一条规则,else 总是跟最接近的if匹配。
我们首先从下面代码开始:
运行的结果是什么呢?
得到的结果是什么也没输出,这是为什么呢?
这就是悬空else的问题,如果有多个if和else,可以记住这样一条规则, else 总是跟最接近
的if匹配。
上面的代码排版,让else和第-一个if语句对齐,让我们以为else是和第一-个if匹配的,当if语句不成立的时候,自然想到的就是执行else子句,打印haha,但实际上else是和第二个if进行匹配的,这样后边的if.。.else语句是嵌套在第一-个if 语句中的,如果第一-个 if语句就不成立,嵌套if和else就没机会执行了,最终啥都不打印。
如果代码改成下面这样就更加容易理解了
2.关系操作符
C语言用于比较的表达式,称为“关系 表达式”(relational expression),里面使用的运算符就称为“关系运算符” (relational operator) ,主要有下面6个。
●大于运算符 >
●小于运算符 <
●大于等于运算符 >=
●小于等于运算符<=
●相等运算符==
●不相等运算符 !=
关系表达式通常返回0或1,表示真假。
C语言中,0表示假,所有非零值表示真。比如,20>12返回1,12>20返回0。
关系表达式常用于if或while结构。
注意:相等运算符==与赋值运算符=是两个不-样的运算符,不要混淆。有时候,可能会不小心写出下面的代码,它可以运行,但很容易出现意料之外的结果。
.上面示例中,原意是x == 5,但是不小心写成x = 5。这个式子表示对变量x赋值5,它的返
回值为5,所以if判断总是为真。
为了防止出现这种错误,有的程序员喜欢将变量写在等号的右边。\
另一个需要避免的错误是:多个关系运算符不宜连用。
那么我们如何修改能够达到想要的效果呢?
eg:我们输入一个年龄,如果年龄在18岁~36岁之间,我们输出青年。
3. 条件操作符
条件操作符也叫三目操作符,需要接受三个操作数的,形式如下:
exp1 ? exp2 : exp3;
条件操作符的计算逻辑是:如果exp1为真,exp2计算,计算的结果是整个表达式的结果;如果exp1为假,exp3 计算,计算的结果是整个表达式的结果。
上面的代码我们也可以使用条件操作符来编写
练习:使用条件操作符来比较两个数的最大值
4.逻辑操作符:&& 、|| 、!
逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。.
●!:逻辑取反运算符(改变单个表达式的真假)
●&&:与运算符,就是并且的慧崽议两侧的表达式都为買"则为買,否则为假)。
●||:或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)
注: C语言中,非0表示真,0表示假
4.1 逻辑取反运算符
4.2 与运算符
&&就是与运算符,也是并且的意思,&& 是一个双目操作符,使用的方式是a&&b , &&两边的表达式都是真的时候,整个表达式才为真,只要有一个是假,则整个表达式为假。
比如:如果我们说月份是3月到5月,是春天,那使用代码怎么体现呢?
4.3或运算符
||就是或运算符,也就是或者的意思,||也是一一个双目操作符,使用的方式是a | | b,||
两边的表达式只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假。
比如:我们说一年中月份是12月或者1月或者2月是冬天,那么我们怎么使用代码体现呢?
4.4 练习:闰年的判断
输入一个年份year,判断year是否是闰年
闰年判断的规则:
1.能被4整除并且不能被100整除是闰年
2.能被400整除是闰年
4.5短路
C语言逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。
如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。
如前面的代码:
表达式中&&的左操作数是month >= 3,右操作数是month <= 5,当左操作数month >= 3的
结果是0的时候,即使不判断month <= 5,整个表达式的结果也是0 (不是春季)
对于||操作符是怎么样呢?我们结合前面的代码:
如果month== 12,则不用再判断month是否等于1或者2,整个表达式的结果也是1 (是冬季)。
所以,I操作符的左 操作数的结果不为0时,就无需执行右操作数。
像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。
练习:阅读代码,计算得到的结果
将a改成1后,得到的结果又是什么呢?
再变换一下,看看得到的结果是什么呢?
再变换一下,计算得到的结果是什么呢?
5.switch 语句
除了if语句外,C语言还提供了switch语句来实现分支结构。
switch语句是一种特殊形式的if…else 结构,用于判断条件有多个结果的情况。它把多重的else if改成更易用、可读性更好的形式。
switch (expression)
{
case value1: statement
case value2: statement
default: statement
}
上面代码中,根据表达式expression不同的值,执行相应的case分支。如果找不到对应的值,就执行default分支。
注:
●
switch后的expression必须是整型表达式
●
case后的值,必须是整形常量表达式
5.1 if语句与switch语句的对比
练习:输入任意一个整数值,计算除3之后的余数
如果使用if语句完成,如下:
如果改成switch语句改写,就可以写成如下形式:
为什么满足switch的语法形式了得到的结果不是想要的呢?是因为每一个case语句中的代码执行完成后,需要加上break,才能跳出这个switch语句。修改后的代码如下:
练习:
输入一个1~7的数字,打印对应的星期几
例如:
输入: 1输出:星期一
输入: 2输出:星期二
输入: 3输出:星期三
输入: 4输出:星期四
输入: 5输出:星期五
输入:6输出:星期六
输入: 7输出:星期天
代码如下:
#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;
}
如果需求发生变化,变为:
1.输入1-5,输出的是“工作日”;
2.输入6-7, 输出“休息日”
. 上面的练习中,我们发现应该根据实际的情况,来在代码中觉得是否使用break,或者在哪里使用.break,才能正确完成实际的需求。
5.3 switch语句 中的default
在使用swi tch语句的时候,我们经常可能遇到一种情况,比如swi tch后的表达式中的值无法匹配代码中的case语句的时候,这时候要不就不做处理,要不就得在switch语句中加入default子句。
switch (expression)
{
case value1: statement
case value2: statement
default: statement
}
swi tch后边的expression的结果不是value1,也不是value2的时候,就会执行default子句。
就比如前面做的打印星期的练习,如果day的输入不是1~7的值,如果我们要提示:输入错误,则可以这样完成代码:
5.4 switch语句中的case和default的顺序问题
在switch语句中case子句和default |子句有要求顺序吗? default 只能放在最后吗?
其实,在swi tch语句中case语句和default语句是没有顺序要求的,只要你的顺序是满足实际需求的就可以。.
不过我们通常是把default子句放在最后处理的。
6.while循环
C语言提供了3种循环语句,while 就是其中一种,接下来就介绍一下while语句。while语句的语法结构和if语句非常相似。
if(表达式)
语句;
while(表达式)
语句;//如果循环体想包含更多的语句,可以加上⼤括号
if后边条件满足,打印一次
while后边的条件满足,死循环打印。
从上面两段代码对比可以看出if和while的区别,while语句是可以实现循环效果的。
6.2 while语句的执行流程
首先.上来就是执行判断表达式,表达式的值为0,循环直接结束;表达式的值不为0,则执行循环语句,语句执行完后再继续判断,是否进行下一次判断。
6.3 while循环的实践
练习:在屏幕上打印1-10的值
6.4 练习
输入一个正的整数,逆序打印这个整数的每一位
例如:
输入: 1234,输出: 4 3 2 1
输入: 521,输出: 1 2 5
题目解析
1.要想得到n的最低位,可以使用n%10的运算,得到的余数就是最低位,如: 1234%10得 到4
2.要想去掉n的最低位,找出倒数第二位,则使用n=n/10操作就可以去掉最低位的,如:n=1234/10得到123,123相较于1234就去掉了最低位,123%10就得 到倒数第二位3。
3.循环1和2两个步骤,在n变成0之前,就能到所有的位。
7.for循环
7.1 语法形式
for |循环是三种循环中使用最多的,for循环的语法形式如下:
for(表达式1; 表达式2; 表达式3)
语句;//如果循环体想包含更多的语句,可以加上⼤括号
表达式1用于循环变量的初始化
表达式2用于循环结束条件的判断
表达式3用于循环变量的调整
7.2 for循环的执行流程
首先执行表达式1初始化循环变量,接下来就是执行表达式2的判断部分,表达式2 |的结果如果==0,则循环结束;表达式2 的结果如果!=0则执行循环语句,循环语句执行完后,再去执行表达式3 ,调整循环变量,然后再去表达式2的地方执行判断,表达式2 的结果是否为0,决定循环是否继续。
整个循环的过程中,表达式1初始化部分只被执行1次,剩下的就是表达式2、循环语句、表达式3在循环。
7.3for循环练习
练习:在屏幕上打印 1-10的值
7.4 while循环和for循环的对比
for和while在实现循环的过程中都有初始化、判断、调整这三个部分,但是for循环的三个部分非常集中,便于代码的维护,而如果代码较多的时候while循环的三个部分就比较分散,所以从形式上for循环要更优一些。
7.5练习
练习:计算1-100之间3的倍数数字之和
我们也可以将上述代码进行优化:
8. do while循环
8.1 语法形式
在循环语句中do while 语句的使用最少,它的语法如下:
do
语句;
while(表达式);
while和for这两种循环都是先判断,条件如果满足就进入循环,执行循环语句,如果不满足就跳出循环;
而do while 循环则是先直接进入循环体,执行循环语句,然后再执行whi le后的判断表达式,表达式为真,就会进行下一次,表达式为假,则不再继续循环。
do while循环执行流程图
在do while循环中先执行图上的“语句”,执行完语句,在去执行“判断表达式”,判断表达式的结果是!=0,则继续循环,执行循环语句;判断表达式的结果==0,则循环结束。
所以在do while 语句中循环体是至少执行一次的,这是do while 循环比较特殊的地方。
8.3 do while循环实例
在屏幕上打印1-10的值
8.4练习
输入一个正整数,计算这个整数是几位数?
例如:
输入: 1234输出: 4
输入:12
输出: 2
这里并非必须使用do while 语句,但是这个代码就比较适合使用do while 循环,因为n即使是0,也是1位数,要统计位数的。
9. break和continue语句
在循环执行的过程中,如果某些状况发生的时候,需要提前终止循环,这是非常常见的现象。C语言中提供了break和continue两个关键字,就是应该到循环中的。
●break的作用是用于永久的终止循环,只要break被执行,直接就会跳出循环,继续往后执行。
●conti nue的作用是跳过本次循环continue后边的代码,在for |循环和while循环中有所差异的。
9.1while循环中的break和continue
9.1.1 break举例
打印了1,2,3,4,5后,当i等于5的时候,循环正break的地方终止,不再打印,不再循环。
所以break的作用就是永久的终止循环,只要break被执行,break 外的第一层循环就终止了。
那以后我们在循环中,想在某种条件下终止循环,则可以使用break来完成我们想要的效果。
9.1.2 continue举例
continue是继续的意思,在循环中的作用就是跳过本次循环中conti nue后边的代码,继续进行下一次循环的判断。
上面的代码,如果把break换成continue会是什么结果呢?
9.2 for循环中的break和continue
9.2.1 break举例
其实和while循环中的break-样,for 循环中的break也是用于终止循环的,不管循环还需要循环多少次,只要执行到了break,循环就彻底终止,请看如下代码。
9.2.2 continue举例
所以在for循环中continue的作用是跳过本次循环中conti nue后的代码,直接去到循环的调整部分。未来当某个条件发生的时候,本次循环无需再执行后续某些操作的时候,就可以使用continue来实现。
这里也可以观察一下while循环和for循环中continue的区别:
9.3 do while循环的break和continue
do. while语句中的break和continue的作用和while循环中几乎一模一-样,大家下来可以自行测试并体会。
#include <stdio.h>
int main()
{
int i = 1;
do
{
if(i == 5)
break;
printf("%d ", i);
i = i + 1;
}while(i<=10);
return 0;
}
#include <stdio.h>
int main()
{
int i = 1;
do
{
if(i == 5)
continue;
printf("%d ", i);
i = i + 1;
}while(i<=10);
return 0;
}
10.循环的嵌套
前面介绍了三种循环while,do while,for, 这三种循环往往会嵌套在一起才 能更好的解决问题,就是我们所说的:循环嵌套,这里我们就看一个例子。
10.1 练习
找出100~200之间的素数,并打印在屏幕上。
注:素数又称质数,只能被1和本身整除的数字。
10.2 解析
1.要从100-200之间找出素数,首先得有100~200之间的数,这里可以使用循环解决。
2.假设要判断i是否为素数,需要拿2-i-1之间的数字去试除i,需要产生2~i-1之间的数字,也可以使用
循环解决。
3.如果2~i-1之间有数字能整除i,则i不是素数,如果都不能整除,则i是素数。
10.3代码实现
代码方法一:
代码方法二:
代码方法三:
11. goto语句
C语言提供了一种非常特别的语法,就是goto语句和跳转标号,goto 语句可以实现在同一个函数内跳转到设置好的标号处。
eg:
#include <stdio.h>
int main()
{
printf("hehe\n");
goto next:
printf("haha\n");
next:
printf("跳过了haha的打印\n");
return 0;
}
goto语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以我们的建议是能不用尽量不去使用;但是goto语句也不是一无是处, 在多层循环的代码中,如果想快速跳出使用goto就非常的方便了。
for(...)
{
for(...)
{
for(...)
{
if(disaster)
goto error;
}
}
}
error:
//...
本来for循环想提前退出得使用break,一个break只能跳出一-层for循环,如果3层循环嵌套就得使用3个break才能跳出循环,所以在这种情况下我们使用goto语句就会更加的快捷。