C语言 第三讲:分支和循环(上)

目录

正文开始

一,if语句

[1.1 if](#1.1 if)

[1.2 else](#1.2 else)

[1.3 分支中包含多条语句](#1.3 分支中包含多条语句)

[1.3 嵌套if](#1.3 嵌套if)

[1.5 悬空else问题](#1.5 悬空else问题)

二,关系操作符

三,条件操作符

四,逻辑操作符:&&,||,!

[4.1逻辑取反运算符 !](#4.1逻辑取反运算符 !)

[4.2逻辑与运算符 &&](#4.2逻辑与运算符 &&)

[4.3逻辑或运算符 ||](#4.3逻辑或运算符 ||)

4.4练习:闰年的判断

[4.5 短路](#4.5 短路)

五,switch语句

5.1if语句和switch语句的对比

[5.2 switch语句中的break](#5.2 switch语句中的break)

5.3switch语句中的default

[5.4 switch语句中的case和default顺序问题](#5.4 switch语句中的case和default顺序问题)

[六, while循环](#六, while循环)

[6.1 if和while的对比](#6.1 if和while的对比)

[6.2 while语句的执行流程](#6.2 while语句的执行流程)

[6.3 while循环的实践](#6.3 while循环的实践)

6.4练习

[七, for循环](#七, 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练习

[八, do-while循环](#八, do-while循环)

8.1语法形式

[8.2 do while循环的执行流程](#8.2 do while循环的执行流程)

[8.3 do while循环的实践](#8.3 do while循环的实践)

8.4练习

九,break和continue语句

[9.1 while循环中的break和continue](#9.1 while循环中的break和continue)

[9.1.1 break举例](#9.1.1 break举例)

[9.1.2 continue举例](#9.1.2 continue举例)

[9.2 for循环中的break和continue](#9.2 for循环中的break和continue)

[9.2.1 break举例](#9.2.1 break举例)

9.2.2

[9.3 do while循环中的break和continue](#9.3 do while循环中的break和continue)

十,循环的嵌套

10.1练习

10.2题目解析

10.3参考代码

优化

十一,goto语句

11.1"趣味"小程序


正文开始

C语言是结构化的程序设计语言,这里的结构指的是顺序结构、选择结构、循环结构,C语言是能够实现这三种结构 的,其实我们如果仔细分析,我们日常所见的事情都可以拆分为这三种结构或者这三种结构的组合。 我们可以使用if、switch实现分支结构,使用for、while、do while实现循环结构。

一,if语句

1.1 if

if语言的语法形式如下:

cs 复制代码
if(表达式)
	语句

表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行 在C语言中,0为假,非0表示真,也就是表达式的结果如果是0,则语句不执行,表达式的结果如果不是0,则语句执行。

例子:输入一个整数,判断是否为奇数

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	if(num % 2 == 1)//== 判断相等
		printf("%d 是奇数\n", num);
	//if(num % 2 == 0)	加上这行代码可以让偶数也打印出来,但是这里解释if语句便不使用
		//printf("%d 是偶数\n", num);
	return 0;
}

1.2 else

如果一个数不是奇数,那就是偶数了,如果任意一个整数,我们要清楚的判断是奇数还是偶数怎么表示呢? 这里就需要 if...else... 语句了,语法形式如下:

cs 复制代码
if(表达式)
	语句1
else
	语句2

例子:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则是偶数

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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;
}

练习

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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 语句中默认都只控制一条语句,比如:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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后也可以跟上大括号。如下:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if(age >= 18) //if 后使用{}控制多条语句-这个块也叫程序块,或者复合语句
	{
		printf("成年\n");
		printf("可以谈恋爱了\n");
	}
	return 0;
}
cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if(age >= 18) //if 后使用{}控制多条语句-这个块也叫程序块,或者复合语句
	{
		printf("成年\n");
		printf("可以谈恋爱了\n");
	}
	else //else后使用{}控制多条语句-这个块也叫:程序块或者复合语句
	{
		printf("未成年\n");
		printf("不可以谈恋爱\n");
	}
	return 0;
}

1.3 嵌套if

在 if else 语句中, else 可以与另一个if语句连用,构成多重判断。 比如:要求输入一个整数,判断输入的整数是0,还是正数或者负数。请看如下代码:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	if(num == 0)
		printf("输入的数字是0\n");
	else if(num > 0)
		printf("输入的数字是正数");
	else
		printf("输入的数字是负数")
	return 0;
}

上图中橙色背景的代码就是嵌套在前面的e1se子句中的,构成了嵌套的if语句。 再比如: 输入一个整数,如果是正数,再判断是奇数还是偶数,并输出;如果不是正数则输出:非正数。

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	if (num % 2 == 0)
		printf("输入的数字是偶数\n");
	else if (num % 2 == 1)
		printf("输入的数字是奇数\n");
	else
		printf("输入的数字是负数\n");
	return 0;
}

1输入一个人的年龄

2如果年龄<18岁,打印"少年·

3如果年龄在18岁至44岁打印"青年"

4如果年龄在45岁至59岁打印"中老年"

5如果年龄在60岁至89岁打印"老年"

6如果90岁及以上打印"老寿星"

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int age = 0;
	printf("请输入你的年龄:");
	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("老寿星");
	return 0;
}

1.5 悬空else问题

如果有多个if和else,可以记住这样一条规则,else总是跟最接近的if匹配。

我们首先从下面代码开始

cs 复制代码
#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,那就执行e1se子句,打印haha 但是当你去运行代码,输出的结果是:啥都不输出。

二,关系操作符

C语言用于比较的表达式,称为"关系表达式"(relationalexpression),里面使用的运算符就称为"关系运算符" (relational operator),主要有下面6个。

>大于运算符

<小于运算

>=大于等于运算符

<=小于等于运算符

==相等运算符

!=不相等运算符

下面是一些例子。

cs 复制代码
a == b;
a != b;
a < b;
a > b;
a <= b;
a >= b;

关系表达式通常返回0或1,表示真假。 C语言中,0表示假,所有非零值表示真。

比如,20 > 12返回1,12>20返回0。

关系表达式常用于if或while结构。

cs 复制代码
if (x == 3)
{
	printf("x is 3.\n");
}

注意:相等运算符与赋值运算符 = 是两个不一样的运算符,不要混淆。有时候,可能会不小心写出下面的代 码,它可以运行,但很容易出现意料之外的结果。

cs 复制代码
if (x = 3)...

上面示例中,原意是 × == 3 ,但是不小心写成x = 3。这个式子表示对变量x赋值3,它的返回值为3,所以 if判断总是为真。

为了防止出现这种错误,有的程序员喜欢将变量写在等号的右边。

cs 复制代码
if (3 == x)...

这样的话,如果把误写成,编译器就会报错。

cs 复制代码
/*报错*/
if (3 = x)...

另一个需要避免的错误是:多个关系运算符不宜连用

cs 复制代码
i < j < k
cs 复制代码
#include <stdio.h>
int main()
{
	int a = 1;
	int b = 7;
	int c = 5;
	if(a < b < c)
		printf("hehe\n");
	else
		printf("haha\n");
	return 0;
}

这句话语法是没问题的,但是逻辑上是有问题的先是a<b判断为1(正确),在判断1<c判断为真所以输出hehe

上面示例中,连续使用两个小于运算符。这是合法表达式,不会报错,但是通常达不到想要的结果,即不是保证变 量j的值在i和k之间。因为关系运算符是从左到右计算,所以实际执行的是下面的表达式。

cs 复制代码
(i < j) < k

上面式子中,i < j返回0 或 1,所以最终是0或1与变量k进行比较。如果想要判断变量j的值是否在i和 k之间,应该使用下面的写法。

cs 复制代码
i < j && j < k
cs 复制代码
#include <stdio.h>
int main()
{
	int a = 1;
	int b = 7;
	int c = 5;
	if(a < b && b < c)
		printf("hehe\n");
	else
		printf("haha\n");
	return 0;
}

比如:我们输入一个年龄,如果年龄在18岁~36岁之间,我们输出青年。 如果我们这样写

cs 复制代码
#include <stdio.h>
int main()
{
	int age = 0;
	printf("请输入你的年龄");
	scanf("%d", &age);
	if(18<=age<=36)
	{
		printf("青年\n");
	}
	return 0;
}

这是因为,我们先拿18和age中存放的10比较,表达式18<=10为假,18<=age的结果是0,再拿0和36比较, 0<=36为真,所以打印了青年,所以即使当age是10的时候,也能打印青年,逻辑上是有问题,这个代码应该怎 么写呢?

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int age = 0;
	printf("请输入你的年龄");
		scanf("%d", &age);
	if (18 <= age && age <= 36)
	{
		printf("青年\n");
	}
	return 0;
}

以上就是关于操作符,我们需要掌握的,剩下的只要按照字面意思理解使用就行,没有特别注意的。

三,条件操作符

条件操作幅符也叫三目操作符,需要接受三个操作数的,形式如下;

cs 复制代码
exp1 ? exp2 : exp3

条件操作符的计算逻辑是:如果exp1为真,exp2计算,计算的结果是整个表达式的结果;如果exp1为假, exp3计算,计算的结果是整个表达式的结果。

练习1:使用条件操作符表示下面代码的逻辑

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d", &a);
	if (a > 5)
		b = 3;
	else
		b = -3;
	printf("%d\n", b);
	return 0;
}
cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d", &a);
	b = (a == 5 ? 3 : -3);
	printf("%d", b);
	return 0;
}

练习2:使用条件表达式实现找两个数中的最大值

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a , &b);
	int m = (a < b ? b : a);
	printf("%d", m);
	return 0;
}

四,逻辑操作符:&&,||,!

逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。

!:逻辑取反运算符(改变单个表达式的真假)。

&&:逻辑与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。

||:逻辑或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)。

注:C语言中,非0表示真,0表示假

4.1逻辑取反运算符 !

比如,我们有一个变量叫f1ag,如果flag为假,要做一个什么事情,就可以这样写代码:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int flag = 0;
	scanf("%d", &flag);
	if(!flag)
	{
		printf("do something\n");	
	}
	return 0;
}

如果flag为真,flag就是假,如果flag为假,flag就是真 所以上面的代码的意思就是f1ag为假,执行if语句中的代码。

4.2逻辑与运算符 &&

&&就是与运算符,也是并且的意思,&&是一个双目操作符,使用的方式是a&&b,&&两边的表达式都是真的时 候,整个表达式才为真,只要有一个是假,则整个表达式为假。

比如:如果我们说月份是3月到5月,是春天,那使用代码怎么体现呢?

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int month = 0;
	scanf("%d", &month);
	if(month >= 3 && month <= 5)
	{
		printf("是春天");
	}
	return 0;
}

4.3逻辑或运算符 ||

||就是或运算符,也就是或者的意思,||也是一个双目操作符,使用的方式是a || b,|| 两边的表达式 只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假。

比如:我们说一年中月份是12月或者1月或者2月是冬天,那么我们怎么使用代码体现呢?

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int month = 0;
	scanf("%d", &month);
	if(month == 12 || month == 1 || month == 2)
		printf("是冬天");
	return 0;
}

4.4练习:闰年的判断

输入一个年份year,判断year是否是闰年

闰年判断规则

1.能被4整除并且不能被100整除

2.能被400整除

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int year = 0;
	scanf("%d", &year);
	if(year % 4 ==0 && year % 100 != 0)
		printf("是闰年");
	else if(year % 400 == 0)
		printf("是闰年");
	else
		printf("不是闰年");
	return 0;
}
cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int year = 0;
	scanf("%d", &year);
	if((year % 4 ==0 && year % 100 != 0) || (year % 400 == 0))
		printf("是闰年");
	return 0;
}

4.5 短路

C语言逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。 如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为"短路"。 如前面的代码:

cs 复制代码
if(month >= 3 && month <= 5)

表达式中&&的左操作数是month>=3,右操作数是month<=5,当左操作数month>=3的结果是0的时 候,即使不判断month=5,整个表达式的结果也是0(不是春季)。 所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执行。

对于||操作符是怎么样呢?我们结合前面的代码:

cs 复制代码
if(month == 12 || month == 1 || month == 2)

如果month==12,则不用再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。 所以,操作符的左操作数的结果不为0时,就无需执行右操作数。

像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值

练习:阅读代码,计算代码输出的结果

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 0, b = 2, c = 3, d = 4;
	int i = a++ && ++b && d++;
	printf("a = %d\n b = %d\n c = %d\n d = %d\n ", a, b, c, d );
	return 0;
}

a++先计算后++,所以a++ && ++b为0(假的)根据逻辑运算符的短路情况,出现了0右边就不再继续算了,所以只有a加了1

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int a = 0, b = 2, c = 3, d = 4;
	int i = a++ || ++b || d++;
	printf("a = %d\n b = %d\n c = %d\n d = %d\n ", a, b, c, d );
	return 0;
}

同理先算a++ && ++b,a++为假所以继续算,++b为真则真,后面就不算了,所以a是1,b是3,c是3,d是4

五,switch语句

除了if语句外,C语言还提供了switch语句来实现分支结构。 switch语句是一种特殊形式的if...else结构,用于判断条件有多个结果的情况。它把多重的else if改成 更易用、可读性更好的形式。

cs 复制代码
switch (expression)
{
	case value1: statement
	case value2: statement
	case value3: statement
	...
	default: statement
}

上面代码中,根据表达式expression不同的值,执行相应的case分支。如果找不到对应的值,就执行 default分支。

注: ·switch后的expression必须是整型表达式 ·case后的值,必须是整形常量表达式

5.1if语句和switch语句的对比

练习:输入任意一个整数值,计算除3之后的余数

如果使用if语句完成,如下:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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
		printf("余数是2\n");
	return 0;
}

switch语句如下:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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,会发生什么

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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;
}

练习:

输入一个1~7的数字,打印对应的星期几

例如:

输入:1 输出:星期一

输入:2 输出:星期2

输入:3 输出:星期3

输入:4 输出:星期4

输入:5 输出:星期5

输入:6 输出:星期6

输入:7 输出:星期天

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch(day)
	{
	case 1:
		printf("星期一\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;
	case 7:
		printf("星期天\n");
		break;
	}
	return 0;
}

如果需求发生变化:

1.输入1~5,输出的是"工作日"

2.输入6~7,输出的是"休息日"

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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.3switch语句中的default

在使用switch语句的时候,我们经常可能遇到一种情况,比如switch后的表达式中的值无法匹配代码中的 case语句的时候,这时候要不就不做处理,要不就得在switch语句中加入default子句。

cs 复制代码
switch (expression)
{
	case value1: statement
	case value2: statement
	default: statement
}

switch后边的expression的结果不是value1,也不是value2的时候,就会执行default子句。 就比如前面做的打印星期的练习,如果day的输入不是1~7的值,如果我们要提示:输入错误,则可以这样完成代码:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#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;
}
cs 复制代码
    default:
        printf("输入错误~\n");
        break;

5.4 switch语句中的case和default顺序问题

在switch语句中case子句和default子句有要求/顺序吗?default只能放在最后吗? 其实,在switch语句中case语句和[default语句是没有顺序要求的,只要你的顺序是满足实际需求的就可 以。

不过我们通常是把default子句放在最后处理的。

六, while循环

C语言提供了3种循环语句,while就是其中一种,接下来就介绍一下while语句。 while语句的语法结构和if语句非常相似。

6.1 if和while的对比

cs 复制代码
if(表达式)
	语句;


while(表达式)
	语句;//如果循环体想包含跟多但语句,可以加上大括号

你可以来对比来看一下,具体写个代码吧

cs 复制代码
//代码1
#include <stdio.h>
int main()
{
	if(1)
		printf("hehe\n");//if后边条件满足,打印一次hehe
	return 0;
}
cs 复制代码
//代码2
#include <stdio.h>
int main()
{
	while(1)
		printf("hehe\n");//while后边条件满足,死循环打印hehe
	return 0;
}

这就是他们的区别,while语句是可以实现循环效果的

6.2 while语句的执行流程

首先上来就是执行判断表达式,表达式的值为0,循环直接结束;表达式的值不为0,则执行循环语句,语句执行完后再继续判断,是否进行下一次判断。

6.3 while循环的实践

练习:在屏幕上打印1~10的值

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n = 0;
	while (n < 10)
	{
		n = n + 1;
		printf("%d\n", n);
	}
	return 0;
}

6.4练习

输入一个正的整数,逆序打印这个整数的每一位

例如:

输入:1234,输出:4 3 2 1

输入:521,输出:5 2 1

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	while (n)
	{
		printf("%d ", n % 10);
		n = n / 10;

	}
	return 0;
}

要想得到n的最低位,可以使用n%10的运算,得到的余数就是最低位,如:1234%10得到4 要想去掉n的最低位,找出倒数第二位,则使用n=n/1e操作就可以去掉最低位的,如:n=1234/10得到123, 123相较于1234就去掉了最低位,123%10就得到倒数第二位3。 循环1和2两个步骤,在n变成0之前,就能到所有的位。

七, for循环

7.1 语法形式

for循环是三种循环中使用最多的,for循环的语法形式如下:

cs 复制代码
for(表达式1;表达式2;表达式3)
	语句;//如果循环体想包含更读多的语句,可以加上大括号
	
	//对于for循环,初始化部分,判断部分,调整部分都可以省略
	//判断部分省略掉,就意味着判断恒为正

表达式1:用于循环变量的初始化

表达式2:用于循环结束条件的判断

表达式3:用于循环变量的调整

拿while循环来演示:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n = 0;//循环变量的初始化
	while (n < 10)//循环结束的判断
	{
		n = n + 1;//循环变量的调整
		printf("%d\n", n);
	}
	return 0;
}

for循环在形式上要比while循环更优

7.2 for循环的执行流程

在for循环中表达式1只被执行一次

首先执行表达式1初始化循环变量,接下来就是执行表达式2的判断部分,表达式2的结果如果==0,则循环结 束:表达式2的结果如果!=0则执行循环语句,循环语句执行完后,再去执行表达式3,调整循环变量,然后再去 表达式2的地方执行判断,表达式2的结果是否为0,决定循环是否继续。 整个循环的过程中,表达式1初始化部分只被执行1次,剩下的就是表达式2、循环语句、表达式3在循环。

7.3 for循环的实践

练习:在屏幕上打印1~10的值

参考代码:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}
	return 0;
}

7.4 while循环和for循环的对比

for和while在实现循环的过程中都有初始化、判断、调整这三个部分,但是for循环的三个部分非常集中,便于代码的维护,而如果代码较多的时候while循环的三个部分就比较分散,所以从形式上for循环要更优一些。

7.5练习

计算1~100之间3的倍数的数字之和

参考代码:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n = 0;
	int sum = 0;
	for (n = 0; n <= 100; n += 3)
	{
		sum = sum + n;
	}
	printf("%d", sum);
	return 0;
}
cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n = 0;
	int sum = 0;
	for (n = 0; n <= 100; n++)
	{
		if (n % 3 == 0)
		{
			sum += n;
		}
	}
	printf("%d", sum);
	return 0;
}

