循环结构(1):while循环、for循环

while循环

语法结构:

while(表达式)

     循环语句;

while循环的break:

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

运行结果:

所以,while循环的break用于永久终止循环。

 while循环的continue:

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

运行结果:

 所以,while循环的continue用于跳过本次循环,终于本次循环,即continue后面的代码不会再执行,而是直接跳转到while语句的判断部分,进行下一次循环的入口判断。

接下来,借助while循环介绍一下getchar、putchar和输入缓冲区。

#include<stdio.h>
int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
		putchar(ch);
	return 0;
}

运行结果:

 不难看出,当我输入了NOF的时候,程序并没有按照我想要的停下来,为什么这样子呢?是因为getchar每次从输入缓冲区读取一个字符,相当于NOF三个字符是分开输入,然后分开输出的,此时,如果想要让程序停下来,需要按下“Ctrl+Z”,用于结束循环,效果如下:

 再来看下面这个程序,理解一下什么是用getchar接收多余的字符,以达到自己想要的逻辑效果:

//先输入密码,放入password数组中,再请用户输入N/F,用于确认密码是否正确
#include<stdio.h>
int main()
{
	int rea = 0;
	char password[30];
	printf("请输入密码:\n");
	scanf("%s", password);//输入密码,放入password数组中
	printf("请输入Y/F:");
	rea=getchar();//N/F
	if (rea == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("错误,请重新输入密码:\n");
	}
	return 0;
}

运行结果:

 根据运行结果能看出来,代码出现了bug,并没有按照我想要的逻辑方式执行,为什么这样子呢?在“请输入Y/F”这句话之后,并没有等待我输入Y/F,而是直接进行了if语句的判断,输出了最终的结果,但是很显然,getchar肯定是得到了字符的,不然不会执行下一步的命令。我们调试一下,能够得到下面信息:

 10对应的字符是“\n”,也就是说,在我们输入字符串“8888”的时候,最后是有一位隐藏的“\n”的,换行这个转义字符被留在了输入缓冲区,在getchar获取字符的时候,首选就是输入缓冲区的字符,如果输入缓冲区无字符的时候,才会考虑从键盘读取字符。这里,getchar读入了换行这个转义字符,所以在后面判断的时候,才会出现上述结果,那我们要怎么才能得到我们想要的逻辑效果呢?

我们可以提前用getchar读取那些被留在输入缓冲区的字符,并且用while循环实现,代码如下:

//先输入密码,放入password数组中,再请用户输入N/F,用于确认密码是否正确
#include<stdio.h>
int main()
{
	int rea = 0;
	int ch = 0;
	char password[30];
	printf("请输入密码:\n");
	scanf("%s", password);//输入密码,放入password数组中
	while ((ch = getchar()) != '\n')
	{
		;//while循环内直接写空语句就可以
	}
	printf("请输入Y/F:\n");
	rea=getchar();//N/F
	if (rea == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("错误,请重新输入密码:\n");
	}
	return 0;
}

 运行结果:

用while循环和getchar在实现这方面的控制十分有优势,我们习惯于用getchar来获取输入缓冲区内多余的字符。

for循环:

语法结构:

for(表达式1;表达式2;表达式3)

     循环语句;

表达式1::初始化部分,用于用于始化循环变量;

表达式2:条件判断部分,用于判断循环终止;

表达式3:调整部分,用于循环条件的调整。

for循环的三个条件在while循环中也体现出来了,不过是分散体现,所以对修改循环的判断条件或者进行循环条件的调整的时候,while循环就不如for循环更有优势。

输出1-10十个数,看一下break和continue在该代码中的效果:

//输出1-10十个数
#include<stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
		printf("%d ", i);
	return 0;
}

运行结果:

加上break:

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

运行结果:

 

 加上continue:

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

运行结果:

所以,我们能从代码运行的结果中看出来,break是终止整个循环,continue是跳出当前这一次的循环,二者for语句中的作用和在while语句中的作用是类似的。

由于for循环调整循环变量和while位置不同,在一些情况下,相较于for循环,while循环更容易出现死循环,举个例子:

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

	return 0;
}

运行效果:

我往下多截了一大段,能看出来,这个程序并没有结束,它陷入了死循环,在i=5之后,i++不再执行,循环变量的调整不再起作用。可以与上面的for循环相比一下,for循环就可以避免这种情况,不会出现死循环。

对于for语句的循环控制变量的两点建议:

1)不要在for循环体内进行修改循环变量,不然for循环可能会失去控制;

2)建议for语句的循环控制变量的取值采取前闭后开区间写法。

如果在for循环体内修改循环变量会出现什么后果呢?看一下下面这段代码:

#include<stdio.h>
int main()
{
	int i = 1;
	for (i = 1; i <= 10; i++)
	{
		if (i = 5)
			printf("hallo ");
		printf("hehe ");
	}
	return 0;
}

运行结果:

 一样的,出现了死循环……

我们更加建议使用前闭后开区间写法,比如采用“for(i=0;i<10;i++)”,而不是“for(i=0;i<=9;i++)”,因为前面那句话的“10”具有更多的意义,十次循环,十次输出等。

下面介绍一下for循环的变种:

for(;;)
{
printf("hallo")
}

1)for循环的初始化、判断以及调整部分都是可以省略的,如果省略的是判断部分,那得到的判断结果就恒为真,但是省略很多时候也会改变循环的逻辑和结果,所以在不熟练的情况下,我们并不建议省略。看一下下面这个例子:

#include<stdio.h>
int main()
{
	int i = 0, k = 0;
	for (i = 0; i < 10; i++)
	{
		for (k = 0; k < 10; k++)
			printf("haha ");
	}
	return 0;
}

运行结果就是打印出了100个“haha”。

再看一下我们省略了初始化循环变量的效果,代码如下:

#include<stdio.h>
int main()
{
	int i = 0, k = 0;
	for (; i < 10; i++)
	{
		for (; k < 10; k++)
			printf("haha\n");
	}
	return 0;
}

现在,请亲爱的读者朋友仔细思考一下上述代码运行的结果是什么?

好了,在你有了自己的答案之后,可以看一下我展示的运行结果:

 打印结果是10个“haha”,为什么是这个结果呢?我们来分析一下:首先进入外层循环,判断i=0,条件为真,进行内层循环,k=0,判断条件为真,开始打印10个“haha”,然后经过十次循环后,k=10,跳出内层循环,然后进入外层循环,i=1,条件为真,再次进入内层循环,此时k=10,条件为假,跳出循环,之后的9次内层循环都直接跳出,不再进行打印。所以当内层循环少了初始化后,再次进入内层循环之后就不再对内层循环变量进行初始化,就得到了上面的运行结果。

2)再看另一种变种:

#include<stdio.h>
int main()
{
	int x, y;
	for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
	{
		printf("haha\n");
	}
	return 0;
}

运行结果:打印两个“haha”。这种变种较为少见一些。

再来思考一下下面这个代码的循环次数是几次:

#include<stdio.h>
int main()
{
	int i = 0, k = 0;
	for (i = 0, k = 0; k = 0; i++, k++)
	{
		printf("haha");
		k++;
	}
	return 0;
}

运行结果:

 循环次数为0,因为判断条件是“k=0”,是赋值语句,k=0,为假,跳出循环,不管其他地方怎么修改k的值,一旦进入for循环的判断语句,k就会被赋值为0,所以该循环的判断结果恒为假,所以循环次数为0。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值