目录
[1. if语句](#1. if语句)
[1.1 if](#1.1 if)
[1.2 else](#1.2 else)
[1.3 分支中包含多条语句](#1.3 分支中包含多条语句)
[1.4 嵌套if](#1.4 嵌套if)
[1.5 悬空else问题](#1.5 悬空else问题)
[2. 关系操作符](#2. 关系操作符)
[3. 条件操作符](#3. 条件操作符)
[4. 逻辑操作符](#4. 逻辑操作符)
[4.1 逻辑取反操作符](#4.1 逻辑取反操作符)
[4.2 逻辑与运算符](#4.2 逻辑与运算符)
[4.3 逻辑或运算符](#4.3 逻辑或运算符)
[4.4 连续:闰年的判断](#4.4 连续:闰年的判断)
[4.5 短路](#4.5 短路)
[5. switch语句](#5. switch语句)
[5.1 if语句和switch语句的对比](#5.1 if语句和switch语句的对比)
[5.2 switch语句中的break](#5.2 switch语句中的break)
[5.3 switch语句中的default](#5.3 switch语句中的default)
[5.4 case和default的顺序](#5.4 case和default的顺序)
[6. while循环](#6. while循环)
[6.1 if和while的对比](#6.1 if和while的对比)
[6.2 while语句的执行流程](#6.2 while语句的执行流程)
[6.2 while循环的实践](#6.2 while循环的实践)
[6.4 练习](#6.4 练习)
[7. for循环](#7. for循环)
[7.1 语法形式](#7.1 语法形式)
[7.2 for循环的执行流程](#7.2 for循环的执行流程)
[7.3 for循环的实践](#7.3 for循环的实践)
[7.4 while循环和for循环的对比](#7.4 while循环和for循环的对比)
[7.5 练习](#7.5 练习)
[8. do while循环](#8. do while循环)
[8.1 语法形式](#8.1 语法形式)
[8.2 do while循环的执行流程](#8.2 do while循环的执行流程)
[8.3 do while循环的实践](#8.3 do while循环的实践)
[8.4 练习](#8.4 练习)
[9. break和continue语句](#9. break和continue语句)
[9.1 while循环中的continue和break](#9.1 while循环中的continue和break)
[9.1.1 break举例](#9.1.1 break举例)
[9.1.2 continue举例](#9.1.2 continue举例)
[9.2 for循环中的continue和break](#9.2 for循环中的continue和break)
[9.2.1 break举例](#9.2.1 break举例)
[9.2.2 continue举例](#9.2.2 continue举例)
[9.3 do while循环中的continue和break](#9.3 do while循环中的continue和break)
[9.3.1 break举例](#9.3.1 break举例)
[9.3.2 continue举例](#9.3.2 continue举例)
[10. 循环的嵌套](#10. 循环的嵌套)
[10.1 练习](#10.1 练习)
[10.2 题目解析:](#10.2 题目解析:)
[10.3 代码](#10.3 代码)
[11. goto语句](#11. goto语句)
C语言是结构化的程序设计语言,这里的结构指的是顺序结构、选择结构、循环结构、C语言是能够实现这三种结构的,其实我们如果仔细分析,我们日常中的事情都可以拆分为这三种结构或者这三种结构的组合。
我们可以使用if、switch实现分支结构,使用for、while、do while、实现循环结构。
1. if语句
1.1 if
if的语法形式:
cpp
if(表达式)
语句;
表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行。
在C语言中,0为假,非0为真,也就是说表达式的结构如果是0,则语句不执行,表达式的结构如果为非0,则语句执行。
cpp
#include <stdio.h>
int main()
{
if (1 == 2)
printf("hello world\n");
return 0;
}
这段代码是不会输出任何结果的,因为1是不可能等于2的。
cpp
#include <stdio.h>
int main()
{
if (2 == 2)
printf("hello world\n");
return 0;
}
那如果改成2和2判断相等,条件肯定为真,所以屏幕上就输出hello world。
**例子:**输入一个整数,判断是否为奇数
cpp
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
if (a % 2 != 0)
printf("%d是奇数\n", a);
return 0;
}
1.2 else
如果一个数不是奇数,那么就肯定是偶数,对于任意一个数,我们要清楚的判断是奇数还是偶数,那么这个时候就需要用到if....else....语句了。
cpp
if(表达式)
语句1;
else
语句2;
**例子:**输入一个整数,判断是否为奇数,如果是奇数就打印奇数,是偶数就打印偶数。
cpp
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
if (a % 2 != 0)
printf("%d是奇数\n", a);
else
printf("%d是偶数\n", a);
return 0;
}
练习:输入一个年龄,>=18岁就输出:成年,否则就输出:未成年
cpp
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18)
printf("成年\n");
else
printf("未成年\n");
return 0;
}
1.3 分支中包含多条语句
默认在if和else语句中默认都控制一条语句。所以我们要控制一条语句以上的化就得加大括号。
cpp
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18)
printf("成年\n");
printf("可以谈恋爱了\n");
return 0;
}
上面的代码,你会发现输入的值不管是>=18还是<18,"可以谈恋爱"都会打印在屏幕上。
这是因为 if 语句只能控制⼀条语句,就是 printf(" 成年了 \n"); ,if语句为真,则打印成年了, if语句为假,则不打印,对于 printf(" 可以谈恋爱了 \n"); 是独⽴存在的,不管if语句的条件的真假,都会被执⾏。那如果我们要if语句同时控制2条语句,怎么办呢?那就要使⽤ else 后也可以跟上大括号。如下:
cpp
#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;
}
1.4 嵌套if
在if else语句中,else可以与另一个if语句连用,构成多重判断。
比如:要求输入一个整数,判断输入的整数时是0,还是正数或者负数。
cpp
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num == 0)
printf("输入的值是0\n");
else
{
if (num > 0)
printf("输入的值是正数\n");
else
printf("输入的值是负数\n");
}
return 0;
}
这段代码我们还可以改造一下。
cpp
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
if (num == 0)
printf("输入的值是0\n");
else if (num > 0)
printf("输入的值是正数\n");
else
printf("输入的值是负数\n");
return 0;
}
有了嵌套if语句,就可以完成更多复杂逻辑的判断。
练习:
输⼊⼀个⼈的年龄
如果年龄 <18 岁,打印 " 少年 "
如果年龄在 18 岁⾄ 44 岁打印 " ⻘年 "
如果年龄在 45 岁⾄ 59 岁打印 " 中⽼年 "
如果年龄在 60 岁⾄ 89 岁打印 " ⽼年 "
如果 90 岁及以上打印 " ⽼寿星 "
代码:
cpp
#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;
}
1.5 悬空else问题
如果有多个if和else,可以记住这样一条规则,else总是跟最近的if匹配。
cpp
#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;
}
a是0,不等于1,条件为假,走else,打印哈哈,当你这样想的时候就错了。
当我运行代码的时候,发现什么都不输出。
这就是悬空else的问题,如果有多个 的 if 匹配。上⾯的代码排版,让 if 和 else ,可以记住这样⼀条规则, else 总是跟最接近的if匹配。
else 和第⼀个 if 语句对齐,让我们以为 语句不成立的时候,⾃然想到的就是执行else子句,打印 else 是和第⼀个if匹配的,当 进⾏匹配的,这样后边的 haha ,但实际上 if...else 语句是嵌套在第⼀个if else 是和第⼆个 if 成立,嵌套 if 和 if 语句中的,如果第⼀个 if 语句就不 else 就没机会执⾏了,最终啥都不打印。
如果代码改成下⾯这样就更加容易理解了。
cpp
#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. 关系操作符
C语言用于比较的表达式,称为"关系表达式"(relational expression),里面使用的运算符就称为"关系运算符"(relational operator),主要有下面6个。
- > 大于运算符
- < 小于运算符
- >= 大于等于运算符
- <= 小于等于运算符
- == 相等运算符
- != 不相等运算符
例子:
cpp
a == b;
a != b;
a < b;
a > b;
a <= b;
a >= b;
关系表达式通常返回0或1,表示真假。
C语言中,0表示假,所有非0表示真,比如20 > 12返回1,12 > 20返回0。
关系表达式常用于if或while结构。
cpp
if (x == 3) {
printf("x is 3.\n");
}
注意:相等运算符 == 与赋值运算符 = 是两个不一样的运算符,不要混淆,有可能会写成下面的代码,但是这种代码可以运行,结构就是意料之外的。
cpp
if (a = 3)
{
//....
}
上面的示例中,原本是x == 3,但是不小心写成x = 3。这个式子的意思就是对变量x 进行赋值,它的返回值为3,所以if判断总是为真。
为了防止这种错误,有的程序员喜欢将变量写在等号的右边。
cpp
if(x == x)
{
//......
}
如果这样写的化吧 == 写成 = ,编译器就会报错。
cpp
if(3 = x)
{
//.....err - 常量不能赋给变量
}
另一个需要避免的错误是:多个关系运算符不宜连用。
cpp
#include <stdio.h>
int main()
{
int a = 10;
int b = 8;
int c = 5;
if (a < b < c)
printf("hello world!\n");
return 0;
}
这种代码能输出是因为表达式是从左到右依次计算,a < b条件为假,也就是为0,0 < 5,条件为真,大于输出。
所以我们应该这样写。
cpp
#include <stdio.h>
int main()
{
int a = 10;
int b = 8;
int c = 5;
if (a < b && b < c)
printf("hello world!\n");
return 0;
}
比如:我们输入一个年龄,如果年龄在18岁~36岁之间,我们输出青年。
cpp
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
//if ( 18 <= age <= 36) - err
if (age >= 18 && age <= 36)
{
printf("青年\n");
}
return 0;
}
3. 条件操作符
条件操作符也叫三目操作符,需要接收三个操作数的。
cpp
exp1 ? exp2 : exp3
条件操作符的计算逻辑是:如果exp1为真,exp2计算,计算的结果是整个表达式的结果。如果exp1为假,exp3计算,计算的结果是整个表达式的结果。
例子:如果a大于10的话b是1,否则b就是-1。
cpp
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d", &a);
if (a > 10)
b = 1;
else
b = -1;
printf("b = %d\n", b);
}
那么针对这段代码,我们就可以使用三目操作符。
cpp
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d", &a);
b = a > 10 ? 1 : -1;
printf("b = %d\n", b);
return 0;
}
使用条件表达式实现找两个数中的较大值。
cpp
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int max = a > b ? a : b;
printf("较大值是:%d\n", max);
return 0;
}
4. 逻辑操作符
逻辑操作符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。
- ! : 逻辑取反运算符(改变单个表达式的真假)。
- && :逻辑与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。
- || : 逻辑或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)。
注 :在C语言中,非0表示真,0表示假
4.1 逻辑取反操作符
代码:
cpp
#include <stdio.h>
int main()
{
int flag = 0;
scanf("%d", &flag);
if (!flag)
{
printf("hello world!\n");
}
return 0;
}
输入1,为真,逻辑反操作变成假,不进入判断,则什么都不输出。
输入0,为假,逻辑反操作变成真,进入判断,输出hello world。
4.2 逻辑与运算符
&& 就是与运算符,也是并且的意思, && 是一个双目操作符,使用的方式是a&&b,&&两边的表达式都是真的时候,整个表达式才为真,只要有一个为假,则整个表达式为假。
比如:如果我们用代码实现判断春天,我们应该怎么写呢?
cpp
#include <stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month >= 3 && month <= 5)
{
printf("春天\n");
}
return 0;
}
这里表达的意思是month既要大于等于3,又要小于等于5,必须同时满足。
4.3 逻辑或运算符
|| 就是或运算符,也就是或者的意思, || 也是一个双目操作符,使用的方式是 a || b, ||两边的表达式只要有一个是真的,整个表达式就是真的,两边的表达式都为假的时候,才为假。
比如:我们说一年中月份是12月或者1月或则2月是冬天,那么我们怎么使用代码体现呢?
cpp
#include <stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month == 1 || month == 2 || month == 12)
printf("冬天\n");
return 0;
}
4.4 连续:闰年的判断
输入一个年份year,判断year是否是闰年。
- 能被4整除并且不能被100整除是闰年
- 能被400整除是闰年
代码:
cpp
#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);
}
return 0;
}
这个代码我们还可以优化一下。
cpp
#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);
return 0;
}
4.5 短路
C语言逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。
如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值,这种情况称为"短路"。
cpp
if(month >= 3 && month <= 5)
{
//.........
}
表达式中&&的做操作数是month >= 3,右操作数是month <= 5,当左操作数month >= 3的结果是0的时候,即使不判断month <= 5,整个表达式的结果也是0,不是春天。
所以对于&&操作符来说,左边操作数是0的时候,右边操作数不再执行。
那么对于||操作符是怎么样呢?
cpp
if(month == 1 || month == 2 || month == 12)
{
//..........
}
如果month == 1,则不用再判断month是否等于1或者2,整个表达式的结果也是1,是冬季。
所以, || 操作符的左操作数的结果不为0时,就无需执行右操作数。
像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。
下面代码的执行结果是什么?
cpp
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("i = %d\n a = %d\n b = %d\n c = %d\nd = %d\n",i, a, b, c, d);
return 0;
}
因为a++是后置++,所以是先用,后++,此时第一个表达式的结果为0,对于&&来说,第一个表达式为0,后面的表达式则不用计算,整体表达式为0,那么第一个&&的结果就是0,第二个&&的左边是0,那么右边也是0,所以整个表达式的结果就是0,所以i = 0,a = 1,b = 2,c = 3.d = 4。
当我们把&&改为||结果又是什么呢?
cpp
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++||++b||d++;
printf("i = %d\n a = %d\n b = %d\n c = %d\nd = %d\n",i, a, b, c, d);
return 0;
}
a++,后置++,先使用,后计算,第一个表达式为假,则计算第二个表达式,前置++,先++,后使用,所以b = 3,则第一个||为真,对于||运算来说左边的表达式为真 ,则不再计算右边的表达式,所以整体表达式为真,则i = 1,a = 1,b = 3,c = 3,d = 4
5. switch语句
除了if语句外,C语言还提供了switch语句来实现分支结构,switch就是开关的意思。
switch语句是一种特殊形式的if....else结构,用于判断条件有多个结果的情况,它把多重的else if改写成易用,可读性更好的形式,但是有的else if语句改成switch的话特别别扭。
cpp
switch(expression)
{
case value1: statement
case value2: statement
default: statement
}
上面代码中,根据表达式expression不同的值,执行相应的case分支,如果找不到对应的值,就执行default分支。
注:
- switch后的expression必须是整型表达式
- case后的值,必须是整型常量表达式
- 比如浮点数就不行,字符类型可以,因为字符类型也是归类到整型家族的,因为字符本质就是ASCII码值,而ASCII码值是整数。
5.1 if语句和switch语句的对比
输入任意一个整数值,计算除3之后的余数。
代码:
cpp
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if (n % 3 == 0)
printf("余数是0\n");
else if (n % 3 == 1)
printf("余数是1\n");
else if (n % 3 == 2)
printf("余数是2\n");
return 0;
}
如果用switch写的话就可以这样写。
cpp
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch (n % 3)
{
case 0:
printf("余数是0\n");
break;
case 1:
printf("余数是1\n");
break;
case 2:
printf("于是是2\n");
break;
}
return 0;
}
上述的代码中,我们要注意的点有:
- case和后边的数字之间必须有空格
- 每一个case语句中的代码执行完成后,需要加上break,才能跳出这个switch语句 。
5.2 switch语句中的break
break是打断,停止的意思。
前面的代码,如果我们去掉break,会出现什么情况呢?
cpp
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch (n % 3)
{
case 0:
printf("余数是0\n");
case 1:
printf("余数是1\n");
case 2:
printf("于是是2\n");
}
return 0;
}
switch语句具有透传功能,所以要加上break,当我们输入3,余数是0,从case0进入,打印,打印完成没有遇到break,就继续执行case2,直到遇到break,或者代码运行完成。
当然,break也不是每个case语句都得有,这就得根据实际情况来看了。
练习:
输⼊⼀个1~7的数字,打印对应的星期⼏
例如:
输⼊:1 输出:星期⼀ 输⼊:
2 输出:星期⼆ 输⼊:
3 输出:星期三 输⼊:
4 输出:星期四 输⼊:
5 输出:星期五 输⼊:
6 输出:星期六 输⼊:
7 输出:星期天
代码:
cpp
#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~5,输出的是"工作日";
- 输如6~7,输出的是"休息日";
代码:
cpp
#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;
}
return 0;
}
5.3 switch语句中的default
在使用switch语句的时候,我们这里经常可能遇到一种情况,比如switch后的表达式中的值无法匹配代码中的case语句的时候,这个时候要不就不做处理,要不就在switch中加入default子句。
cpp
switch (expression) {
case value1: statement
case value2: statement
default: statement
}
switch后面的expression的结果不是value1,也不是value2的时候,就会执行default子句。
就比如前面写的打印星期的代码,如果day的值不是1~7的时候,我们就要提示。
cpp
#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("输入错误,输入的范围应在1~7");
break;
}
return 0;
}
5.4 case和default的顺序
在switch语句中case子句和default子句是没有顺序要求的,只要顺序是满足实际需求的就可以。
不过我们通常是把default子句放在最后处理的。
6. while循环
C语言提供了3种循环语句,while就是其中一种,while语句的语法结构和if语句非常相似。
6.1 if和while的对比
cpp
if(表达式)
语句;
while(表达式)
语句;//如果循环体要包含更多的语句,就要加上大括号
对比:
cpp
//if
#include <stdio.h>
int main()
{
if (1)
printf("hello world!\n");//条件满足,打印一次
return 0;
}
cpp
//while
#include <stdio.h>
int main()
{
while (1)
printf("hello world!\n");//条件满足,循环打印
return 0;
}
while是实现循环的。
6.2 while语句的执行流程
首先上来就是执行判断表达式,表达式的值为0,循环直接结束,表达式的值不为0,则执行循环语句,语句执行完后再继续判断,是否进入循环。
6.2 while循环的实践
在屏幕上打印1~10的值。
cpp
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
printf("%d ", i);
i++;
}
return 0;
}
6.4 练习
输⼊⼀个正的整数,逆序打印这个整数的每⼀位
例如:
输⼊:1234,输出:4321
输⼊:521,输出:125
题目解析:
- 要想得到n的最低位,可以使⽤n%10的运算,得到的余数就是最低位,如:1234%10得到4
- 要想去掉n的最低位,找出倒数第⼆位,则使⽤ n=n/10操作就可以去掉最低位的,如: n=1234/10得到123,123相较于1234就去掉了最低位,123%10就得到倒数第⼆位3。
- 循环1和2两个步骤,在n变成0之前,就能到所有的位。
cpp
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
while (a)
{
printf("%d ", a % 10);
a /= 10;
}
return 0;
}
7. for循环
7.1 语法形式
for循环时三种循环种使用最多的。
cpp
for(表达式1; 表达式2; 表达式3)
语句;//如果循环体想包含更多的语句,可以加上⼤括号
- 表达式1用于循环变量的初始化
- 表达式2用于循环结束条件的判断
- 表达式3用于循环变量的调整
7.2 for循环的执行流程
⾸先执⾏ ==0,则循环结束; 表达式 2 的判断部分,表达式 2 的结果如果表达式2的结果如果!=0则执⾏循环语句,循环语句执行完后,再去执行表表达式2 的执行执⾏判断,3调整循环变量,然后再去达式表达式2的结果是否为0,决定循环是否继续。
整个循环的过程中,表达式1初始化部分只被执行1次,剩下的就是表达式2、循环语句、表达式3,再循环。
7.3 for循环的实践
在屏幕上打印1~10的值。
代码:
cpp
#include <stdio.h>
int main()
{
for (int i = 1; i <= 10; i++)
{
printf("%d ", i);
}
return 0;
}
运行结果:
7.4 while循环和for循环的对比
for和while在实现循环的过程中都有初始化、判断、调整这三个部分,但是 分⾮常集中,便于代码的维护,而如果代码较多的时候式上for 循环要更优⼀些。
7.5 练习
计算1~100之间3的倍数的数字之和。
代码:
cpp
#include <stdio.h>
int main()
{
int sum = 0;
for (int i = 1; i <= 100; i++)
{
if (i % 3 == 0)
{
sum += i;
}
}
printf("%d\n", sum);
return 0;
}
其实我们还可以对这个代码优化一下。
cpp
#include <stdio.h>
int main()
{
int sum = 0;
for (int i = 0; i <= 100; i+=3)
{
sum += i;
}
printf("%d\n", sum);
return 0;
}
8. do while循环
8.1 语法形式
在循环语句中do while语句使用最少。
cpp
do
语句;
while(表达式);
while和for这两种循环都是先判断,条件满足就进入循环,执行循环语句,如果不满足就跳出循环。
而do while循环则是先直接进入循环体,执行循环语句,然后再执行while后的判断表达式,表达式为真,就会进行下一次循环,表达式为假,则不再继续循环。
8.2 do while循环的执行流程
在do while循环中先执⾏图上的"语句",执⾏完语句,在去执⾏"判断表达式",判断表达式的结果是!=0,则继续循环,执⾏循环语句;判断表达式的结果==0,则循环结束。
所以在do while语句中循环体是⾄少执行⼀次的,这是 do while 循环比较特殊的地方。
8.3 do while循环的实践
在屏幕上打印1~10的值。
cpp
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
一般do while使用在循环体至少被执行一次的场景下,所以较少一些。
8.4 练习
输⼊⼀个正整数,计算这个整数是几位数?
例如:
输⼊:1234 输出:4
输⼊:12 输出:2
cpp
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
int i = 0;
do
{
i++;
num /= 10;
} while (num);
printf("%d\n", i);
return 0;
}
这里并非使用do while语句,但是这个代码就比较适合使用do while语句,因为即使n是0,也是1位数。
9. break和continue语句
在循环执行的过程中,如果某些状况发生的适合,需要提前终止循环,这是非常常见的现象。C语言中提供了break和continue两个关键字,就是应用到循环中的。
- break的作用是用于永久的终止循环,只要break被执行,直接就会跳出循环,继续往后执行。
- continue的作用是跳过本次循环中的continue后面的代码,在for循环和while循环中有所差异。
9.1 while循环中的continue和break
9.1.1 break举例
cpp
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
break;
printf("%d ", i);
i++;
}
return 0;
}
运行结果:
打印了1,2,3,4后,当i等于5的时候,循环在 break 的地地方终止,不再打印,不再循环。
所以break的作⽤就是永久的终止循环,只要break被执行, break 外的第⼀层循环就终止了。 那以后我们在循环中,想在某种条件下终止循环,则可以使⽤break来完成我们想要的效果。
9.1.2 continue举例
cpp
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
continue;
//当i等于5后,就执行continue,直接跳过后面的代码
//使得调整部分也跳过了,所以代码会死循环
printf("%d ", i);
i++;
}
return 0;
}
到这⾥我们就能分析出来, continue 可以帮助我们跳过某⼀次循环 continue 后边的代码,直接 到循环的判断部分,进行下⼀次循环的判断,如果循环的调整是在 continue 后边的话,可能会造成死循环。
9.2 for循环中的continue和break
9.2.1 break举例
和while循环中的break一样,for循环中的break也是用于终止循环。
cpp
#include <stdio.h>
int main()
{
for (int i = 1; i <= 10; i++)
{
if (5 == i)
break;
printf("%d ", i);
}
return 0;
}
运行结果:
break的作用是永久的终止循环。
9.2.2 continue举例
cpp
#include <stdio.h>
int main()
{
for (int i = 1; i <= 10; i++)
{
if (5 == i)
continue;
printf("%d ", i);
}
return 0;
}
运行结果:
所以在 for 循环中continue 的作⽤是跳过本次循环中 continue 后的代码,直接去到循环的调 整部分。未来当某个条件发⽣的时候,本次循环⽆需再执行后续某些操作的时候,就可以使用 continue来实现。
while循环中和for循环中continue的区别。
在while循环中continue跳过了调整部分,使得代码死循环,而在for循环中continue没有跳过调整部分,知识当i是5的适合,跳过打印而已,不会造成死循环。
9.3 do while循环中的continue和break
9.3.1 break举例
cpp
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (5 == i)
break;
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
运行结果:
当i为5的时候跳出循环,所以只打印1,2,3,4。
9.3.2 continue举例
cpp
#include <stdio.h>
int main()
{
int i = 1;
do
{
if (5 == i)
continue;
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
运行结果:
当i是5的时候执行continue,跳过了调整部分,使得代码死循环。
10. 循环的嵌套
前⾯学习了三种循环 while 、 do while、 for ,这三种循环往往会嵌套在⼀起才能更好的解决问题,就是我们所说的:循环嵌套。
10.1 练习
找出100~200之间的素数,并打印在屏幕上。
注:素数又称质数,只能被1和本身整除的数字。
10.2 题目解析:
- 要从100~200之间找出素数,⾸先得有100~200之间的数,这⾥可以使⽤循环解决。
- 假设要判断i是否为素数,需要拿2~i-1之间的数字去试除i,需要产⽣2~i-1之间的数字,也可以使用循环解决。
- 如果2~i-1之间有数字能整除i,则i不是素数,如果都不能整除,则i是素数。
10.3 代码
cpp
#include <stdio.h>
#include <math.h>//sqrt头文件
//sqrt是一个库函数 - 计算平方根的
int main()
{
int flag = 0;
//for (int i = 100; i <= 200; i++)
for (int i = 101; i <= 200; i+=2)//优化:偶数都是素数 - 可以排除
{
flag = 0;//假设i是素数
//for (int j = 2; j <= i - 1; j++)
for (int j = 2; j <= sqrt(i); j++)//优化:
/*
如果 m = a * b
那么a和b中至少有一个数字是<= 开平方m的(根号m)
16 = 4 * 4
= 2 * 8
如果要判断i是否是素数时,只要判断2~根号i之间
有因子能整除i就说明不是素数
*/
{
if (i % j == 0)
{
flag = 1;//不是素数
break;
}
}
if (!flag)//如果是素数就打印
printf("%d ", i);
}
return 0;
}
11. goto语句
C语言提供了一种非常特别的语法,就是goto语句和跳转标号,goto语句可以实现在同一函数内跳转到设置好的标号处。
例如:
cpp
#include <stdio.h>
int main()
{
printf("1\n");
goto next;
printf("2\n");
next:
printf("3\n");
return 0;
}
输出结果:
当执行到goto语句的地方,就直接到next地方,跳过了2的打印,所以打印1,3。
goto语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以我们的建议是能不⽤尽量不去使⽤;但是使⽤ goto 就⾮常的方便了。
cpp
for (...)
{
for (...)
{
for (...)
{
if (disaster)
goto error;
}
}
}
error:
//...
for循环想提前退出得使用break,一个break只能跳出一层for循环,如果3层循环嵌套就得使用3个break才能跳出循环,所以在这种情况下我们使用goto语句就会更加的快捷。