while语句,一种运用于循环的语句。只要一个被while指定的变量没有满足while的要求,就会一直循环直到满足要求。简单来说就是这样:
while(表达式)
{
循环语句;
}
要想实际体验while语句的循环,可以写下以下代码:
while (1)
{
printf("a");
}
结果会变成这样:
因为这个while语句里的表达式永远为真,所以循环条件永远满足,会一直循环打印a。(如果打印\a而不是a的话,电脑会一直响。\a是使电脑蜂鸣的操作符)
我们来看一个简单的例子:
//打印1到10的数字
int i= 1;
while (i<= 10)
{
printf("%d\n", i);
i++;//i=i+1
}
显而易见,这个循环的目的就是打印1到10的数字。while语句的表达式明确表示i<=10时脱离循环,也就是说当i=11的时候就可以脱离循环了。如果想搞清楚详细的循环情况,那循环的流程图也可以通过以下图片进行理解:
接下来我们可以试着用if语句搭配while语句:
int i= 1;
while (i<= 10)
{
if (5 == i)
{
printf("混入其中\n");
}
printf("%d\n", i);
i++;
}
打印出来是这样的效果:
流程图:
基本的while语句配合if语句就是这样,while还可以配合其他关键词使用,今天介绍两个关键词:
while(表达式)
{
continue;
break;
}
continue:跳过本次循环后面的代码,进行下一次循环的判断
break:用于永久的终止循环
我们还是用同一个例子以break举例:
int i= 1;
while (i<= 10)
{
if (5 == i)
{
break;
}
printf("%d\n", i);
i++;
}
以上代码的结果只会输出1234,因为在i=5的循环中,break直接结束了整个循环,i=5自然也就没法打印。下面是流程图:
接下来是continue:
int i= 1;
while (i<= 10)
{
if (5 == i)
{
continue;
}
printf("%d\n", i);
i++;//输出并不是1234678910
}
以上代码的输出是1234,虽然和使用break的结果完全一样,但他们的性质不同——break在循环的基础上完全终止了循环。而continue,在i=5的循环中,continue在被触发后使它后面的语句无法被触发从而开始另一个循环,然而这个新循环的i依旧等于5。它始终无法被递增,永远只能是i=5,故永远只能进行死循环。
以下是流程图:
所以在使用continue或break之前要注意使用的位置,比如说想要实现跳过数字的代码可以这样:
int i = 1;
while (i <= 10)
{
if (5 == i)
{
i++;
continue;
}
printf("%d\n", i);
i++;//输出为1234678910
}
当i=5时,if的条件满足,让i的值+1,然后再跳过本次循环,进入另一个循环。由于新循环的i=6,所以也就可以继续循环了。
下面是流程图:
以上这些就是while的基本用法。接下来想介绍一下while与字符的搭配,所以要引入两个新的标准库函数:
#include <stdio.h>
//这两个函数需要包含以上头文件才可以使用
int main()
{
getchar();
putchar();
return 0;
}
可以运行以下代码来了解两个函数的基本作用:
int ch = 0;
ch = getchar();//输入单个字符
printf("%c\n",ch);//这是第一种打印getchar()里的字符的方法
putchar(ch);//这是第二种,相比第一种方法会简洁的多
getchar:从你写的输入(键盘输入的字符)提取单个字符,并返回该字符的ASCLL值(或EOF表示输入结束)。例:getchar(ch) = 'a',ch的值为97 (EOF:end of file,目前在此表示“没有更多的数据可取”)
putchar:向输出(屏幕)写入单个字符。例:getchar(ch) = 'a',putchar(ch) = 'a'
下面来看个基本的例子:
int ch = 0;
while ((ch = getchar()) != EOF)//EOF:end of file,目前在此表示“没有更多的数据可取”
{
putchar(ch);//适当的修改这种代码可以用来清理缓冲区
}
以上这串代码的意思是定义了一个变量ch,然后进入循环。循环的循环条件是当ch的值被getchar()提取单个字符直到没有字符可提取时,ch == EOF,跳出循环。假如我将变量ch设置为abcd1234\n,则输出为abcd1234\n(没错,回车键也被包括在在内)
要想理解getchar()的运行逻辑,我们首先要引入一个新的概念:输入缓冲区
事实上你从键盘上输入的字符(在回车之后)并不会直接被getchar()读取,而是先被输入到输入缓冲区,再被getchar()一个个读取。为了便于理解,我画了张getchar()的流程图:
这是我们在打完abcd1234并回车之后的状态:
就像以上的图片所说明的一样,我们从键盘输入的字符会先存在输入缓冲区然后再供getchar()读取
第一个例子的流程图:
第一个例子就是这样
接下来我们来看第二个例子:
char a = '\0';//初始化ascll码为0
while ((a = getchar()) != EOF)
{
if (a < '0' || a>'9')//如果a<0 并且 a>9
{
continue;
}
putchar(a);
}
//只打印数字字符
以上的代码就如注释所说,只打印数字字符。为什么,因为运用了Ascll码来判断哪个是数字字符。
if的表达式明确说明a如果是小于0的ascll码或者大于9的Ascll码的话就会跳出循环,判断循环条件,并进入下一个循环。杜绝了0至9以外的字符
流程图:
下面我们来看看getchar()的最后一个例子:
//假设密码是一个字符串
char password[20] = { 0 };
printf("请输入密码>>>");//abcd1234\n
scanf("%s", &password);//读取密码
printf("请确认密码(Y/N)>>>");
int a = getchar();//等待读取
if ('Y' == a)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
乍一看很唬人,但我们可以了解到这只是个让你设定密码并用Y或者N确认密码的程序。那它的输出理应是先让你写出你想设定的密码,回车,再让你确认自己的密码,回车并得出结果:
请输入密码>>>abcd1234
请确认密码(Y/N)>>>No
呃,这跟我们想象中的答案其实并不相同,因为在我输入密码并回车之后,就直接蹦出了第二行的内容【请确认密码(Y/N)>>>No】,这代表getchar()已经被触发,且使用了‘Y’以外的字符进行了触发。下面我们用getchar()的流程图来解释一下这个问题:
其实scanf也会在输入缓冲区读取字符,不过与getchar()不同的是,scanf默认不会主动处理缓冲区内的换行符或其他空白字符。也就是说在我们设定好密码后,缓冲区里是这么个情况:
破案了,因为getchar()读取了\n所以才导致if接受到了除'Y'以外的结果,直接输出了“NO”
就着这个问题,我们可以想出一个解决方案:
//假设密码是一个字符串
char password[20] = { 0 };
printf("请输入密码>>>");//abcd1234\n
scanf("%s", &password);//读取密码,但不会读取\n
getchar();//读取\n
printf("请确认密码(Y/N)>>>");
int a = getchar();//等待读取
if ('Y' == a)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
这样的话就可以解决之前的问题了,输出是这样的:
请输入密码>>>abcd1234
请确认密码(Y/N)>>>Y
Yes
十分完美
但如果设定的密码包含空格之后还能顺利运行吗?答案是不行,根据前面所讲,scanf默认不会主动处理缓冲区内的换行符或其他空白字符,所以自然的,getchar()又一次背负了它不该背负的东西。假如我们设定密码为abcd 1234,下面是流程图:
这个时候我们可以使用while来解决它了:
//假设密码是一个字符串
char password[20] = { 0 };
printf("请输入密码>>>");//abcd1234\n
scanf("%s", &password);//读取密码,但不会读取\n
int ch = 0;
while ((ch = getchar()) != '\n')//循环读取直到读取到\n为止
{
;
}
printf("请确认密码(Y/N)>>>");
int a = getchar();//等待读取
if ('Y' == a)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
这样的话,就可以解决空格的问题了,因为getchar会读取字符直到读取完\n为止,竟然缓冲区里没有东西,那剩下的getchar()也就可以让我们自己打字了。下面是流程图:
输出:
请输入密码>>>abcd 1234
请确认密码(Y/N)>>>Y
Yes
好像突然可以理解为什么设置大多数账号密码时都不能用空格什么的了
软件:visual studio 2022