欢迎关注WX公众号:【程序员管小亮】
专栏C++学习笔记
声明
1)本文仅供学术交流,非商用。所以部分参考资料并没有详细对应。如果某部分不小心侵犯了大家的利益,还望海涵,并联系博主删除。
2)博主才疏学浅,文中如有不当之处,请各位指出,共同进步,谢谢。
3)此属于第一版本,若有错误,还需继续修正与增删。还望大家多多指点。大家都共享一点点,一起为祖国科研的推进添砖加瓦。
〇、写在前面
最近认真钻研了一下,scanf
、gets
和 getchar
的区别,发现好多写的博客都很凌乱,看了半天不知所云为何物,决定自己写一个博客记录总结一下。
一、字符
1、scanf(%c)
首先要说的是 scanf
,它是格式输入函数,标准格式如下:
int scanf(const char * restrict format,...);
从 标准输入流(stdin)
中按照说明的格式读入多个字符,并存入 以输入参数的值为地址的变量 中,所以必须得有 &
,除了把字符串读入字符数组中。
为啥?
很简单,因为数组变量名称本身就是特殊的指针,即,数组首元素的地址,故无需使用 &
取地址,完事。
举个例子:
char a[10];
scanf("%s",a);
没有 &
地址符,程序正常运行。
scanf
在遇到 空格符
、回车符(\n)
和 制表符(\t)
时,都会认为本次输入结束,所有它不能接收 空格符
还有 回车符(\n)
,那么它是如何处理 回车符(\n)
的呢?
除了一种特殊情况:
scanf()
会忽略行开头的所有空格
!!!
scanf
对 末尾回车符 的处理是把 回车符(\n)
保留在缓存中。
#include<stdio.h>
int main(){
char a,ch;
int count=0;
while(1){
scanf("%c",&a);
count++;
printf("**************\n");
printf("%d\n",count);
}
return 0;
}
首先输入 a
,然后 回车
,因为scanf
对 末尾回车符 的处理是把 回车符(\n)
保留在缓存中,所以除了 a
之外,还有 回车
也被读进来了,即,每次蹦两个数字。
这一点和 gets
是不同的!!!在后面的 gets
中会有详细地介绍。
小结:
不接收 空格
,不接收 回车
。
2、getchar
接着要说的,是 getchar()
函数。
它的作用是从键盘获取且只能获取一个字符。
定义如下:
int getchar(void)
getchar()
函数是可以接收 空格
的,但是不能接收 回车
。即最后的 回车符
也不会被接收,getchar()
是会舍弃最后的 回车符
的。
回车
是干啥用的呢?
因为 getchar
函数只能输入字符型,所以在输入时遇到 回车键(\n)
才从缓冲区依次提取字符,遇到 空格符
不会结束,而是会接收它!!!
下面来看一个例子:
#include<stdio.h>
int main(){
char a,ch;
int count=0;
while((ch=getchar())!='q'){
count++;
printf("**************\n");
printf("%d\n",count);
}
return 0;
}
首先确定的一件事是,getchar
是不接收 回车
的,所以正常情况下的计数应该是1。
也同样是因为它本身只能接收1个字符,所以这个 回车
被留在缓存流中了,而我们这里的程序是遇到 q
才停止,故而程序又循环了一下,相当于输入了一个 回车
!!!
如果稍微修改一下程序为:
#include<stdio.h>
int main(){
char a,ch;
int count=0;
while((ch=getchar())!='\n'){
count++;
printf("**************\n");
printf("%d\n",count);
}
return 0;
}
可以看到程序只运行了一次就停止了,因为 回车
是留在缓存流中的,默认输入了。
小结:
接收 空格
,不接收 回车
。
3、实例
总结一下两个函数的使用:
输入完成后:
scanf
把数据一把全梭了;getchar
把数据一个一个从兜里掏。
在很多时候会出现这样一种情况,即先输入了一个 scanf
的语句,然后可能要用到 gets
,这个时候上一个 scanf
留下的 回车
就会打搅乱下面的数据读取!!!这个时候就需要加一个 回车符(\n)
,用 scanf('\n);
;或者读取这个 回车符(\n)
,用 gets();
或 getchar();
。
比如最近在做PTA上的C语言题库时发现的一个题:
给定 n
本书的名称和定价,本题要求编写程序,查找并输出其中定价最高和最低的书的名称和定价。
#include<stdio.h>
struct book{
char name[31];
double price;
};
int main(){
struct book a[10];
int i;
double max=-1,min=10000;
int flag1=0,flag2=0;
int n;
scanf("%d",&n);
for(i=0;i<n;++i){
scanf("\n"); // 去除回车
//gets();
//getchar();
gets(a[i].name);
scanf("%lf",&a[i].price);
if(max<a[i].price){
max=a[i].price;
flag1=i;
}
if(min>a[i].price){
min=a[i].price;
flag2=i;
}
}
printf("%.2lf, %s\n",a[flag1].price,a[flag1].name);
printf("%.2lf, %s\n",a[flag2].price,a[flag2].name);
return 0;
}
首先使用 scanf
输入的书的数量3,留下了一个 回车
,如果在这里直接接着使用一个 scanf
的话,就会出错:
因为 回车
会留在缓存流中,并被下一个函数 get
读取到,从而扰乱了本来的数据读取,继而出现了非预期结果。
小结:
一定要注意 scanf
的 回车符
!!!
二、字符串
1、scanf(%s)
%c
和 %s
的区别是一个是字符,一个是字符串,从这里可以看得出,scanf
函数能对各种类型进行输入,
而不仅仅局限于字符或是字符串,而字符是 getchar
,字符串是 gets
。
不过,无论是对待字符还是字符串,scanf
的处理都是比较相似的,这一点倒是比较容易学习和使用,但是 来自 pudn
,只有一段开头话:
-
中文版本:在数据大量的情况下,用
gets
读取快于scanf()
10倍以上。 -
英文版本:A large number of cases in the data, using
gets
read faster thanscanf
10 times.
小结:
不接收 空格
和 回车
2、gets
到这里,你应该不会忘记上面说过的 scanf
是如何处理 回车符(\n)
的了,这一点和 gets
是差别巨大的!!!
gets
对末尾 回车符
的处理方式是,接收 回车
,但把 回车
替换为 \0
,不像 scanf
是留在缓存中,所以在用 gets
时,要注意数组的大小增加1,不然就会出现数组越界等问题。
还是看个例子,还是上面那个题,虽然题中说的是不超过30个字符,但是因为还有一个 回车符
转换成的 空字符
,所以数组大小需要加1!!!
除了 回车
就是 空格
的问题了,gets
是接收 空格
的,也就是可以读取并输出 空格
。
终止的标志是 Enter
结束输入(空格不结束),比如这里的 Hello
和 World
之间的空格就是正常的。
#include<stdio.h>
#include<string.h>
int main(){
char a[100];
gets(a);
int i;
for(i=0;i<strlen(a);i++){
printf("%c",a[i]);
}
return 0;
}
如果换成 scanf
的话,就只能读取一半了,因为空格也是它的终止符!
#include<stdio.h>
#include<string.h>
int main(){
char a[100];
int i;
scanf("%s",&a);
for(i=0;i<strlen(a);i++){
printf("%c",a[i]);
}
return 0;
}
小结:
接收 空格
和 回车
3、实例
最直接的方式进行对比就是求一下字符串的长度。
#include<stdio.h>
#include<string.h>
int main(){
char a[100];
gets(a);
printf("%d",strlen(a));
return 0;
}
#include<stdio.h>
#include<string.h>
int main(){
char a[100];
// gets(a);
scanf("%s",&a);
printf("%d",strlen(a));
return 0;
}
这也就解释了为什么前面要用 gets
或者是 getchar
去去除 回车
。
三、总结
scanf
忽略行开头的所有空格,并以各种格式化进行数据输入,直到遇到空格
、回车
结束输入,不接收空格
和回车
,留在缓存区中;getchar
只读取一个字符,包括空格
但是不包括回车
,回车
会留在缓冲区中;gets
读取以任何字符开头的字符串,读取的字符串包括空格
但是不包括回车
,以回车
结束输入,接收空格
和回车
,但之后会丢弃回车
并以\0
代替;
最后的一个图给出常用的 while
表达形式:
参考文章
- https://zhidao.baidu.com/question/63301588.html
- https://www.php.cn/faq/415503.html
- https://www.runoob.com/cprogramming/c-tutorial.html
- https://www.cnblogs.com/hlongch/p/5742477.html
转载:https://blog.csdn.net/TeFuirnever/article/details/103930814