八, do-while循环

8.1语法形式

在循环语句中do while语句的使用最少,它的语法如下:

cs 复制代码
do
	语句;
while(表达式);

while和for这两种循环都是先判断,条件如果满足就进入循环,执行循环语句,如果不满足就跳出循环;而do-while循环则是先直接进入循环体,执行循环语句,然后再执行while后的判断表达式,表达式为真,就会进行下一次,表达式为假,则不再继续循环。

特点:循环体至少被执行一次

8.2 do while循环的执行流程

在dowhi1e循环中先执行图上的"语句",执行完语句,在去执行"判断表达式",判断表达式的结果是!=0,则继续循环,执行循环语句;判断表达式的结果==0,则循环结束。所以在dowhile语句中循环体是至少执行一次的,这是dowhile循环比较特殊的地方。

8.3 do while循环的实践

在屏幕上打印1~10的值

cs 复制代码
#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		printf("%d", i);
		i += 1;
	} while (i <= 10);
	return 0;
}

一般do while使用在循环体至少被执行一次的场景下,所以较少一些

8.4练习

输入一个正整数,计算这个整数是几位数?

例如:

输入;1234,输出:4

输入;12,输出:12

参考代码:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	scanf("%d", &n);
	do
	{
		n /= 10;
		i += 1;
	} while (n > 0);
	printf("%d", i);
	return 0;
}

