🦖作者:学写代码的恐龙
🦖博客主页:学写代码的恐龙博客主页
🦖专栏:【初级c语言】
🦖语录:❀未来的你,一定会感谢现在努力奋斗的自己❀
while
for
do while
一:while循环
1.1:while循环的语法结构
while(表达式) 循环语句;
if单分支的语法结构
if(表达式) 语句;
可以看出,while循环的语法结构和if语句的单分支语法结构十分相似。但if单分支语句是当表达式的值为真时执行语句,执行完后程序会接着往下走,执行其他语句,若表达式的值为假,则什么也不执行。while和if也十分相似,当表达式的值为真就执行循环语句,否则就什么也不执行,但while和if的不同点在于如果表达式的值为真,执行循环语句,执行完后程序不像if那样接着往下走,而是返回去继续判断表达式的值是否为真,如果为真会继续执行循环语句,直到表达式的值为假停止执行循环语句,程序会继续往下走,执行另外的语句。
通过代码的运行结果可以看出,当if后面表达式的值为真的时候,会执行一次if下面的语句,而把if换成while后,由于n的值始终等于0没发生任何改变,导致while后面的表达式始终为真,循环语句就会一直执行。while语句的执行流程:(其中!=0表示真,==0表示假)
1.2:在屏幕上打印1~10
int main() { int n = 1; while (n <= 10) { printf("%d ", n); n++; } return 0; }
需要注意的是,和if语句一样,while也只能控制其后面的一条语句,如果当while后面的表达式为真的时候要执行多条语句,需要把这多条语句用大括号括起来,如上面代码的5~8行。
1.3:while循环中的break和continue
1.3.1:break(打断、终止)
还是打印1~10,当n==5的时候执行break
int main() { int n = 1; while (n <= 10) { if (5 == n) { break; } printf("%d ", n); n++; } return 0; }
代码的执行结果:
可以看出执行结果是只打印了1~4。从5开始就没有打印了。
所以break的作用就是,在循环中只要遇到break,就停止后期的所有循环,直接终止循环,所以while中的break是用于永久终止循环的。某种条件满足的状况下我们希望循环终止,此时就可以再代码中加入一个判断然后break。(这是break的第二种用法,在switch选择语句中我们也用到了break)
1.3.2:continue
把上面代码中break改成continue,代码如下:
int main() { int n = 1; while (n <= 10) { if (5 == n) { continue; } printf("%d ", n); n++; } return 0; }
通过运行结果可以看出,当打印完4后,光标一直在闪动,此时说明代码死循环了。
continue的作用就是跳过本次循环continue后面的代码,程序直接跳到循环的判断部分,以上面的代码为例,当n=5的时候,if后面的表达式的值为真,执行continue,此时程序就跳过了“printf("%d ", n);和n++;”,重新回到while后面的判断表达式,由于此时n=5,小于10,所以循环继续,当程序执行到if后面的判断表达式时,此时n还是等于5,表达式为真,执行continue,一直循环往复最终导致程序进入死循环。
总结:
continue在while循环中的作用就是:continue是用于终止本次循环的,也就是本次循环中continue后面的代码不会执行,而是直接跳转到while语句的判断部分,进行下一次循环的入口判断。
将上面代码稍作修改就可以解决死循环的问题了,我们先来找一下上面代码出现死循环的原因,通过上面的分析可以知道,当n=5的时候,执行了continue,程序跳过了“printf("%d ", n);和n++;”,这导致n的值始终为5不会发生任何变化,程序就出现了死循环的结果。那我们把“n++;”这条语句放到continue之前,此时程序每次都会执行n++了,因为continue只会跳过它后边的语句。下面我们上机试试:
可见此时程序没有产生死循环,打印时跳过了5,但是仔细观察就可以发现此时1没有被打印出来却多打印了一个11,这里主要是因为循环里在printf前进行了n++,此时我们只需要把n的初识值赋为0就可以打印出1,把while后面的判断表达式改成“n<10”就可。
1.4:while循环的实际应用
1.4.1:getchar和putchar介绍:
getchar和putchar分别可以用来获取字符和打印字符
1.4.1.1:getchar
可看出getchar是一个只可以获取字符的函数,它的返回值是int型,其实也就是该字符的ASCII值,读取失败返回EOF
1.4.1.2:putchar
putchar是一个打印字符的函数,它的参数是一个字符型变量,返回值是字符型变量存储的字符。
1.4.2:实例1:利用while循环清除缓存区的数据
#include <stdio.h> int main() { int ch = 0; while ((ch = getchar()) != EOF) putchar(ch); return 0; }
这段代码的意图是,用getchar读取一个字符放到ch里面,如果读取的字符不是EOF,我们就对其进行打印
这段代码的具体工作原理还是比较复杂的:
getchar并不是直接从键盘上读数据的,在getchar和键盘之间有一个工作缓存区,getchar在工作的时候会先到工作缓存区检查一下里面有没有字符,没有字符就等待,如上图的黑框光标在闪动,此时我们从键盘上点击A和回车,回车就是’\n’,此时缓存区里就有两个字符’A’和’\n’,然后getchar会拿走一个字符,也就是’A’,把A放到ch变量里,然后ch和EOF比较,EOF是-1,ch是’A’对应的ASCII值,所以此时ch的值是65,不等于-1,判断结果为真,程序就会执行putchar打印出A,下一次循环getchar继续从缓存区读取字符,第一次循环我们输入了’A’和’\n’,getchar取走了’A’还剩一个’\n’,所以第二次循环getchar会取走缓存区里的’\n’放到ch里,覆盖掉之前的A,‘\n’的ASCII值是0,判断表达式的值为真,程序会执行putchar打印出’\n’,我们就会看到换行的效果。想让循环停下来我们需要按“Ctrl+z”。
此代码的应用场景:
int main() { char password[20] = { 0 }; int ch = 0; printf("请输入密码:>"); scanf("%s", password);//123456 printf("请确认密码(Y/N):>"); ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }
输入一串密码,然后输入"Y"或者"N"来输出"确认成功"或者"确认失败"
通过代码的运行结果可以看出,当我们输入密码后,程序直接就输出“确认失败”。说明此代码有问题。接着我们来分析一下问题出现的原因:
我们从键盘上输入的时候,会把数据放在缓存区,然后scanf和getchar都是从缓存区中读取数。我们在输入密码的时候在键盘上点击了"123456\n",此时就会把"123456\n"放入缓存区。然后scanf从缓存区中读取数据,但是scanf只取走了"123456"并赋值给password(这里我们要知道,scanf不会拿’\n’和空格,这时scanf函数的特性,大家记住就可以),缓存区中还剩一个’\n’,当程序执行到getchar的时候,getchar检查缓存区发现有一个’\n’,getchar就会把’\n’拿走赋值给ch,然后执行if后面的判断表达式,‘\n’不等于’Y’,程序就跳转到else输出“确认失败”。
如何解决这个问题呢?
根据上面的分析,我们很容易想出,只要把缓存区里剩下的’\n’消化掉就可以了。具体操作就是:在scanf语句后添加上一个getchar。代码修改如下:
int main() { char password[20] = { 0 }; int ch = 0; printf("请输入密码:>"); scanf("%s", password);//123456 getchar();//用来消化缓存区中剩下的'\n'。 printf("请确认密码(Y/N):>"); ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }
可以看出,此时代码已经可以正常运行了。
哈哈知道这些还远远不够,如果当我们输入的密码是:123456 xxx呢?此时在123456后面有空格
可以看出此时程序又出问题了,它又直接输出了“确认失败”
和之前的分析方法类似,此时缓存区中存的是"123456 xxx\n",而scanf只拿走空格前面的东西(123456),缓存区中还剩下" xxx\n",而scanf后面就只有一个getchar,只能消化一个字符(空格),消化后缓存区中还剩下"xxx\n",那怎么办呢?我们可以写一个循环反复的用getchar直到把缓存区里的’\n’也消化掉就完事了,代码修改如下:
int main() { char password[20] = { 0 }; int ch = 0; printf("请输入密码:>"); scanf("%s", password);//123456 while (getchar() != '\n')//用循环来消化缓存区的数据 { ; } printf("请确认密码(Y/N):>"); ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }