零、引言
我们已经掌握了,if语句。
当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。
但是我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。
那我们怎么做呢? C语言中给我们引入了:
while,
for,
do while
三种语句,
可以实现循环。
一、while
1、基本语法结构
//while 语法结构
while(表达式)
循环语句;
表达式为真,执行循环语句;
直到表达式为假,不再执行。
比如我们实现:
在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ", i);
i = i+1;
}
return 0;
}
2、while语句中的break和continue
break
看如下一段代码:
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
break;
printf("%d ", i);
i = i + 1;
}
return 0;
}
这里代码输出结果为:
1 2 3 4
总结:
break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的 break是用于永久终止循环的。
continue
看如下一段代码:
//continue 代码实例1
#include <stdio.h>
int main()
{
int i = 1;
while(i<=10)
{
if(i == 5)
continue;
printf("%d ", i);
i = i+1;
}
return 0;
}
这里的代码输出结果为:
1 2 3 4 并且程序并没有结束。
原因在于,当i===5时,if判断通过,从而执行continue;
那么continue后面的语句全部不执行,直接继续执行下一次while循环。
下一次while循环时,由于i还是等于5,所以继续执行下一个if语句,再判断,再continue,
从而成为了一个死循环,
一直在
while(i<=10)
{
if(i == 5)
continue;
这三条语句中循环。
再看如下一段代码:
//continue 代码实例2
#include <stdio.h>
int main()
{
int i = 0;
while(i<=10)
{
i = i+1;
if(i == 5)
continue;
printf("%d ", i);
}
return 0;
}
这里的代码输出结果为:
1 2 3 4 6 7 8 9 10 11
总结:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接 跳转到while语句的判断部分。进行下一次循环的入口判断。
再看两个代码实例:
代码1
#include <stdio.h>
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
putchar(ch);
return 0;
}
番外--getchar()函数和putchar()函数的作用
int ch = getchar();
putchar(ch);
printf("%c\n",ch);
putchar(ch);
printf("%c\n",ch);
这两个语句等价。
getchar()函数让计算机读取一个字符,这个字符由我们来输入;
而putchar()函数让计算机将这个字符输出。
至于为什么它的类型是int,
因为getchar函数的返回值是用户输入的字符的ASCII码。
而再用printf函数,将打印类型改为“%c”,即可将这个ASCII码转换成对应的字符。
putchar()函数则简化了上述步骤。
注意,getchar()函数只能读一个字符,scanf可以读一个字符串。
那么为什么这段程序【代码1】能读一个串呢?
如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。
也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完后,才等待用户按键。
用户按完键以后,putchar会把栈/队列里的字符一个一个输出,这就导致了用可以读一个字符串,而不是只读字符串的第一个字符。
番外二--EOF是什么
EOF是一个计算机术语,为End Of File的缩写,是文件结束标志。
在操作系统中表示资料源无更多的资料可读取。
资料源通常称为档案或串流。
通常在文本的最后存在此字符表示资料结束。
它的值是-1。
那么如何获取一个EOF呢?
当我们输入crtl+z时,
会发现程序停止了运行。
Windows中,Ctrl+Z表示EOF。
我们看一个番外代码
int main()
{
char password[20] = { 0 };
printf("请输入密码:");
scanf("%s", password);//输入密码,并存放在password数组中
printf("请确认(Y/N)");
int ret = 0;
ret = getchar();//Y/N
if (ret == 'Y')
{
printf("确认成功");
}
else
{
printf("放弃确认");
}
return 0;
}
按照我们的想法,我们会输一遍密码,然后输入Y or N来确认;
然而,程序运行的结果是:
还没有到确认的那一步,程序就停止运行了。
原因是:
我们先来看一看ret里面存放的是什么:
先按F10进行逐句运行
再 调试--窗口--监视
发现ret里存放的值是10。
10对应的ASCII码是\n
也就是回车!
破案了:我们在输入第一遍密码的时候,为了执行下一语句,按了回车
而这个回车被ret悄悄地拿走了,并存放了进去。
输入函数【scanf和getchar】的执行过程:
有一个区域叫做输入缓冲区,输入函数会去缓冲区中找,等待缓冲区中出现东西。
当我们输入了东西,被存到了输入缓冲区中;
一旦输入缓冲区中出现了数据,
输入函数就把它读走。
我们输入123456\n,
由于\n是一个转义字符,所以scanf函数会先把123456给读走
这时候缓冲区中还留了一个\n
到了getchar(),
它来缓冲区一看,发现有个\n,于是把它读走。
而这时候ret的ASCII码值并不是Y的ASCII码值,
所以不执行if,执行else。
所以会直接打印放弃确认。
这就是整个程序的执行过程。
【题外话:以下程序可以执行:
int ret = 'Y';
cout << ret;
执行结果为89。
如果令int 变量等于一个字符,那么其实他存放的其实是这个字符的ASCII码值。】
那么如何让这段代码1正确执行?
我们想让ret在打完回车后,缓冲区是空的,等待我们输入一个新的数据。
我们可以在输入完密码后,再执行一个getchar()函数,把缓冲区里的‘\n’读走。
代码如下:
int main()
{
char password[20] = { 0 };
printf("请输入密码:");
scanf("%s", password);//输入密码,并存放在password数组中
//缓冲区还剩余一个‘\n’
//读取一下‘\n’
getchar();
//不关心这个‘\n’读到哪了。
printf("请确认(Y/N)");
int ret = 0;
ret = getchar();//Y/N
if (ret == 'Y')
{
printf("确认成功");
}
else if(ret == 'N')
{
printf("放弃确认");
}
else
{
printf("请输入Y/N");
}
return 0;
}
这样代码暂时可正常跑完。
又出现了新的问题:
假如输入一串字符:123456 ABCD
因为scanf函数只会读取空格前的字符,
所以读完123456就会停止;
这时候,getchar读下一个字符,
把\n读走了。
还剩ABCD;
然后ret把A都走了,然而A并不是Y N中的一个,
所以会出现“请输入YN”。
那么怎么解决?
我们可以写一个循环:
while(ch=getchar()!='\n')
{
;
}
让这个循环不断地读,直到读到一个回车。
让回车被ch接受,然后跳出循环,
从而执行后面的代码。
代码2
#include <stdio.h>
int main()
{
while ((ch = getchar()) != EOF)
{
if (ch < ‘0’ || ch > ‘9’)
continue;
putchar(ch);
}
return 0;
}
代码意思是,只打印0~9的数,不然就跳走,继续下一次循环,直到遇到一个EOF(即ctrl+z)
这段代码可指定接收某些字符。