九,break和continue语句

在循环执行的过程中,如果某些状况发生的时候,需要提前终止循环,这是非常常见的现象。C语言中提供了break和continue两个关键字,就是应用到循环中的。break的作用是用于永久的终止循环,只要break被执行,直接就会跳出循环,继续往后执行。continue的作用是跳过本次循环中continue后边的代码,在for循环和while循环中有所差异的。

break是跳过后面所有的,continue是跳过一次

9.1 while循环中的break和continue

9.1.1 break举例

cs 复制代码
#include <stdio.h>
int main()
{
	int i = 1;
	while(i <= 10)
	{
		if(i == 5)
			break;//当i等于5之后,就执行break,循环就终止了
		printf("%d", i);
		i = i + 1;
	}
	return 0;
}

打印了1,2,3,4后,当i等于5的时候,循环在break的地方终止,不再打印,不再循环。所以break的作用就是永久的终止循环,只要break被执行,break外的第一层循环就终止了。那以后我们在循环中,想在某种条件下终止循环,则可以使用break来完成我们想要的效果。

9.1.2 continue举例

continue是继续的意思,在循环中的作用就是跳过本次循环中continue后边的代码,继续进行下一次循环的判断。 上面的代码,如果把break换成continue会是什么结果呢?

cs 复制代码
#include <stdio.h>
int main()
{
	int i = 1;
	while(i <= 10)
	{
		if(i == 5)
			continue;
		printf("%d", i);
		i = i + 1;
	}
	return 0;
}

