[ C语言 ]循环语句---while---for---do while---goto语句详解及练习题巩固

文章目录

  • 前言
  • 一,while 循环
  • 二,for   循环
  • 三,do  while 循环
  • 四,goto语句
  • 五,练习题巩固
  • 总结



前言

本篇内容主要记录 循环语句:

包括while循环,for循环,do...while,goto循环详细讲解以及习题巩固练习

____________________________________________________________________________

                                                                     ****正文开始****

一、while 循环

在我们的日常生活中有很多实际的例子:

同一件事情我们需要完成很多次。 那我们怎么做呢? C语言中给我们引入了: while 语句,可以实现循环。
//while 语法结构
while(表达式)
 循环语句;

Q : 比如我们实现:在屏幕上打印1-10的数字。

int main() {

	int i = 0; // 初始化
	while (i <= 10) {// 判断

		printf("%d ", i);

		i++;       //调整部分
	}
	return 0;
}
这段代码中已经足够清晰的反应了程序的执行过程。
上面的代码已经帮我们了解了 while 语句的基本语法。
那我们再了解一下:

(一)while语句中的breakcontinue

1>break在while循环中

Q : 我们看这段代码,它的执行结果是什么呢?

int main() {
	int  i = 1;
	while (i <= 10) {
		if (5 == i)
			break;
	

		printf("%d ", i);
		i++;
	}
	return 0;
}
我们看代码运行结果:

我们发现了break在while循环中的作用

其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的。

2>continue在while循环中

Q : 我们看这段代码,它的执行结果是什么呢?

int main() {
	int  i = 1;
	while (i <= 10) {
		if (5 == i)
			/*break;*/
		continue;// continue 会跳过后面的语句

		printf("%d ", i);
		i++;
	}
	return 0;
}

我们看运行结果:

 Q : 我们再看这段代码,它的执行结果是什么呢?

int main() {
	int  i = 1;
	while (i <= 10) {
		i++;

		if (5 == i)
		
		continue;// continue 会跳过后面的语句

		printf("%d ", i);
	
	}
	return 0;
}

我们看它的运行结果:

 我们能够发现:第一段代码运行到4之后,当i==5的时候发生了死循环。这是因为continue起了作用,我们就要提到continue 的作用了。

continue在while循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,
而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
A : 因此第一段代码中当 i==5 的时候,走到continue时跳出了本次循环到了,但是这时候 i 还并没有i++,当下一次 i 进入循环的时候,i 的值还是5,再次continue,这就造成了死循环。
同理:
Q : 为什么第二段代码没有造成死循环呢?
A : 其实我们只要自己观察分析代码会发现,在 if 判断之前 i++ 了一次;这就会导致当 i==5时,continue跳出本次循环时,在下一次进入循环的时候 i 并不是仍然是5,而是6(因为i++了一次),所以 if 判断为假,不会continue跳出循环,而且会打印 数字,因此这就是为什么第二段代码没有造成死循环,并且打印的结果中没有数字5。

 (二)getchar 详解

Q : 我们在观察这段代码,他是什么意思?

int main() {

	int ch = 0;
	while ((ch = getchar())!= EOF) {
		putchar(ch);
	}

	return 0;
}

这里的代码适当的修改是可以用来清理缓冲区的.

#include <stdio.h>
int main()
{
    char ch = '\0';
 while ((ch = getchar()) != EOF)
 {
     if (ch < ‘0’ || ch > ‘9’)
        continue;
     putchar(ch);
 }
 return 0; }

这个代码的作用是:只打印数字字符,跳过其他字符的

举例:  请观察这段代码?他会正常输出我们想要的结果吗?

