基础 - 字符读取函数scanf、getchar、gets、cin(清空缓存区解决单字符回车问题)
0x01 scanf、getchar、cin读取单字符:
如下:
//scanf读取字符 回车问题
void Sub_1_1()
{
char v1,v2;
scanf("%c", &v1);
scanf("%c", &v2);
printf("%d %d\n", v1, v2); //回车问题
} /* scanf()和getchar()函数是从输入流缓冲区中读取值的,
而并非从键盘(也就是终端)缓冲区读取。
而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,
所以第一次接受输入时取走字符后会留下字符\n,
这样第二次的读入函数直接从缓冲区中把\n取走了,显然读取成功了,
所以不会再从终端读取! */ //getchar读取字符 回车问题
void Sub_1_2()
{
char ch1, ch2;
ch1 = getchar();
ch2 = getchar();
printf("%d %d\n", ch1, ch2); //回车问题
} //cin读取单字符 无回车问题
void Sub_1_3()
{
char ch1, ch2;
cin >> ch1;
cin >> ch2; cout << ch1 << endl;
cout << ch2 << endl; }
例如:
Sub_1_1、Sub_1_2 输入 a,输出:

Sub_1_3输入a,输出:

为什么这个形式呢?
先说一下输入操作原理:程序的输入都建有一个缓冲区,即输入缓冲区。当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入,
这里的10恰好是回车符,scanf()和getchar()函数是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,所以第一次接受输入时取走字符后会留下字符\n,这样第二次的读入函数直接从缓冲区中把\n取走了。
0x02 scanf()和gets()读取字符串:
//scanf()读取字符串 空格问题
void Sub_2_1()
{
char str1[], str2[];
scanf("%s",str1);
printf("%s\n",str1);
scanf("%s",str2);
printf("%s\n",str2); //空格问题 //hello world ->
//hello
//world
/*第一次输入Hello world!后,
字符串Hello world!都会被读到输入缓冲区中,
而scanf()函数取数据是遇到回车、空格、TAB就会停止,
也就是第一个scanf()会取出"Hello",而"world!"还在缓冲区中,
这样第二个scanf会直接取出这些数据,而不会等待从终端输入。*/ //scanf()读取字符串会舍弃最后的回车符!
//hello ->
//hello -> } //gets()读取字符串 接受空格
void Sub_2_2()
{
char str1[], str2[];
gets(str1);
printf("%s\n",str1);
gets(str2);
printf("%s\n",str2); }
先来看Sub_2_1,程序的功能是读入一个字符串输出,在读入一个字符串输出。可我们会发现输入的字符串中不能出现空格,例如:

这个问题的原因跟0x01类似,第一次输入Hello world后,字符串Hello world都会被读到输入缓冲区中,而scanf()函数取数据是遇到回车、空格、TAB就会停止,也就是第一个scanf()会取出"Hello",而"world"还在缓冲区中,这样第二个scanf会直接取出这些数据,而不会等待从终端输入
Sub_2_2,gets不会有这个问题:

总结:
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)。//似乎并没有用。
//setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区
方法2:自己取出缓冲区里的残留数据。
源代码(包括解决单字符回车问题):
#include <windows.h>
#include <IOSTREAM> using namespace std; void Sub_1_1();
void Sub_1_2();
void Sub_1_3(); void Sub_2_1();
void Sub_2_2(); int main ()
{
//scanf getchar
//Sub_1_1();
Sub_1_2();
//Sub_1_3(); /*****/
//scanf gets
// Sub_2_1();
//Sub_2_2();
} //setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区 //scanf读取字符 回车问题
void Sub_1_1()
{
char v1,v2; scanf("%c", &v1);
//setbuf(stdin, NULL); //解决回车问题
scanf("%c", &v2);
//setbuf(stdin, NULL); //解决回车问题
printf("%d %d\n", v1, v2); //回车问题
} /* scanf()和getchar()函数是从输入流缓冲区中读取值的,
而并非从键盘(也就是终端)缓冲区读取。
而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,
所以第一次接受输入时取走字符后会留下字符\n,
这样第二次的读入函数直接从缓冲区中把\n取走了,显然读取成功了,
所以不会再从终端读取! */ //getchar读取字符 回车问题
void Sub_1_2()
{
char ch1, ch2;
//setbuf(stdin, NULL); //解决回车问题
ch1 = getchar();
//setbuf(stdin, NULL); //解决回车问题
ch2 = getchar();
printf("%d %d\n", ch1, ch2); //回车问题
} //cin读取单字符 无回车问题
void Sub_1_3()
{
char ch1, ch2;
cin >> ch1;
cin >> ch2; cout << ch1 << endl;
cout << ch2 << endl; } //scanf()读取字符串 空格问题
void Sub_2_1()
{
char str1[], str2[];
scanf("%s",str1);
printf("%s\n",str1);
scanf("%s",str2);
printf("%s\n",str2); //空格问题 //hello world ->
//hello
//world
/*第一次输入Hello world!后,
字符串Hello world!都会被读到输入缓冲区中,
而scanf()函数取数据是遇到回车、空格、TAB就会停止,
也就是第一个scanf()会取出"Hello",而"world!"还在缓冲区中,
这样第二个scanf会直接取出这些数据,而不会等待从终端输入。*/ //scanf()读取字符串会舍弃最后的回车符!
//hello ->
//hello -> } //gets()读取字符串 接受空格
void Sub_2_2()
{
char str1[], str2[];
gets(str1);
printf("%s\n",str1);
gets(str2);
printf("%s\n",str2); } //总结
/*
读取字符时:
scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
这个函数是fflush(stdin)//似乎并没有用。
//setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区
方法2:自己取出缓冲区里的残留数据。
*/
基础 - 字符读取函数scanf、getchar、gets、cin(清空缓存区解决单字符回车问题)的更多相关文章
- 关于cin的缓存区影响效果
1. 当缓冲区中有残留数据时,cin函数会直接去读取这些残留数据而不会请求键盘输入.而且,回车符也会被存入输入缓冲区中. int num{}; while(cin>>num) cout&l ...
- UC编程:字符读取与行读取
字符读取函数的应用 下面的演示程序实现从/etc/passwd文件中提取用户名,打印到屏幕上并保存在copyname.txt文件中 使用的函数是getc().putc().putchar() [c] ...
- VBS基础篇 - 常用函数
Option Explicit '*********************************Date/Time函数******************************* 'CDate函 ...
- 深入了解scanf()/getchar()和gets()/cin等函数
转:http://www.cnblogs.com/FCWORLD/archive/2010/12/04/1896511.html 转:问题描述一:(分析scanf()和getchar()读取字符) s ...
- 深入了解scanf() getchar()和gets()等函数之间的区别
scanf(), getchar()等都是标准输入函数,一般人都会觉得这几个函数非常简单,没什么特殊的.但是有时候却就是因为使用这些函数除了问题,却找不出其中的原因.下面先看一个很简单的程序: 程序1 ...
- C语言初步学习I/O函数scanf、getchar、printf和putchar
scanf().printf().getchar()和putchar()这四个函数能够让用户和程序交流,所以被称为输入/输出函数,或简称为I/O函数. 这里先结合缓冲输入来讲讲scanf()和getc ...
- iOS 中基础字符判断函数收集(如判断大小写、数字等)
函数:isdigit 用法:#include 功能:判断字符c是否为数字 说明:当c为数字0-9时,返回非零值,否则返回零. 函数:islower 用法:#include 功能:判断字符c是否为小写英 ...
- PHP基础--strtr和str_replace字符替换函数
(一)strtr是字符替换函数 (1)单个字符替换: <?php echo strtr("abba", "ab", "10"),&qu ...
- scanf()/getchar()和gets()深入分析
C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数 ---------------------------------------------------- | ...
随机推荐
- Matlab:显(隐)式Euler和Richardson外推法变步长求解刚性问题
一.显示Euler 函数文件:Euler.m function f=Euler(h,Y) f(1,1)=Y(1)+h*(0.01-(1+(Y(1)+1000)*(Y(1)+1))*(0.01+Y(1) ...
- Linux 安装 ffmpeg
在安装ffmpeg之前,需要先安装一些必需组件.包括但不限于以下组件(有的系统里面可能已经安装过) 首先在根目录下创建:ffmpeg_sources 1.Yasm sudo apt-get insta ...
- Component(组件)
1.Component是一个模板的控制类用于处理应用和逻辑页面的视图部分. 2.Component时Angular2应用最基础的建筑砖块. 3.任何一个Component都是NgModule的一部分, ...
- day15_python_1124
03序列化模块 04加密模块 05 os sys 模块 06 collections 模块 # 03 序列化模块 # 网络传输数据:字节 bytes# 文件写入内容:bytes , str # dic ...
- day35-python 操作memcache一
memcache简介 Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象减少读取数据库的次数,从而提高动态.数据库驱动网站的速度. ...
- 调用shutdown.sh后出现could not contact localhost8005 tomcat may not be running报错问题
之前调用tomcat的shutdown.sh无法关闭tomcat,一直报could not contact localhost8005 tomcat may not be running错. 在网上找 ...
- js 面试知识点
基础 原型 原型链 作用域 闭包 异步 单线程 JS API DOM操作 AJAX 事件绑定 开发环境 版本管理 模块化 打包工具 运行环境 页面渲 ...
- SQL-43 将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。
题目描述 将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01.CREATE TABLE IF NOT EXISTS titles_test ...
- 《JavaScript Dom 编程艺术》读书笔记-第6章
本章继续对图片库进行改进,主要内容包括三个方面: 1. 把事件处理函数移出文档: 2. 向后兼容: 3. 确保可访问. 之前代码的HTML片段,此时如果浏览器不支持JS,图片显示也能正常工作,只是体验 ...
- springcloud Ribbon学习笔记一
上篇已经介绍了如何开发eureka服务并让多个服务进行相互注册,接下来记录如何开发一个服务然后注册到eureka中并能通过ribbon成功被调用 开发一个用户服务并注册到eureka中,用户服务负责访 ...