while语句
本博客主要内容为 “小甲鱼” 视频课程《带你学C带你飞》【第一季】 学习笔记,文章的主题内容均来自该课程,在这里仅作学习交流。在文章中可能出现一些错误或者不准确的地方,如发现请积极指出,十分感谢。
也欢迎大家一起讨论交流,如果你觉得这篇文章对你有所帮助,记得评论、点赞哦 ~(。・∀・)ノ゙
1. 循环结构
循环结构是编程中常常使用的结构,当在程序中存在着需要循环执行多次的代码时,可以采用循环结构实现。在 C 语言中常见的是 while 循环和 for 循环,在这里首先介绍 while 循环。
2. while 循环结构
2.1 while 语句
while 语句的语法非常简单,使用方法如下
while (表达式)
循环体
只要表达式的值为真,就会不断执行循环体里边的语句或程序块,如下图所示
举例说明
示例1
现在我们要计算1+2+3+……+100的结果,可以画出如下的流程图
根据流程图可以得到如下的程序
#include<stdio.h>
int main()
{
int i = 1, sum = 0;
while (i <= 100)
{
sum = sum + i;
i = i+1;
}
printf("result is %d\n",sum);
return 0;
}
示例2
统计从键盘输入的一行英文句子的字符个数,其流程图如下所示
根据流程图可以得到如下代码
#include<stdio.h>
int main()
{
int count = 0;
printf("please input a english setence:");
while (getchar() != '\n')
{
count = count +1;
}
printf("it has %d words \n",count);
return 0;
}
在ubuntu16.04下通过gcc编译执行得到如下结果
其中 34 个字符包含了其中的空格。
2.2 do … while 语句
while 语句的语法非常简单,使用方法如下
do
循环体
while (表达式);
这里需要注意的是,在 while (表达式);
的后面有一个分号,但是在上一个的中 while (表达式)
是没有分号的。do…while
与 while
语句相反,先执行循环体的内容再判断表达式是否为真,如下图所示
这种循环结构比较特殊,常常用于用户登陆密码验证问题,当输入的密码不正确的时候会要求一直输入密码直至正确(当然生活中的密码往往只可以进行有限次的尝试),常常采用如下左图的使用方式
因为如果采用 while
语句而不是采用 do … while
语句,就会产生上图中右图的现场,代码会有两部分十分相近。
2.3 小结
对于上述的两种循环,其中的 while
语句是入口循环条件, do … while
语句是出口循环条件,其中入口循环条件是首先判断条件是否满足,然后在执行循环体内容;而出口循环条件是先执行循环体,然后判断条件是否满足,因此循环体的内容至少会执行一次。
3. C 语言的三种输入函数
在这里介绍 C 语言中的三种输入函数,scanf()
,getchar()
和 gets()
都是标准输入函数,比如在本文中使用的 getchar()
,但是在使用有一些不同。[2]
3.1 输入操作的原理
在介绍输入函数之前,首先介绍输入操作的原理, 程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。所以我们在使用不同的输入函数时,要考虑在输入缓冲区是否会造成残留的现象。
3.2 三种输入函数用法
gets()
用于从标准输入流stdin读入一个整行(以’\n’或EOF)结束,写入ptr指向的字符数组,并返回这个指针;出错或遇到文件结束时则返回NULL。行末的’\n’从流中取出,但不写入数组。gets()不检查被写入的数组大小。
getchar()
用于从标准输入流stdin读入一个字符,并返回这个字符。如果读到文件结尾,则返回EOF。注意到EOF不能用char类型表示,所以getchar()函数返回的是一个int型的数。使用时也应该注意这一点。
scanf()
函数返回成功赋值的数据项数,出错时则返回EOF,与上面相同,scanf()
函数返回的也是一个int型的数。
因此getchar()
常用于接收字符,而gets()
常用于接受字符串,scanf()
可用于接受字符也可以用于接收字符串。
3.3 三种输入函数的注意事项
首先要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题。
读取字符时:
(1) scanf()
以 Enter 结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
(2) getchar()
以 Enter 结束输入,不会舍弃最后的回车符。
读取字符串时:
(1) scanf()
以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符;
(2) gets()
以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
所以当我们项读取一句话中的每一个字符的时候,往往使用 getchar()
而不使用 scanf()
,因为一句话中是会出现空格的,如果使用 scanf()
会造成将一句话分首先读入第一个空格前的部分,其余部分会残留在输入缓冲区的情况,所以不适合。
其次为了避免出现上述问题,必须要在读取输入前,清空缓冲区的残留数据,可以用以下的方法解决:
(1) C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了,即使用fflush(stdin)
。某些编译器(如VC6)支持用 fflush(stdin) 来清空输入缓冲,但是并非所有编译器都要支持这个功能(linux 下的 gcc 就不支持),因为标准中根本没有定义 fflush(stdin),所以这种方法的移植性不是很好不建议使用;
(2) 自己取出缓冲区里的残留数据,即使用 while ((c = getchar()) != EOF && c != '\n');
,不停地使用getchar()获取缓冲中字符,直到获取的c是“\n”或文件结尾符EOF为止。
3.4 举例说明
使用 scanf()
和getchar()
输入读入字符的示例如下所示
#include <stdio.h>
int main()
{
char char1, char2, char3, char4;
scanf("%c%c%c%c", &char1, &char2, &char3, &char4);
printf("%d %d %d %d\n", char1, char2, char3, char4);
char c;
int i;
scanf("%c%d", &c, &i);
printf("变量c的值是:%c\n", c);
printf("变量i的值是:%d\n", i);
// fflush(stdin);
while ((c = getchar()) != EOF && c != '\n');
char ch1, ch2, ch3, ch4;
ch1 = getchar();
ch2 = getchar();
ch3 = getchar();
ch4 = getchar();
printf("%d %d %d %d\n", ch1, ch2, ch3, ch4);
return 0;
}
执行上面的代码可以获得如下的结果
这里可以看到,对于输入 “a b”, scanf()
将空格与回车符均作为输入,并且打印输出他们的 ascii 码;之后的 scanf()
没有打印输出空格的 ascii 码,是因为定义的输入是 int 型,所以没有将空格这个字符读入;getchar()
获得的结果与 scanf()
是一样的。
其次可以看到我们在这里清楚了输入缓冲区中的残留,否则 getchar()
会先读取缓冲区残留的回车,然后在读入键盘输入的部分;fflush(stdin)
在 ubuntu 下不可用,所以注释掉了。
使用 scanf()
和fgets()
输入读入字符的示例如下所示
#include <stdio.h>
int main()
{
char str1[20], str2[20];
printf("input is:");
scanf("%s",str1);
printf("output is : %s\n",str1);
scanf("%s",str2);
printf("output is : %s\n",str2);
char c;
while ((c = getchar()) != EOF && c != '\n');
printf("input is:");
char str3[20], str4[20];
fgets(str3, 20, stdin);
printf("output is : %s\n",str3);
fgets(str4, 20, stdin);
printf("output is : %s\n",str4);
return 0;
}
这里有两点需要注意,首先 gets()
在 ubuntu 下事会报错的,所以在这里使用 fgets()
替代,其次由于 scanf
不会清除最后的回车符号,所以这里我们还是手动清除缓冲区残留,执行后的结果如下所示
所以建议使用fgets()
读入字符串。
参考
[1] “小甲鱼” 视频课程《带你学C带你飞》【第一季】P13
[2] hao5743《scanf()和getchar() 使用》
[3] dophiJing CSDN 博客 《gets与scanf如何判断读取文件结束》
[4] guanyasu CSDN 博客《C语言清空输入缓冲区》
欢迎大家关注我的知乎号(左侧)和经常投稿的微信公众号(右侧)
相关阅读
在网上搜索了一个MySQL数据库删除重复数据的sql,原文是这样的: DELETE FROM people WHERE peopleName IN ( SELEC
select 1 from ... sql语句中的1代表什么意思?
select 1 from ..., sql语句中的1代表什么意思?查出来是个什么结果 select 1 from table;与select anycol(目的表集合中的任
一、什么是DML语句 DML语句就是数据库操作语句。 二、DML语句的分类 Insert 插入 Update 修
**一、效率高的写法 **1.无ORDER BY排序的写法。(效率最高)(经过测试,此方法成本最低,只嵌套一层,速度最快!即使查询的数据量再大,也几
sql语句 实现分页 /* 分页思想:比如你要每页获取10条记录,当你显示第5页的记录时,也就是选取第40条至50条的记录.首先应该从所有的记