int main() {
	char input[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", input); // abcdef
	
	getchar(); // 拿走 \n


	printf("请输入密码(Y/N):>");
	
	int ch = getchar();
	if (ch == 'Y') {
		printf("确认成功\n");
	}
	else {
		printf("确认失败\n");

	}
	return 0;
}

查看运行结果:

 我们发现如果连续的输入一段数字,程序会正常按照我们的意思输出,但是如果我们更改输入的方法,他还会正常吗?

我们观看这样的输入方式:

 在这里我们输入的密码:123  456

我们在123和456之间加入一个空格,我们发现这就导致了我们直接略过了判断密码是否争取的那一步,并且输出了确认失败,这是为什么呢?

这是因为:

我们从键盘输入: 123 456

实际上是: 123 456\n

读取字符串的时候,遇到空格就结束了,所以getchar只都读走了123

缓冲区内部还有:_ (空格)456\n

所以一个getchar并不能解决问题,应该使用一种方法将缓冲区的所有字符带走,这时候就可以运用while循环,具体代码如下:

//清理缓冲区
	int tmp = 0;
	while ((tmp = getchar()) != '\n') {
		;  //空语句
	}

通过清理缓冲区这时候就可以达到我们想要的结果:

整体代码如下:

int main() {
	char input[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", input); // 123 456
	 
	//清理缓冲区
	int tmp = 0;
	while ((tmp = getchar()) != '\n') {
		;  //空语句
	}


	printf("请输入密码(Y/N):>");

	int ch = getchar();
	if (ch == 'Y') {
		printf("确认成功\n");
	}
	else {
		printf("确认失败\n");

	}
	return 0;
}

我们再看 演示结果:

 我们发现解决了问题

二,for   循环

一:语法
for(表达式1; 表达式2; 表达式3)
 循环语句;
表达式1
表达式1初始化部分,用于初始化循环变量的。
表达式2
表达式2条件判断部分,用于判断循环时候终止。
表达式3
表达式3调整部分,用于循环条件的调整。

我们继续以实例的方式了解for循环语句:

实际的问题:
Q :使用for循环 在屏幕上打印1-10的数字。
int main() {
	int i = 0;
    //for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
	for (i = 1; i <= 10; i++){

		printf("%d ", i);

	}
	return 0;
}

现在我们来对比一下while循环和for循环:

int i = 0;
//实现相同的功能,使用while
i = 1;//初始化部分
while (i <= 10)//判断部分
{
	printf("hehe\n");
	i = i + 1;//调整部分
}
//实现相同的功能,使用while
for (i = 1; i <= 10; i++) {
	printf("hehe\n");
}
可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

(一)breakcontinuefor循环中

我们发现在 for 循环中也可以出现 break continue ,他们的意义和在 while 循环中是一样的。
但是还是有些差异:

1>break 在for循环中

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

我们观察运行结果:

我们观察到输出的结果为:1 2 3 4 

这是因为: 当 i == 5 进入 if 判断当中时,直接跳出 for 循环 

到达 return 0; 

因此打印出 : 1 2 3 4(和while 循环类似)

其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。

2>continue 在for循环中

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
			continue;
		printf("%d ", i);
	}
	return 0;
}
我们观察运行结果:

我们观察到输出的结果是:1 2 3 4 6 7 8 9 10
跳过了数字5,但是它并不是和while循环一样发生了死循环,这是因为for在执行的时候会有执行顺序,当表达式2成立进入循环时遇到continue跳出本次循环时,会接着执行表达式3,也就是调整部分,i 会 i++,这时候 i 会自增成6,在下一次进入循环时,不进入 if 判断。
因此:
我们从结果上就会得到:打印出1 2 3 4  6 7 8 9 10 跳过了数字 5 的打印。
这就是continue在for循环中的作用
建议:
   for (i = 0; i < 10; i++)  ----->建议写成前闭后开,10表示打印10次 提高可读性
 1. for  的舒适化,判断,调整三个部分都可以省略
 2. 中间的判断部分如果省略,意味着判断恒为真,就构成了死循环
 3. 如果条件允许,不建议省略for循环的3个表达式
死循环举例:
	for (;;) {

		printf("hehe\n");// 死循环打印hehe
	}

我们再来看这段代码:

    int i = 0;
    int j = 0;
    for (i = 0; i < 3; i++){
        for (j = 0; j < 3; j++) {
            printf("hehe\n");
        }
    }

我们看运行结果:

我们发现这个程序打印了 9 行 hehe,这是因为当 i ==0 进入程序的时候 j 从0开始循环,当 j == 0 时, 打印一遍 hehe;当 j == 1 时, 打印第二遍 hehe ,d ;当 j == 2 ,打印第三遍 hehe;当 j ==3 不小于3的时候跳出 j 的循环 这时候 i++,此时 i == 1,同理,j 又从0开始打印 3遍hehe;i 再 i++;j 又打印3遍hehe,当 i==3 时 ,i < 3 不成立时,退出循环 ,这时候统计发现一共打印了9遍呵呵。

但是,如果我们省略表达式一(初始化),打印的结果会完全不同。

int main() {
	int i = 0;
	int j = 0;
	for (; i < 3; i++) {
		//  j = 3 没再初始化了
		for (; j < 3; j++) {
			printf("hehe\n"); // 打印3个hehe
		}
	}
	return 0;
}

我们观察运行结果:

 这是因为当 i++ 增到 i==1 进入j 的循环时,j 并没有初始化,还是i=1时候的i++是3,不会再进入j 的循环,因此只会打印  i ==1 第 一 次的3 个hehe。
总结:如果条件允许,不建议省略for循环的3个表达式
我们再来看这一道题 : 
//int main() {
//	int i = 0;
//	int k = 0; 
//	         // k = 0  赋值0  结果是0  表示假 不进入循环
//	for (i = 0, k = 0; k = 0; k++) {
//		k++;
//	}
//	return 0;
//}

Q:问这段代码循环几次?

A : 通过代码我们发现 for循环中的表达式2 是k = 0,‘=’是赋值符号,因此是将数字0赋值给k,我们知道在C语言中0表示假,因此表达式2 判断为假,根本不会进入for循环,因此这段代码循环0次。

三,do  while 循环

do 语句的语法:
do
 循环语句;
while(表达式);
do语句的特点 :  循环至少执行一次,使用的场景有限,所以不是经常使用
#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		printf("%d\n", i);
        i++;
	} while (i < 10);
	return 0;
}

这段代码是用while循环打印1-10。

(一)do while循环中的breakcontinue

1> break 在 do  while  循环中

int main() {
	int i = 1;
	do {
		if (i == 5)
			break;//打印 1 2 3 4
	
		printf("%d ", i);
		i++;
	} while (i <= 10);

	return 0;
}

道理同break在while和for循环中一样。

2> continue 在 do  while  循环中

int main() {
	int i = 1;
	do {
		if (i == 5)
			
		   continue;// 1 2 3 4死循环
		printf("%d ", i);
		i++;
	} while (i <= 10);

	return 0;
}

运行结果:

 原因和while循环中的道里一致,因为continue是跳出本次循环,不会执行后面的i++,所以如果当i==5时就会一直死循环。

这时候我们如果将i++放到continue之前结果为:

int main() {
	int i = 1;
	do {
		i++;
		if (i == 5)
			
		   continue;// 1 2 3 4死循环
		printf("%d ", i);
	
	} while (i <= 10);

	return 0;
}

 我们发现和while循环中的将i++的第二种可能性一直,道理相同。

四,goto语句

C 语言中提供了可以随意滥用的 goto 语句和标记跳转的标号。
从理论上 goto 语句是没有必要的,实践中没有 goto 语句也可以很容易的写出代码。
但是某些场合下 goto 语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
多层循环这种情况使用 break 是达不到目的的。它只能从最内层循环退出到上一层的循环。
goto 语言真正适合的场景如下:
// 多层循环这种情况使用break是达不到目的的,他只能从最内层循环退出上一层的循环
// 这时候 goto语句适合这种场景
for () {
	for () {
		for () {
			if (disaster) {
				goto error;
			}
		}
	}
}
...
error:
if(disaster)
// 处理错误情况

goto again 用法(标签一致就行,但标签必须在同一个函数内)

int main() {

again:
	printf("hehe\n");
	printf("haha\n");
	goto again; // 标签一致就行,标签必须在同一个函数内

	return 0;
}

结果演示: 

会死循环打印hehe和haha.

小游戏,小整蛊:

//例如: 写一个关机程序
//只要程序启动了,就倒计时60秒关机,如果60秒之内,输入:我是猪,就取消关机,如果不输入,时间到就关机
  
 shutdown   windows提供的关机命令
 shutdown -s -t 60秒之后关机
 shutdown -a 取消关机
int main() {

	char input[20] = { 0 };
	system("shutdown -s -t 60");

again:
	printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
	scanf("%s", input);  //input本来就是地址 不用取地址
	//判断
	if (strcmp(input,"我是猪") == 0) {
		// 取消关机
		system("shutdown -a");
	}
	else {
		goto again;
	}

	return 0;
 }

五,练习题巩固

1.计算n的阶乘

int main() {

	int n = 0;
	scanf("%d", &n);// 5
	int i = 0;
	int ret = 1;
	for (i = 1; i <= n; i++) {
		ret *= i;
	}
	printf("%d\n",ret);
	return 0;
}

 2.计算 1!+2!+3!+4!+.....n!

int main() {
	int n = 0;//共n个数字
	scanf("%d", &n);
	int i = 0;// j  内部的第 i 个数字
	int j = 0;// n  内部的第 j 个数字
	int sum = 0;

	for (j = 1; j <= n; j++) {// 
		int ret = 1;
		for (i = 1; i <= j; i++) {
			ret *= i;
		}
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

当然这道题我们还有优化算法:

int main() {
	int n = 0;
	int i = 0;
	int ret = 1;
	int sum = 0;
	for (n = 1; n <= 10; n++) {
		ret = ret * n;
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

3.在一个有序数组中查找具体的某个数字n(二分查找)

这个是普通求法:

int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;
	int i = 0;
	for (i = 0; i < 10; i++) {
		if (arr[i] == k) {
			printf("找到了,下标是%d\n", i);
			break;
		}
		else if (i == 10) {
			printf("找不到\n");
		}
	}
	return 0;
}

我们发现,如果说这个数组中定义了100甚至更多的数字时,这样的算法就会耗时耗力,因为有一种更简便的算法:

二分法 -- 折半查找

int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	 //         40       /    4  = 10
	int k = 7;
	int left = 0;
	int right = sz - 1;


	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] < k) {
			left = mid + 1;
		}
		else if (arr[mid] > k) {
			right = mid - 1;
		}
		else {
			printf("找到了,下标是%d \n", mid);
			break;
		}
	}
	if (left > right) {
		printf("找不到\n");
	}
	return 0;
}

  4:反向打印一个数字

int main() {
	int n = 0;
	scanf("%d", &n);
	while (n!=0) {
		printf("%d", n % 10);
		n = n / 10;
	}
	return 0;
}

                                                                   ****正文结束****

———————————————————————————————————————————








总结

本篇文章的内容就记录完毕,由于本人技术水平有限,若各位读者发现错误,欢迎及时纠正。

  • 25
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白又菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值