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(清空缓存区解决单字符回车问题)的更多相关文章

  1. 关于cin的缓存区影响效果

    1. 当缓冲区中有残留数据时,cin函数会直接去读取这些残留数据而不会请求键盘输入.而且,回车符也会被存入输入缓冲区中. int num{}; while(cin>>num) cout&l ...

  2. UC编程:字符读取与行读取

    字符读取函数的应用 下面的演示程序实现从/etc/passwd文件中提取用户名,打印到屏幕上并保存在copyname.txt文件中 使用的函数是getc().putc().putchar() [c] ...

  3. VBS基础篇 - 常用函数

    Option Explicit '*********************************Date/Time函数******************************* 'CDate函 ...

  4. 深入了解scanf()/getchar()和gets()/cin等函数

    转:http://www.cnblogs.com/FCWORLD/archive/2010/12/04/1896511.html 转:问题描述一:(分析scanf()和getchar()读取字符) s ...

  5. 深入了解scanf() getchar()和gets()等函数之间的区别

    scanf(), getchar()等都是标准输入函数,一般人都会觉得这几个函数非常简单,没什么特殊的.但是有时候却就是因为使用这些函数除了问题,却找不出其中的原因.下面先看一个很简单的程序: 程序1 ...

  6. C语言初步学习I/O函数scanf、getchar、printf和putchar

    scanf().printf().getchar()和putchar()这四个函数能够让用户和程序交流,所以被称为输入/输出函数,或简称为I/O函数. 这里先结合缓冲输入来讲讲scanf()和getc ...

  7. iOS 中基础字符判断函数收集(如判断大小写、数字等)

    函数:isdigit 用法:#include 功能:判断字符c是否为数字 说明:当c为数字0-9时,返回非零值,否则返回零. 函数:islower 用法:#include 功能:判断字符c是否为小写英 ...

  8. PHP基础--strtr和str_replace字符替换函数

    (一)strtr是字符替换函数 (1)单个字符替换: <?php echo strtr("abba", "ab", "10"),&qu ...

  9. scanf()/getchar()和gets()深入分析

    C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数 ---------------------------------------------------- | ...

随机推荐

  1. 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) ...

  2. Linux 安装 ffmpeg

    在安装ffmpeg之前,需要先安装一些必需组件.包括但不限于以下组件(有的系统里面可能已经安装过) 首先在根目录下创建:ffmpeg_sources 1.Yasm sudo apt-get insta ...

  3. Component(组件)

    1.Component是一个模板的控制类用于处理应用和逻辑页面的视图部分. 2.Component时Angular2应用最基础的建筑砖块. 3.任何一个Component都是NgModule的一部分, ...

  4. day15_python_1124

    03序列化模块 04加密模块 05 os sys 模块 06 collections 模块 # 03 序列化模块 # 网络传输数据:字节 bytes# 文件写入内容:bytes , str # dic ...

  5. day35-python 操作memcache一

    memcache简介 Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象减少读取数据库的次数,从而提高动态.数据库驱动网站的速度. ...

  6. 调用shutdown.sh后出现could not contact localhost8005 tomcat may not be running报错问题

    之前调用tomcat的shutdown.sh无法关闭tomcat,一直报could not contact localhost8005 tomcat may not be running错. 在网上找 ...

  7. js 面试知识点

    基础           原型  原型链 作用域  闭包 异步  单线程 JS API        DOM操作 AJAX 事件绑定 开发环境    版本管理 模块化 打包工具 运行环境    页面渲 ...

  8. 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 ...

  9. 《JavaScript Dom 编程艺术》读书笔记-第6章

    本章继续对图片库进行改进,主要内容包括三个方面: 1. 把事件处理函数移出文档: 2. 向后兼容: 3. 确保可访问. 之前代码的HTML片段,此时如果浏览器不支持JS,图片显示也能正常工作,只是体验 ...

  10. springcloud Ribbon学习笔记一

    上篇已经介绍了如何开发eureka服务并让多个服务进行相互注册,接下来记录如何开发一个服务然后注册到eureka中并能通过ribbon成功被调用 开发一个用户服务并注册到eureka中,用户服务负责访 ...