这是因为i = i + 1在continue语句的后面会跳过导致i不能变为6,所以停止在1234

那如果调换一下位置呢

cs 复制代码
#include <stdio.h>
int main()
{
	int i = 1;
	while(i <= 10)
	{	
		i = i + 1;
		if(i == 5)
			continue;
		printf("%d", i);
	}
	return 0;
}

也并不是我们所想象的那样是1234678910

因为i = i + 1的语句调换,导致一开始计算结果就是2,并且当i = 10的时候依然可以进入while循环并使i+1得到11

到这里我们就能分析出来,continue可以帮助我们跳过某一次循环continue后边的代码,直接到循环的判断部分,进行下一次循环的判断,如果循环的调整是在continue后边的话,可能会造成死循环。

9.2 for循环中的break和continue

9.2.1 break举例

其实和while循环中的break一样,for循环中的break也是用于终止循环的,不管循环还需要循环多少次,只要执行到了break,循环就彻底终止,我们上代码。

cs 复制代码
#include <stdio.h>
int main()
{
	int i = 0;
	for(i = 1;i <=10; i++)
	{
		if(i == 5)
			break;
		printf("%d", i);
	}
	return 0;
}

break的作用是永久的终止循环,未来我们在某个条件发生的时候,不想再继续循环的时候,就可以使用break来完成。

