分支和循环
- 一、if语句
- 二、关系操作符/运算符
- 三、条件操作符/运算符
- 四、逻辑操作符/运算符:&&、||、!
- 五、switch语句
- 六、while循环
- 七、for循环
- 八、do while循环
- 九、break和continue语句
- 十、循环的嵌套
- 十一、goto语句
C语言是一门结构化的程序设计语言,这里的结构指的是顺序结构、选择结构(也可以叫做分支结构或条件判断结构)、循环结构。我们可以使用if
语句、switch
语句实现分支结构,用while
循环、for
循环、do while
循环实现循环结构。
一、if语句
1.if
语法:
if(表达式)
语句;
表达式成立(为真),则执行语句;表达式不成立(为假),则不执行语句。
C语言中,0为假,非0为真。即表达式为0,则不执行语句;表达式为非0,则执行语句。
例子: 输入一个整数,判断是否为奇数。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 2 == 1)
printf("%d是奇数\n", num);
return 0;
}
2.else
如果一个数不是奇数,那就是偶数了。那么,输入任意一个整数时,该用什么方法判断它是奇数还是偶数呢?这时候就要用到if else
语句了。
语法:
if(表达式)
语句1;
else
语句2;
例子: 输入一个整数,判断是否为奇数,如果是奇数则打印奇数,否则打印偶数。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 2 == 1)
printf("%d是奇数\n", num);
else
printf("%d是偶数\n", num);
return 0;
}
练习: 输入一个年龄,>=18岁就输出成年,否则就输出未成年。
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18)
printf("成年\n");
else
printf("未成年\n");
return 0;
}
3.分支中包含多条语句
默认在if
和else
语句中都只控制一条语句。
例子:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18)
printf("成年了\n");
printf("可以谈恋爱了\n");
return 0;
}
我们发现,不管输入的值是>=18,还是<18,可以谈恋爱了
都会被打印在屏幕上。
这是因为if语句只能控制一条语句:if语句的表达式成立(为真),则执行语句printf("成年了\n");
;if语句的表达式不成立(为假),则不执行该语句。语句printf("可以谈恋爱了\n");
是独立存在的,不论if语句的表达式是真是假,这条语句都会被打印在屏幕上。
若想让if
和else
语句控制多条语句的话,那就要用大括号{}
把代码块括起来。(被大括号括起来的多条语句叫做代码块/程序块,也叫做复合语句。)
例子:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18)
{
printf("成年了\n");
printf("可以谈恋爱了\n");
}
else
{
printf("未成年\n");
printf("不可以早恋哦\n");
}
return 0;
}
4.嵌套if语句
语法1:if else
语句中的else
与另一个if
语句连用,构成多重判断。
例子: 输入一个整数,判断输入的数是0、是正数还是负数。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num > 0)
printf("%d是正数\n", num);
else if (num < 0)
printf("%d是负数\n", num);
else
printf("是0\n");
return 0;
}
背景为蓝色的代码是嵌套在前面的else
语句中的:
语法2:if else
语句里的if
嵌套一个if
语句。
例子: 输入一个整数,如果是正数,则再判断是奇数还是偶数,并输出;若不是正数,则输出非正数。
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num > 0)
{
if (num % 2 == 0)
printf("%d是正数且是偶数\n", num);
else
printf("%d是正数且是奇数\n", num);
}
else
printf("非正数\n");
return 0;
}
背景为蓝色的代码是嵌套在前面的if
里的:
练习:
输入一个人的年龄
如果年龄<18岁,则打印“少年”
如果年龄在18岁到44岁之间,则打印“青年”
如果年龄在45岁到59岁之间,则打印“中老年”
如果年龄在60岁到89岁之间,则打印“老年”
如果年龄在90岁及以上,则打印“老寿星”
较复杂写法:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
printf("少年\n");
else if (age >= 18 && age <= 44)
printf("青年\n");
else if (age >= 45 && age <= 59)
printf("中老年\n");
else if (age >= 60 && age <= 89)
printf("老年\n");
else
printf("老寿星\n");
return 0;
}
上述代码中,若表达式age < 18
为假,则进入下一个else if
语句中,所以这个else if
语句暗含着表达式age >= 18
,意味着表达式age >= 18
可以省略不写。简化写法:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
printf("少年\n");
else if (age <= 44)
printf("青年\n");
else if (age <= 59)
printf("中老年\n");
else if (age <= 89)
printf("老年\n");
else
printf("老寿星\n");
return 0;
}
加上大括号更容易明白:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
{
printf("少年\n");
}
else
{
if (age <= 44)
{
printf("青年\n");
}
else
{
if (age <= 59)
{
printf("中老年\n");
}
else
{
if (age <= 89)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}
}
}
}
return 0;
}
5.悬空else问题
如果有多个if
和一个else
,那么else
总是跟最近的if
匹配。
例子:
#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;
}
结果是什么都没打印:
实际上,else
是和第二个if
语句匹配,后面的if else
语句是嵌套在第一个if
里的,若第一个if
的表达式不成立,则嵌套在里面的if 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;
}
若希望else
与第一个if
匹配,代码可以写成:
#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;
}
只要加上适当的大括号,代码的逻辑就会更加的清晰,所以写代码的时候注意括号的使用,就会让代码的可读性变高。
二、关系操作符/运算符
C语言里用于比较的表达式叫做“关系表达式”(relational expression)。关系表达式通常返回0
或1
,分别表示假或真,C语言里,0为假,非0为真,例如,20>19
返回1
,12>20
返回0
。关系表达式常用于if
和while
结构。
例子:
#include <stdio.h>
int main()
{
int x = 3;
if (x == 3)
printf("x=%d", x);
return 0;
}
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i++;
}
return 0;
}
关系表达式中使用的运算符叫做“关系运算符”(relational operator),主要有下面六个:
>
:大于运算符
<
:小于运算符
>=
:大于等于运算符
<=
:小于等于运算符
==
:相等运算符
!=
:不相等运算符
下面是一些例子:
a > b;
a < b;
a >= b;
a <= b;
a == b;
a != b;
#include <stdio.h>
int main()
{
int b = (3 == 5);
printf("b=%d\n", b);
return 0;
}
#include <stdio.h>
int main()
{
int b = (0 == 0);
printf("b=%d\n", b);
return 0;
}
注1: 相等运算符==
和赋值运算符=
不一样,有的时候会把==
误写成=
,程序能运行,但运行结果会出乎意料。
例子:
#include <stdio.h>
int main()
{
int x = 0;
if (x = 3)
printf("I like C\n");
return 0;
}
上述示例中,代码原意是x == 3
但是误写成了x = 3
,x = 3
表示=
右边的3
赋值给=
左边的x
,所以这个式子的返回值为3(非0,为真),if判断总为真。
为了防止出现这种错误,可以把变量写在等号的右边。如果把相等运算符==
写成赋值运算符=
,编译器就会报错。
例子:
#include <stdio.h>
int main()
{
int x = 17;
if (17 == x)
printf("seventeen is %d\n", x);
return 0;
}
#include <stdio.h>
int main()
{
int x = 17;
if (17 = x)
printf("seventeen is %d\n", x);
return 0;
}
**注2:**多个关系操作符不宜连用。
i<j<k
上述关系表达式中连用了两个小于运算符,这是合法表达式,不会报错,但是不会保证变量j
的值在变量i
和变量k
之间。关系表达式是从左往右计算的,所以实际的表达式如下:
(i<j)<k
上面表达式中,i<j
返回值为0
或1
,结果是0
或1
和变量k
进行比较。若想判断变量j
是否在变量i
和k
之间,则用下列写法:
i<j && j<k
例子: 输入一个年龄,如果年龄在18岁到36岁之间,则输出青年。
如果这样写:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (18 <= age <= 36)
printf("青年\n");
return 0;
}
就会发现,不管输入的值在不在18到36之间,都会输出青年。原因是关系表达式18<=age
的返回值0
或1
总是小于36的,所以关系表达式18<=age<=36
的返回值总为1
,即总能输出青年。
正确的代码如下:
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (18 <= age && age <= 36)
printf("青年\n");
return 0;
}
三、条件操作符/运算符
条件操作符是一个需要三个操作数的操作符,所以条件操作符又叫做三目操作符。形式如下:
exp1 ? exp2 : exp3
上述表达式中,若exp1
(expression 1:表达式1)为真,则计算exp2
,计算的结果为整个表达式的结果;若exp1
为假,则计算exp3
,计算的结果为整个表达式的结果。
练习1: 使用条件操作符表示下面代码的逻辑
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d", &a);
if (a > 5)
b = 3;
else
b = -3;
printf("b=%d\n", b);
return 0;
}
用条件操作符表示:
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d", &a);
b = a > 5 ? 3: -3;
printf("b=%d\n", b);
return 0;
}
}
练习2: 使用条件表达式找两个数中的最大值。
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
scanf("%d %d", &num1, &num2);
int max = num1 > num2 ? num1 : num2;
printf("max=%d\n", max);
return 0;
}
试着用if语句写写:
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int max = 0;
scanf("%d %d", &a, &b);
if (a > b)
max = a;
else
max = b;
printf("max=%d\n", max);
return 0;
}
四、逻辑操作符/运算符:&&、||、!
逻辑运算符提供逻辑判断功能,主要有下面三个运算符:
逻辑与运算符&&
:就是并且的意思,两侧的表达式都为真,则为真,否则为假。
逻辑或运算符||
:就是或者的意思,两侧的表达式只要有一个为真,则为真,否则为假。
逻辑取反运算符!
:改变单个表达式的真假。
注: C语言中,0为假,非0为真。
1.逻辑与运算符&&
&&
是与运算符,就是并且的意思,&&
是一个双目操作符,使用形式是a && b
。只有&&
两侧的表达式都为真,结果才为真,否则为假。
例子: 用代码表示月份从三月到五月是春天。
#include <stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month >= 3 && month <= 5)
printf("春天\n");
return 0;
}
2.逻辑或运算符||
||
是或运算符,就是或者的意思,||
也是一个双目操作符,使用形式是a || b
。||
两侧的表达式只要有一个为真,则为真,否则为假。
例子: 用代码表示月份是12月/1月/2月是冬天。
#include <stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month == 12 || month == 1 || month == 2)
printf("冬天\n");
return 0;
}
3.逻辑取反运算符!
!
是取反运算符,用于改变单个表达式的真假,!
是一个单目操作符,使用形式是!a
。
例子:
#include <stdio.h>
int main()
{
int a = 0;
printf("a=%d\n", !a);
return 0;
}
#include <stdio.h>
int main()
{
int a = 8;
printf("a=%d\n", !a);
return 0;
}
定义一个变量flag
,flag
为真,做一些事;flag
为假,做一些事。
#include <stdio.h>
int main()
{
int flag = 0;
scanf("%d", &flag);
if (flag)//flag为真,做一些事。
printf("do something\n");
return 0;
}
#include <stdio.h>
int main()
{
int flag = 0;
scanf("%d", &flag);
if (!flag)//flag为假,那么!flag为真,做一些事。
printf("do something\n");
return 0;
}
4.练习:闰年的判断
输入一个年份year,判断year是否为闰年。
判断是否为闰年的规则:
(1)能被4整除并且不能被100整除是闰年。
(2)能被400整除是闰年。
法一:
#include <stdio.h>
int main()
{
int year = 0;
scanf("%d", &year);
if (year % 4 == 0 && year % 100 != 0)
printf("%d年是闰年\n", year);
else if (year % 400 == 0)
printf("%d年是闰年\n", year);
else
printf("%d年不是闰年\n", year);
return 0;
}
法二:if(() || ())
#include <stdio.h>
int main()
{
int year = 0;
scanf("%d", &year);
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
printf("%d年是闰年\n", year);
else
printf("%d年不是闰年\n", year);
return 0;
}
5.短路
逻辑运算符中的&&
和||
有一个特点:它们总是先对左侧的表达式求值,再对右侧的表达式求值。
短路: 若逻辑运算符&&
和||
的左侧表达式满足逻辑运算符的条件,就不用执行右侧表达式了。
短路求值: 仅仅根据左操作数的结果就能知道整个表达式的结果,而不用对右操作数进行计算的运算。
(1)与运算符&&
如前面的代码:
if (month >= 3 && month <= 5)
&&
的左操作数为month >= 3
,右操作数为month <= 5
。若左操作数month >= 3
的结果为0,则不用执行右操作数month <= 5
,即整个表达式的结果为0
。
**结论:**对于与运算符&&
来说,若左操作数的结果为0,则不用执行右操作数了,即整个表达式的结果为0
。
(2)或运算符||
如前面的代码:
if (month == 12 || month == 1 || month == 2)
若month == 12
的结果不为0,就不用再判断month是否等于1或2了,即整个表达式的结果为1
。
结论: 对于或运算符||
来说,若左操作数的结果不为0,则不用执行右操作数了,即整个表达式的结果为1
。
练习: 阅读代码,计算代码输出的结果。
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d,b = %d,c = %d,d = %d,i = %d\n", a, b, c, d, i);
return 0;
}
分析: 表达式a++ && ++b && d++
中,先对左操作数a++
进行计算:后置++,先使用,结果为0。后面的操作数就不用计算了,即整个表达式的结果为0
,也就是i = 0
。a使用完后+1,所以a = 1
,b、c、d三个变量的值不变,所以最终输出内容为:
若把表达式a++ && ++b && d++
换成a++ || ++b || d++
:
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("a = %d,b = %d,c = %d,d = %d,i = %d\n", a, b, c, d, i);
return 0;
}
分析: 因为左操作数a++
的结果为0,所以再看下一个操作数++b
:前置++,先+1,b = 3
;后使用,这个操作数的结果不为0。表明整个表达式的结果为1
,即i = 1
,那就不用计算后面的操作数了,也就是说变量c、d的值不变,a使用完后+1,所以a = 1
,所以最终输出的内容是:
五、switch语句
switch
语句是一种特殊形式的if else
结构,用于判断条件有多个结果的情况,它把多重的else if
改成更易用、可读性更好的形式。
switch (expression)
{
case value1:
statement;
break;
case value2:
statement;
break;
......
default:
statement;
break;
}
上面代码中,根据表达式expression
不同的值,去执行相应的case
分支,若没有找到对应的值,则执行default
分支。
注:
(1)switch
中的expression
必须是整型表达式(int、short、long、long long、char,字符型有对应的ASCII码值)。
(2)case
后的值必须是整型常量表达式。
1.if语句和switch语句的对比
练习: 输入任意一个整数值,计算除3之后的余数。
若使用if语句:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num % 3 == 1)
printf("%d除3之后余数是1\n", num);
else if (num % 3 == 2)
printf("%d除3之后余数是2\n", num);
else
printf("%d除3之后余数是0\n", num);
return 0;
}
若使用switch语句:
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
switch (num % 3)
{
case 0:
printf("%d除3后余数为0\n", num);
break;
case 1:
printf("%d除3后余数为1\n", num);
break;
case 2:
printf("%d除3后余数为2\n", num);
break;
}
return 0;
}
上述代码中,需要注意的点:
(1)case
和后面的数字之间要有空格。
(2)每一个case
语句中的代码执行完成后,要加上一个break;
,这样才能跳出switch
语句。
2.switch语句中的break
前面的代码中,若去掉case
里的break;
,会发生什么结果呢?
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
switch (num % 3)
{
case 0:
printf("%d除3后余数为0\n", num);
case 1:
printf("%d除3后余数为1\n", num);
case 2:
printf("%d除3后余数为2\n", num);
}
return 0;
}
可以发现,7除3的余数明明是1,但是多打印了余数是2这一行。原因是如果某一个case
语句的后面没有break
语句,代码会继续往下执行,直到遇到break
语句或者switch
语句结束。当然,不是每一个case
语句都有break
,这要根据实际情况来看。
练习: 输入一个1到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;
default:
printf("输入错误\n");
break;
}
return 0;
}
若需求发生变化:
(1)输入1到5,输出“工作日”。
(2)输入6或7,输出“休息日”。
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日\n");
break;
case 6:
case 7:
printf("休息日\n");
break;
default:
printf("输入错误\n");
break;
}
return 0;
}
3.switch语句中的default
当表达式expression
没有找到对应的case
分支时,要不就不做处理,要不就加一个default
子句。
switch (expression)
{
case value1:
statement;
break;
case value2:
statement;
break;
default:
statement;
break;
}
switch
后边的表达式expression
的结果既不是value1
也不是value2
的时候,就会执行default
子句。
前面打印星期的练习有用到default
:若输入的数不是在1到7之间,则输出“输入错误”。下图中蓝色背景的代码就是。
4.switch语句中的case和default的顺序问题
其实,switch
语句中的case
语句和default
语句没有顺序要求,但是通常是把default
子句放在最后的。
六、while循环
1.if和while的对比
while
语句的语法结构和if
语句的非常相似:
if (表达式)
语句;
while (表达式)
语句;//若循环体想要包含更多的语句,可以加上大括号。
while
语句和if
语句的具体代码的对比:
#include <stdio.h>
int main()
{
if (1)
printf("hehe\n");//若满足if后面的条件,则打印一次hehe。
return 0;
}
#include <stdio.h>
int main()
{
while (1)
printf("hehe\n");//若满足while后面的条件,则死循环打印hehe。
return 0;
}
很显然,while
语句是可以实现循环效果的,这就是它们的区别。
2.while语句的执行流程
先执行判断表达式,若表达式的结果为0
,则直接跳出循环;若表达式的结果不为0
,则执行循环语句,再执行判断表达式进行下一次的判断,判断是否进入下一次循环。
3.练习
练习1: 在屏幕上打印1到10的值。
#include <stdio.h>
int main()
{
int num = 1;
while (num <= 10)
{
printf("%d ", num);
num++;
}
return 0;
}
练习2: 输入一个正的整数,逆序打印这个整数的每一位。
例如:
输入1234,输出4 3 2 1
输入564,输出4 6 5
题目解析:
(1)若想得到num
的最低位,则可以用num % 10
,例如1234 % 10
为4。
(2)若想去掉num
的最低位,则可以用num /= 10
,例如1234 /= 10
为123。123 % 10
就能得到倒数第二位3。
(3)循环前两个步骤,在num
变为0
之前,就可以打印所有的位了。
#include <stdio.h>
int main()
{
unsigned int num = 0;
scanf("%u", &num);
while (num)
{
printf("%d ", num % 10);
num /= 10;
}
return 0;
}
七、for循环
for
循环语句是在三种循环语句中使用最多的一个循环语句。
1.语法形式
for (表达式1; 表达式2; 表达式3)
语句;//若循环体想要包含更多的语句,则要加上大括号。
表达式1: 用于循环变量的初始化。
表达式2: 用于循环结束条件的判断。
表达式3: 用于循环变量的调整。
2.for循环的执行流程
先执行表达式1
初始化循环变量,再执行表达式2
判断表达式,若表达式2的结果为假,则循环直接结束;若表达式2为真,则执行循环语句,再执行表达式3
调整循环变量,最后再判断表达式,判断是否进入下一次循环。
整个循环的过程中,表达式1
循环变量的初始化只被执行1次,只有表达式2、循环语句、表达式3在循环。
3.for循环的练习
练习1: 在屏幕上打印1到10的值。
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}
return 0;
}
练习2: 计算1到100之间3的倍数的数字之和。
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for (i = 1; i <= 100; i++)//循环100次
{
if (i % 3 == 0)//判断100次
sum += i;
}
printf("sum = %d\n", sum);
return 0;
}
上述代码的优化:如果能直接产生3的倍数的数字,就省去了多余的循环和判断。
#include <stdio.h>
int main()
{
int i = 0;
int sum = 0;
for (i = 3; i <= 100; i += 3)//循环30多次,没有判断
sum += i;
printf("sum = %d\n", sum);
return 0;
}
4.while循环和for循环的对比
while
和for
在实现循环的过程中都有初始化、判断、调整这三个部分,但是for
循环的三个部分非常集中,便于代码的维护,而如果代码较多的时候while
循环的三个部分就很分散,所以从形式上来看,for
循环要更优一些。
八、do while循环
在循环语句中,do while
语句使用的最少。
1.语法形式
do
语句;//若循环体想包含更多的语句,可以加上大括号
while (表达式);
while
和for
这两种循环都是先判断,如果满足条件,则直接进入循环体,执行循环语句;如果不满足条件,则直接跳出循环。
而do while
循环是先直接进入循环体,执行循环语句,然后再执行while
后面的判断表达式,若表达式为真,则进入下一次循环;若表达式为假,则不再继续循环。所以在do while
语句中循环体是至少执行一次的,这是do while
循环比较特殊的地方。
2.do while循环的执行流程
3.do while循环的练习
练习1: 在屏幕上打印1到10的值
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
或者:
#include <stdio.h>
int main()
{
int i = 0;
do
{
i++;
printf("%d ", i);
} while (i < 10);
return 0;
}
练习2: 输入一个正整数,计算这个整数是几位数。
例如:
输入1234,输出4
输入78,输出2
#include <stdio.h>
int main()
{
unsigned num = 0;
int cnt = 0;
scanf("%u", &num);
do
{
cnt++;
num /= 10;//这句和上一句cnt++可以互换位置
} while (num);
printf("cnt = %d\n", cnt);
return 0;
}
这里并非必须使用do while
语句,但是这个代码就比较适合使用do while
循环,因为num
即使是0,也是1位数,也是要统计的。
九、break和continue语句
在执行循环的过程中,遇到某些状况的时候,是需要提前终止循环的。C语言中提供了break
和continue
这两个关键字,就是应用到循环中的。
break
在三种循环中的作用都是永久的终止循环。只要break
被执行,break
外的第一层循环就终止了,直接跳出该循环,继续往后执行。
continue
的作用是跳过本次循环中的continue
后面的代码。continue
在while
和for
这两种循环中的作用是有所差异的:在while
循环中,执行完continue
后直接进入循环的判断部分;在for
循环中,执行完continue
后直接进入循环的调整部分。
1.while循环中的break和continue
break举例
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
break;
printf("%d ", i);
i++;
}
return 0;
}
打印了1 2 3 4后,当i等于5时,遇到break
,直接跳出break
外的第一层循环,循环终止。
continue举例
上面的代码,把break
换成continue
会是什么结果呢?
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
continue;
printf("%d ", i);
i++;
}
return 0;
}
上述代码中,打印了1 2 3 4,当i等于5的时候,执行continue
,跳过本次循环中continue
后面的语句,直接进入判断部分,由于跳过了i++
,所以i一直是5,陷入死循环。显然,如果循环的调整部分是在continue
之后,可能会造成死循环。
练习: 试写出下列代码在屏幕上打印的结果。
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
i++;
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
结果:
2.for循环中的break和continue
break举例
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
continue举例
上面的代码,把break
换成continue
会是什么结果呢?
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
所以在for
循环中,continue
的作用是跳过本次循环中continue
后面的代码,直接进入循环的调整部分。
3.do while循环中的break和continue
do while
语句中的break
和continue
的作用几乎和while
语句中的一模一样。直接给出示例:
break举例
#include <stdio.h>
int main()
{
int i = 0;
do
{
i++;
if (i == 5)
break;
printf("%d ", i);
} while (i < 10);
return 0;
}
continue举例
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (i == 5)
continue;
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
十、循环的嵌套
前面学习了三种循环:while
、for
、do while
,这三种循环往往会嵌套在一起使用,即循环的嵌套。
例子: 找出100到200之间的素数并打印在屏幕上。(素数:又称质数,只能被1和它本身整除的数)
法一:
找出100到200之间的素数,首先要有100到200之间的数,这里可以用循环解决。判断i是否为素数,可以拿2到i-1之间的数去试除i,需要产生2到i-1之间的数,这里也可以用循环解决。若2到i-1之间有能整除i的数字,则i不是素数;若都不能整除i,则i是素数。
#include <stdio.h>
int main()
{
int i = 0;
//int flag = 1;//错误写法,写在这屏幕上什么也没有
for (i = 100; i <= 200; i++)//循环产生100到200之间的数字
{
int j = 0;
int flag = 1;//假设i是素数
for (j = 2; j <= i - 1; j++)//循环产生2到i-1之间的数字
{
if (i % j == 0)
{
flag = 0;//i不是素数
break;
}
}
if (flag == 1)
printf("%d ", i);
}
return 0;
}
注: 不能把if(flag == 1)
语句写成else
语句放在前一个for
循环里。例如,i等于102,j等于7,102 % 7 不为0,这时就会执行else
语句,这样就会把102误认为是素数打印出来。错误写法:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 100; i <= 200; i++)
{
int j = 0;
int flag = 1;//假设i是素数
for (j = 2; j <= i - 1; j++)
{
if (i % j == 0)
{
flag = 0;//i不是素数
break;
}
else
printf("%d ", i);
}
}
return 0;
}
法二: n = a * b,其中a和b可不可能都大于根号n?很显然是不可能的,若都大于根号n,则a乘b的结果肯定是大于n的,这与等于n是矛盾的。所以,a和b至少有一个值是小于等于根号n的,如果n不是素数,那么一定有一个因子在2到根号n之间,也就是说,若2到根号n之间有能整除n的数字,则n不是素数;若都没有能整除的,则n是素数。
#include <stdio.h>
#include <math.h>
int main()
{
int i = 0;
for (i = 100; i <= 200; i++)
{
int j = 0;
int flag = 1;
for (j = 2; j <= sqrt(i); j++)
//sqrt(i)表示根号i,sqrt()是库函数,需要包含头文件<math.h>
{
if (i % j == 0)
{
flag = 0;
break;
}
}
if (flag == 1)
printf("%d ", i);
}
return 0;
}
在上述代码的基础上其实还能优化,我们知道偶数肯定不是素数,所以在第一个for
循环上可以把偶数"过滤掉":
#include <stdio.h>
#include <math.h>
int main()
{
int i = 0;
for (i = 101; i <= 200; i += 2)
{
int j = 0;
int flag = 1;
for (j = 2; j <= sqrt(i); j++)
{
if (i % j == 0)
{
flag = 0;
break;
}
}
if (flag == 1)
printf("%d ", i);
}
return 0;
}
十一、goto语句
goto
语句可以实现在同一个函数内跳转到设置好的标号处。
例子:
#include <stdio.h>
int main()
{
printf("hehe\n");
goto next;
printf("haha\n");
next:
printf("hehe是呵呵\n");
return 0;
}
#include <stdio.h>
int main()
{
again:
printf("hehe\n");//死循环打印hehe
goto again;
return 0;
}
goto
语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以建议是能不用尽量不用。但是,goto
语句也不是一无是处,在多层循环的代码中,若想快速跳出,使用goto
语句就非常方便了。
for (...)
{
for (...)
{
for (...)
{
if (disaster)
goto error;
}
}
}
error:
//...
for
循环想提前退出就要用break
,一个break
只能跳出一层循环,有三层循环的嵌套就要用三个break
才能跳出循环,所以这种情况下用goto
语句就会快捷点。
练习: 使用goto
语句写一个关机程序。程序运行起来后,电脑将在一分钟后关机,但是,若输入:“人生是旷野,不是轨道”,就取消关机。
在搜索栏输入"cmd",然后点击"打开"
打开后如下图所示:
输入shutdown -s -t 60
(关机倒计时60秒),系统会弹出电脑将在一分钟后关机的提示。
再输入shutdown -a
(取消关机),系统会取消关机。
代码演示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char input[20] = { 0 };//输入的字符串放进字符数组里
system("shutdown -s -t 60");
again:
printf("请注意,你的电脑将在60秒后关机,若输入;“人生是旷野,不是轨道”,就会取消关机。\n");
scanf("%s", input);//输入的字符串就存储在input里
if (strcmp(input ,"人生是旷野,不是轨道") == 0)
{
system("shutdown -a");
}
else
goto again;
return 0;
}
注:
(1)system()
是一个库函数,这个函数是执行系统命令的,需要包含头文件<stdlib.h>
。
(2)字符串是不能使用==
比较大小的,不能写成:input == "人生是旷野,不是轨道"
,应该使用strcmp()
函数 - string compare,要包含头文件<string.h>
。strcmp()
如果判断两个字符串相等,则返回0
。
上述代码也可以用while
循环写:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char input[20] = { 0 };
system("shutdown -s -t 60");
while (1)
{
printf("请注意,你的电脑将在60秒后关机,若输入;“人生是旷野,不是轨道”,就会取消关机。\n");
scanf("%s", input);
if (strcmp(input, "人生是旷野,不是轨道") == 0)
{
system("shutdown -a");
break;
}
}
return 0;
}
标签:语句,main,int,循环,printf,include,表达式,分支
From: https://blog.csdn.net/2401_87255690/article/details/142875588