循环语句(while,for,do...while)

Posted Living_Amethyst

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环语句(while,for,do...while)相关的知识,希望对你有一定的参考价值。

 写这篇文章,我深有感触,在写代码的过程中,我们经常会出现最后的结果达不到我们预期的效果的情况,我们一定一定要耐下心来,一步一步地去思考,是哪里出了问题,怎么能解决问题,这样的一个过程是十分重要的,是能让我们越来越接近真相的过程。学习编程的路肯定不是一帆风顺的,但我们要有能够克服任何苦难的决心,这是最重要的。 


在这篇文章中,我们将会对循环语句有一个更加深入的了解

并且我们还能了解到getchar与putchar的相关知识

  让我们开始吧!


一.while循环 

1.while循环语法 

while语句又称当型循环语句,其语法为:

while (表达式) 

 循环语句

其具体执行过程如下:

   (1)计算表达式的值。若为真,则转步骤(2),否则退出循环,执行while的下一条语句

   (2)执行循环语句(即循环体),并返回步骤(1) 

 

 这里试着使用while循环打印1~10的数

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

2.break和continue 在while循环中

(1).break

#i#include <stdio.h>
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 

如果将刚刚的break换成continue

那么运行的结果又会发生什么变化呢?

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

4后面的光标在闪动,说明此时程序进入了死循环 

 原因是,与break语句不同,

continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接 跳转到while语句的判断部分。进行下一次循环的入口判断

如图中红色框框内的代码在continue的作用下会被跳过,i++不会被执行,所以i就一直为5,进去死循环

3.两个代码的练习

让我们再看两个跟while循环有关的代码,再看之前,我们需要先了解一下getchar和putchar

getchar

在msdn中,我们查找到getchar的解释

int ch = getchar() ;   //获取字符

printf("%c\\n",ch) ;       //打印获取的字符

这里我们会有这样的疑问:我们的 ch 获取的是一个字符,为什么放到int整型里去?

原因有两个

  1. 虽然getchar返回的是个字符,但是字符的存储值是它的 ASCII码值,如 ’a‘对应的ASCII码值就是97
  2. getchar读取失败的时候返回EOF,而EOF是-1,是个整数

  

getchar - 获取(输入一个字符)

putchar - 输出一个字符 

 putchar

在msdn中的定义

 int ch = getchar() ;   //获取字符

putchar (ch);//输出一个字符

 getchar 和 putchar 可以用scanf 和printf代替,且scanf和printf的功能更全,getchar和putchar只能操作字符 

第一个代码

这个代码会将你输入的字符打印出来,如果想停止:ctrl+z 可以让getchar返回一个EOF

我们写这样的代码有什么意义呢?实际上是有意义的,我们这里再举一个例子

#include <stdio.h>
int main()
{
   char input[20] = { 0 };//创建一个数组
	printf("请输入密码:>");
	scanf("%s", input);
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\\n");
	}
	else
    {
		printf("确认失败\\n");
	 }

	return 0;
}

看这个代码时,可能会有疑问,为什么scanf函数里的input没有取地址,

               是因为数组名本身就是一个地址,所以不需要再取地址


   这样一个程序,我们的本意是输入密码后需要用户确认密码是否正确,可当程序走起来后我们发现,在我们还没有输入时,已经打印出了“确认失败”

下面我们就来分析一下程序出问题的原因 ,全部在这张图上了

解决方法 :把输入缓冲区里scanf没有拿走的\\n拿走 ,改进如下

#include <stdio.h>
int main()
{
   char input[20] = { 0 };//创建一个数组
	printf("请输入密码:>");
	scanf("%s", input);
	getchar();   //拿走\\n
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\\n");
	}
	else
    {
		printf("确认失败\\n");
	 }

	return 0;
}

 

我们成功了!!! 

下面是还可能出现的错误的情况:如果密码当中有“ ”(空格)

当用户输入的密码中含有空格时,又出现了刚刚的错误的情况,我们再来分析

我们可以发现这时需要拿走更多的字符,所以我们使用while循环 

while ((tmp = getchar()) != '\\n')  //只要不是/n,就说明没拿完,就进入循环
    {
        ;                                             //空语句(什么也不干)
    } 

#include <stdio.h>
int main()
{
   char input[20] = { 0 };//创建一个数组
	printf("请输入密码:>");
	scanf("%s", input);
	int tmp = 0;
	while ((tmp = getchar()) != '\\n')//只要不是/n,就说明没拿完,就进入循环
	{
		;//空语句(什么也不干)
	}
     printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\\n");
	}
	else
    {
		printf("确认失败\\n");
	 }

	return 0;

 我们惊喜地发现,我们又通过改变代码使这个程序执行成功了!