9.2.2

上面的代码如果把break换成continue会怎么样

cs 复制代码
#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后的代码,直接去到循环的调整部分。未来当某个条件发生的时候,本次循环无需再执行后续某些操作的时候,就可以使用continue来实现。

在这里我们也可以来对比一下while循环和for循环中continue的区别:

9.3 do while循环中的break和continue

do while语句中的break和continue的作用和while循环中几乎一模一样,可以自行体会

十,循环的嵌套

前面学习了三种循环while,dowhile,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参考代码

cs 复制代码
#include <stdio.h>
int main()
{
    int n = 0;
    for (n = 100; n <= 200; n++)  // 遍历100到200之间的所有数
    {
        int j = 0;                // 用于判断是否能整除的除数
        int flag = 1;             // 标记是否为素数,1表示是素数
        for (j = 2; j <= n - 1; j++)  // 用2到n-1的数去除n
        {
            // 如果n能被j整除,说明不是素数
            if (n % j == 0)
            {
                flag = 0;          // 标记为非素数
                break;             // 跳出内层循环,无需继续判断
            }
        }
        // 如果是素数则打印
        if (flag == 1)
            printf("%d ", n);
    }
    printf("\n");  // 最后换行,使输出更规范
    return 0;
}

优化

cs 复制代码
#include <stdio.h>
#include <math.h>
int main()
{
	int i = 0;
	for (i = 101; i <= 200; i += 2)//主动排出来偶数减少数量
	{
		int j = 0;
		int flag = 1;//flag=1假设是素数
		//sqrt是一个用来开平方的库函数,此时代表根号i,一个数的因子肯定有小于等于它自身开平方的,如果2-根号i之间没有,则是1
		for (j = 2; j <= sqrt(i); j++)
		{
			if (i % j == 0)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
		{
			printf("%d ", i);
		}
	}
	printf("\n");
	return 0;
}

十一,goto语句

C语言提供了一种非常特别的语法,就是goto语句和跳转标号,goto语句可以实现在同一个函数内跳转到设置好的标号处。

例如:

cs 复制代码
#include <stdio.h>
int main()
{
	printf("haha\n");
	goto next;
	printf("hehe\n");
next:
	printf("heihei\n");
	return 0;
}

next的名字是随便起的

cs 复制代码
#include <stdio.h>
int main()
{
next:
	printf("haha\n");
	goto next;
	return 0;
}

如果在代码中频繁的使用goto语句的话,会让代码执行流程比较乱,容易出现问题

goto语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以我们的建议是能不用尽量不去使用;但是goto语句也不是一无是处,在多层循环的代码中,如果想快速跳出,使用goto就非常的方便了。

本来for循环想提前退出得使用break,一个break只能跳出一层for循环,如果3层循环嵌套就得使用3个break才能跳出循环,所以在这种情况下我们使用goto语句就会更加的快捷。

11.1"趣味"小程序

cs 复制代码
//写一个关机程序
//1.程序运行起来后,电脑在1分钟内关机
//2.但是输入:我是猪,就取消关机
//
//system 函数:执行系统命令
//stdlib.h
//strcmp 是专门用来比较两个字符串的内容的
//strcmp函数返回0,表示两个字符串相等
//string.h

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	char input[20] = {0};
	system("shutdown -s -t 60");
again:
	printf("请注意,你的电脑将在1分钟内关机,如果输入我是猪,就取消关机\n");
	scanf("%s", input);//数组名本来就是地址不需要取地址符
	if(strcmp(input, "我是猪") == 0) //两个字符串比较大小,不能使用==,应该使用strcmp来比较
	{
		system("shutdown -a");//取消关机
	}
	else
	{
		goto again;
	}
	return 0;
}

可以拿去让你的好兄弟试试

第三章:循环与分支上结束

相关推荐
今日待办3 小时前
Arduino Nano33 BLESense Rev2【室内空气质量检测语音识别蓝牙调光台灯】
c语言·单片机·嵌入式硬件·mcu·语音识别·ardunio·arduinonano33
Dovis(誓平步青云)3 小时前
《探索C++11:现代语法的性能优化策略(中篇)》
开发语言·c++
再努力"亿"点点3 小时前
爬取m3u8视频完整教程
开发语言·python
一个响当当的名号3 小时前
c++primer 个人学习总结-模板和泛型编程
开发语言·c++·学习
落羽的落羽3 小时前
【C++】C++11的可变参数模板、emplace接口、类的新功能
开发语言·c++·学习
滴滴滴嘟嘟嘟.3 小时前
Qt对话框与文件操作学习
开发语言·qt·学习
liulilittle5 小时前
HTTP简易客户端实现
开发语言·网络·c++·网络协议·http·编程语言
程序员皮皮林5 小时前
Java jar 如何防止被反编译?代码写的太烂,害怕被人发现
java·开发语言·jar
qczg_wxg5 小时前
高阶组件介绍
开发语言·javascript·react native·ecmascript