分支和循环(上)

目录

[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是否是闰年。

  1. 能被4整除并且不能被100整除是闰年
  2. 能被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;
}

上述的代码中,我们要注意的点有:

  1. case和后边的数字之间必须有空格
  2. 每一个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. 输入1~5,输出的是"工作日";
  2. 输如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

题目解析:

  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之前,就能到所有的位。
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 题目解析:

  1. 要从100~200之间找出素数,⾸先得有100~200之间的数,这⾥可以使⽤循环解决。
  2. 假设要判断i是否为素数,需要拿2~i-1之间的数字去试除i,需要产⽣2~i-1之间的数字,也可以使用循环解决。
  3. 如果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语句就会更加的快捷。

相关推荐
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
hikktn6 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
观音山保我别报错6 小时前
C语言扫雷小游戏
c语言·开发语言·算法
小林熬夜学编程9 小时前
【Linux系统编程】第四十一弹---线程深度解析:从地址空间到多线程实践
linux·c语言·开发语言·c++·算法
墨墨祺9 小时前
嵌入式之C语言(基础篇)
c语言·开发语言
躺不平的理查德9 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
幼儿园园霸柒柒11 小时前
第七章: 7.3求一个3*3的整型矩阵对角线元素之和
c语言·c++·算法·矩阵·c#·1024程序员节
好想有猫猫11 小时前
【51单片机】串口通信原理 + 使用
c语言·单片机·嵌入式硬件·51单片机·1024程序员节
摆烂小白敲代码12 小时前
背包九讲——背包问题求方案数
c语言·c++·算法·背包问题·背包问题求方案数