第二个代码

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

这个代码就比较简单了 就是只打印0~9的数字

但有一点需要说明

这个括号不能少((ch=getchar())!=EOF) 如果少了 ,就不是把获取的字符放进ch和EOF比较了,而是字符直接与EOF比较,不相等就为假,就为0,这时就把0赋给了ch 

 二.for循环

1.for循环语法 

 for循环的语法:

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

     循环语句;

 表达式1

表达式1为初始化部分,用于初始化循环变量的。

 表达式2

表达式2为条件判断部分,用于判断循环时候终止。

 表达式3

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


这里我们同样也使用for循环来打印一下1~10的数来熟悉一下for循环

#include <stdio.h>
int main()
{
 int i = 0;

 for(i=1; i<=10; i++)
 {
 printf("%d ", i);
 }
 return 0;
}

并且,我们用这个代码为例,来帮助我们理解for循环的流程图

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

int i = 0;
//实现相同的功能,使用while
i=1;//初始化部分
while(i<=10)//判断部分
{
 printf("hehe\\n");
 i = i++;//调整部分
}
//实现相同的功能,使用while
for(i=1; i<=10; i++)
{
 printf("hehe\\n");
}

可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离 较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。 for循环使用的频率也最高。 

2. break和continue在for循环中

我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。

但是还是有些差异:

(1).break

可见,break在for循环中与在while循环中类似,都是直接终止循环 

(2).continue 

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

 continue在for循环和在while循环中有所不同 

这里执行起来并不是死循环了,而是跳过5打印了1 2 3 4 6 7 8 9 10

          当i==5时,执行continue语句,跳过printf语句 ,执行 i++,之后 i为6,i==5为假,continue语句不再执行 


for语句的循环控制变量 (作为补充)

一些建议:

  1.  不可在for 循环体内修改循环变量,防止 for 循环失去控制。
  2.  建议for语句的循环控制变量的取值采用“前闭后开区间”写法。 
int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{}
//两边都是闭区间
for(i=0; i<=9; i++)
{}

第一种也就是前闭后开的写法很直观,这个循环要循环10次(但不是总是如此) 

一些for循环的变种 

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

变种1

 for的初始化,判断,调整三个部分都可以省略

 中间的判断部分如果省略,意味着判断恒为真,就构成死循环

如果条件允许,不建议省略for循环的3个表达式 

这里看一个嵌套的for循环 ,来比较一下

#include <stdio.h>
int main()
{
	int i = 0;
	int j = 0;
	for (i = 0;i < 3;i++)
	{
		for (j = 0;j < 3;j++)
		{
			printf("hehe\\n");
		}
	}
  return 0;
}

在正常情况下,这个程序会3次外循环,3次内循环,共9次 打印9次hehe 

我们现在试一下省略for的第一个初始化语句 

#include <stdio.h>
int main()
{
	int i = 0;
	int j = 0;
	for (;i < 3;i++)
	{
		for (;j < 3;j++)
		{
			printf("hehe\\n");
		}
	}
  return 0;
}

结果只打印了三次, 原因是 虽然外循环还是3次,但内循环由于 j 没有初始化,在内循环第3次后,j就变成了4,内循环不再执行

变种2 

使用多于一个变量控制循环,这是允许的 

for (x=0,y=0;x<2&&y<5,++x,y++)


 这里,我们再拓展一道笔试题

请问循环要循环多少次?

//请问循环要循环多少次?
#include <stdio.h>
int main()
{
 int i = 0;
 int k = 0;
 for(i =0,k=0; k=0; i++,k++)
        k++;
 return 0;
}

答案是0次  

原因是这里的红色框中的 k=0是赋值,k被赋值为0,0为假,循环不执行

三.do...while()循环 

1.do...while()循环的语法

do

         循环语句;

while  (表达式);

我们再用do...while循环来试着打印1~10的数


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

do..while的特点是:循环至少执行一次,使用的场景有限,所以不是经常使用。 

流程图 

 

 

 

2.break和continue在do...while循环中

(1).break 

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

 

可见,break在三个循环中较为类似,都是直接终止循环,但是值得注意的是: break只能终止一层循环,如果有刚刚那种嵌套式的循环,只能终止一层

(2).continue 

 

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

运行的结果是1 2 3 4死循环 

以上是关于循环语句(while,for,do...while)的主要内容,如果未能解决你的问题,请参考以下文章

for,while,do while语句区别以及常见死循环格式

js循环语句while,do..while,for

js循环语句while,do..while,for

循环语句 while,do while ,for 循环

关于循环的整理

JAVA 循环结构 - for, while 及 do...while