缓存区 及scanf() getchar() gets()的区别
2016-07-17 19:12
246 查看
首先,我先说一下对缓存区的理解
缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储
空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是
输出设备,分为输入缓冲区和输出缓冲区。
我这边以一个例子说下缓存区是如何进行工
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
printf("%d", n);
return 0;
}
首先,程序运行到scanf()时会停止,请求外界输入,然后比如你输入一个34然后回车,实际上你在键盘
上输入了字符'3''4'还有一个‘\0’;
当键盘输入结束时会将字符输入到缓存区中,scanf函数以及其他标准输入函数便会立刻从缓存区中获取
内容,然后按照%d的规则从缓存区中获取字符
它获取了''3''4' 并且将其转变为整数34 存入了变量n中,
题目要求scanf获取一个整数到n中
它完成了但是并没有结束 因为缓存区中并不干净 回车符'\n'仍然留
在缓存区中,这样加入还有一个scanf函数要求输入就一个字符,那么此时将不需要从键盘上面输入,会
自动将回车符给这个scanf函数
有一点要牢记,输入列表中的内容全是字符,格式说明符对于scanf是十分重要的,它便是“规则”
告诉
scanf如何从缓存区中获取字符并且如何做转换
以上基本是缓存区的工作道理,下面我将会说一些例子来进一步理解这几个函数
1.scanf(
)
(一)先看下scanf()对字符的处理
#include
int main()
{
char ch1, ch2;
scanf("%c", &ch1);
scanf("%c", &ch2);
printf("%d %d\n", ch1, ch2);
return 0;
}
我们准备输入字符a和b,但是我们会发现当我们输入a后回车准备继续输入时,你会发现此时已经结束,
并且输出结果为97 10,为什么会这样呢,因为当你输入a回车后,字符a和回车符‘\0’已经存储到缓存区
然后将字符a保存到ch1 中,可是此时缓存区中有存留了'\0',当运行到第二个scanf时,就不会等待外界
输入而是直接将'\0'存储到ch2中,并以%d输出,及为10
(二)scanf()对字符串的处理
#include
<stdio.h>
int main()
{
char n1[10],n2[10];
scanf("%s",n1);
scanf("%s",n2);
printf("n1 = %s, n2 = %s\n", n1, n2 );
return 0;
}
输入:hello回车world回车
得到如下的输出:
n1=hello,n2=wolrd光标处(程序结束)
这里hello后面就是输入再多个回车、空格也不会被赋值到n2中的,因为使用scanf函数输入字符串的
时候他们只是被当做分隔符。另外就是输入n2的时候,n2后面的那个回车也被当做了分隔符,所以输
出的时候,只是简单的输出了n1和n2的内容,而没有输出回车换行符。
如果再定义一个字符变量n3,并在printf后加上
scanf("%c", &n3);
printf("%c", n3):
输入:hello回车world回车
得到:
n1=hello,n2=wolrd
光标处(程序结束)
说明此时缓冲区内只有一个'\n ',这说明了 scanf不会把回车、空格赋给字符串但是会赋给字符
总结一下就是:
如果scanf输入的不是字符,那么分隔符为回车,空格、tab键时,两个数据之间的分隔符只是
起区别两个数据的作用,把分隔好的两个数据分别赋值到各自定义好的变量或数组中去,两个
数据之间的分隔符被从缓冲区读出但是不起任何作用,当然最后一个'\n '会被留在缓冲区内,除
非用getchar();或scanf("%c",&c);把它读出来。回车是一定要有的,不管getchar还是scanf只要
通过缓冲区输入数据的函数都是等待回车键'\n '出现才进入缓冲区的。
2.getchar()
getchar()是stdio.h中的库函数,它的作用是从标准输入流中读入一个字符,也就是说,如果缓存区
有数据的话不用输
入它就可以直接读取了。
#include <stdio.h>
int main()
{
char ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d\n", ch1, ch2);
return 0;
}用上面的例子来说一下getchar,同样输入a回车符,结果与scanf的结果是一样的,当程序
调用getchar()函数时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户
按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar()函数才开始从键盘缓
冲区中每次读入一个字符。也就是说,后续的getchar()函数调用不会等待用户按键,而直接读取
缓冲区中的字符,直到缓冲区中的字符读完后,才重新等待用户按键。
通俗一点说,当程序调用getchar()函数时,程序就等着用户按键,并等用户按下回车键返回。期间
按下的字符存放在缓冲区,
第一个字符作为函数返回值。继续调用getchar()函数,将不再等用户按键,而是返回您刚才输入的
第2个字符;继续调用,返回第3个字符,直到缓冲区中的字符读完后,才等待用户按键。
3.gets( )
#include <stdio.h>
int main()
{
char str1[20], str2[20];
scanf("%s",str1);
printf("%s\n",str1);
scanf("%s",str2);
printf("%s\n",str2);
return 0;
}
程序的功能是读入一个字符串输出,在读入一个字符串输出。可我们会发现输入的字符串中不能出现空格,例如:
测试一输入 Hello world!
输出 Hello
world!
到此程序执行完毕,不会执行第二次的读取操作!这个问题的原因跟问题一类似,第一次输入Hello
world!后,字符串Hello world!都会被读到输入缓冲区中,而scanf()函数取数据是遇到回车、空格、
TAB就会停止,也就是第一个scanf()会取出"Hello", 而"world!"还在缓冲区中,这样第二个scanf
会直接取出这些数据,而不会等待从终端输入。
测试二输入Hello
输出Hello
输入world
输出world
程序执行了两次从键盘读入字符串,说明第一次输入结束时的回车符被丢弃!即:scanf()读取字符
串会舍弃最后的回车符!
我们再看一下gets()读取字符串的情况:
用scanf来读取一个字符串时,字符串中是不可以出现空格的,一旦出现空格,后面的数据就会舍弃
残留在缓冲区中。其实有另外一个函数是可以接受空格的,那就是gets(),下面我们看一下这个函数
的应用,
我们把上面程序改动一下
#include <stdio.h>
int main()
{
char str1[20], str2[20];
gets(str1);
printf("%s\n",str1);
gets(str2);
printf("%s\n",str2);
return 0;
}
输入 Hello world!
输出 Hello world!
输入 12345
输出 12345
显然与上一个程序的执行情况不同,这次程序执行了两次从键盘的读入,而且第一个字符串取了
Hello world! 接受了空格符,而没有像上一个程序那样分成了两个字符串!所以如果要读入一个
带空格符的字符串时因该用gets(), 而不宜用scanf()!
对三个函数进行下总结
第一:要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)
缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储
空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是
输出设备,分为输入缓冲区和输出缓冲区。
我这边以一个例子说下缓存区是如何进行工
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
printf("%d", n);
return 0;
}
首先,程序运行到scanf()时会停止,请求外界输入,然后比如你输入一个34然后回车,实际上你在键盘
上输入了字符'3''4'还有一个‘\0’;
当键盘输入结束时会将字符输入到缓存区中,scanf函数以及其他标准输入函数便会立刻从缓存区中获取
内容,然后按照%d的规则从缓存区中获取字符
它获取了''3''4' 并且将其转变为整数34 存入了变量n中,
题目要求scanf获取一个整数到n中
它完成了但是并没有结束 因为缓存区中并不干净 回车符'\n'仍然留
在缓存区中,这样加入还有一个scanf函数要求输入就一个字符,那么此时将不需要从键盘上面输入,会
自动将回车符给这个scanf函数
有一点要牢记,输入列表中的内容全是字符,格式说明符对于scanf是十分重要的,它便是“规则”
告诉
scanf如何从缓存区中获取字符并且如何做转换
以上基本是缓存区的工作道理,下面我将会说一些例子来进一步理解这几个函数
1.scanf(
)
(一)先看下scanf()对字符的处理
#include
int main()
{
char ch1, ch2;
scanf("%c", &ch1);
scanf("%c", &ch2);
printf("%d %d\n", ch1, ch2);
return 0;
}
我们准备输入字符a和b,但是我们会发现当我们输入a后回车准备继续输入时,你会发现此时已经结束,
并且输出结果为97 10,为什么会这样呢,因为当你输入a回车后,字符a和回车符‘\0’已经存储到缓存区
然后将字符a保存到ch1 中,可是此时缓存区中有存留了'\0',当运行到第二个scanf时,就不会等待外界
输入而是直接将'\0'存储到ch2中,并以%d输出,及为10
(二)scanf()对字符串的处理
#include
<stdio.h>
int main()
{
char n1[10],n2[10];
scanf("%s",n1);
scanf("%s",n2);
printf("n1 = %s, n2 = %s\n", n1, n2 );
return 0;
}
输入:hello回车world回车
得到如下的输出:
n1=hello,n2=wolrd光标处(程序结束)
这里hello后面就是输入再多个回车、空格也不会被赋值到n2中的,因为使用scanf函数输入字符串的
时候他们只是被当做分隔符。另外就是输入n2的时候,n2后面的那个回车也被当做了分隔符,所以输
出的时候,只是简单的输出了n1和n2的内容,而没有输出回车换行符。
如果再定义一个字符变量n3,并在printf后加上
scanf("%c", &n3);
printf("%c", n3):
输入:hello回车world回车
得到:
n1=hello,n2=wolrd
光标处(程序结束)
说明此时缓冲区内只有一个'\n ',这说明了 scanf不会把回车、空格赋给字符串但是会赋给字符
总结一下就是:
如果scanf输入的不是字符,那么分隔符为回车,空格、tab键时,两个数据之间的分隔符只是
起区别两个数据的作用,把分隔好的两个数据分别赋值到各自定义好的变量或数组中去,两个
数据之间的分隔符被从缓冲区读出但是不起任何作用,当然最后一个'\n '会被留在缓冲区内,除
非用getchar();或scanf("%c",&c);把它读出来。回车是一定要有的,不管getchar还是scanf只要
通过缓冲区输入数据的函数都是等待回车键'\n '出现才进入缓冲区的。
2.getchar()
getchar()是stdio.h中的库函数,它的作用是从标准输入流中读入一个字符,也就是说,如果缓存区
有数据的话不用输
入它就可以直接读取了。
#include <stdio.h>
int main()
{
char ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d\n", ch1, ch2);
return 0;
}用上面的例子来说一下getchar,同样输入a回车符,结果与scanf的结果是一样的,当程序
调用getchar()函数时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户
按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar()函数才开始从键盘缓
冲区中每次读入一个字符。也就是说,后续的getchar()函数调用不会等待用户按键,而直接读取
缓冲区中的字符,直到缓冲区中的字符读完后,才重新等待用户按键。
通俗一点说,当程序调用getchar()函数时,程序就等着用户按键,并等用户按下回车键返回。期间
按下的字符存放在缓冲区,
第一个字符作为函数返回值。继续调用getchar()函数,将不再等用户按键,而是返回您刚才输入的
第2个字符;继续调用,返回第3个字符,直到缓冲区中的字符读完后,才等待用户按键。
3.gets( )
#include <stdio.h>
int main()
{
char str1[20], str2[20];
scanf("%s",str1);
printf("%s\n",str1);
scanf("%s",str2);
printf("%s\n",str2);
return 0;
}
程序的功能是读入一个字符串输出,在读入一个字符串输出。可我们会发现输入的字符串中不能出现空格,例如:
测试一输入 Hello world!
输出 Hello
world!
到此程序执行完毕,不会执行第二次的读取操作!这个问题的原因跟问题一类似,第一次输入Hello
world!后,字符串Hello world!都会被读到输入缓冲区中,而scanf()函数取数据是遇到回车、空格、
TAB就会停止,也就是第一个scanf()会取出"Hello", 而"world!"还在缓冲区中,这样第二个scanf
会直接取出这些数据,而不会等待从终端输入。
测试二输入Hello
输出Hello
输入world
输出world
程序执行了两次从键盘读入字符串,说明第一次输入结束时的回车符被丢弃!即:scanf()读取字符
串会舍弃最后的回车符!
我们再看一下gets()读取字符串的情况:
用scanf来读取一个字符串时,字符串中是不可以出现空格的,一旦出现空格,后面的数据就会舍弃
残留在缓冲区中。其实有另外一个函数是可以接受空格的,那就是gets(),下面我们看一下这个函数
的应用,
我们把上面程序改动一下
#include <stdio.h>
int main()
{
char str1[20], str2[20];
gets(str1);
printf("%s\n",str1);
gets(str2);
printf("%s\n",str2);
return 0;
}
输入 Hello world!
输出 Hello world!
输入 12345
输出 12345
显然与上一个程序的执行情况不同,这次程序执行了两次从键盘的读入,而且第一个字符串取了
Hello world! 接受了空格符,而没有像上一个程序那样分成了两个字符串!所以如果要读入一个
带空格符的字符串时因该用gets(), 而不宜用scanf()!
对三个函数进行下总结
第一:要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)
相关文章推荐
- exchange2010动态通讯组
- Android必知必会-发布开源 Android 项目注意事项
- Android必知必会-发布开源 Android 项目注意事项
- 关于进制之间的转化问题
- 移除未排序链表中的重复结点
- transformX和projectionCenter的设置
- XLT的unity3D学习笔记(一)
- 1002. 写出这个数 (20)
- 可变参数函数分析(va_list,va_start(),va_end())
- Android线程和线程池
- phpStudy for Linux (lnmp+lamp一键安装包)
- HDU 2102 A计划
- ParalleX OS 设计与实现 启动篇multiboot方式
- GNS3-1.0 IOU lincense出现无效证书的解决方式
- 加载plist数据
- HBase hbck——检察HBase集群Region的一致性
- 面试题-----(StringBuffer)
- JSP概述
- Python学习进程(3)Python基本数据类型
- 初识Yarn, Mesos and Borg