基础 - 字符读取函数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()等函数 ---------------------------------------------------- | ...
随机推荐
- ZCRM_AU_MAIL
FUNCTION ZCRM_AU_MAIL. *"---------------------------------------------------------------------- ...
- [poj P2411] Mondriaan's Dream
[poj P2411] Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 18023 A ...
- mst总结
1.jsonp跨域 Jsop的原理:利用script不存在跨域的问题,动态创建script标签,把需要请求的数据源地址赋值给其src属性,并且指定一个回调函数,从而接受到我们想要的数据 后台设置下 ...
- 深入剖析Java中的装箱和拆箱(缓存池技术)
以下是本文的目录大纲: 一.什么是装箱?什么是拆箱? 简单一点说,装箱就是 自动将基本数据类型转换为包装器类型:拆箱就是 自动将包装器类型转换为基本数据类型. 二.装箱和拆箱是如何实现的 1:反编 ...
- Guess Number Game
We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...
- copy GC 和 mark & compaction GC的算法异同
先标记 然后 copy GC是,对所有child,判断, 如果child没有被访问过,那么拷贝到新地址,child的forwording指向新地址,child标记为已访问,把自己对child的引用改为 ...
- [BUG]读配置文件中文, 查询不到数据库
配置文件编码, 要和数据库编码一致
- lettuce行为驱动框架实例
练习: 一:e1_MyFirstBDD 使用方法的方式实现阶乘的计算 zero.feature: Feature: Compute factorial In order to play with Le ...
- Cortex-M3的一些概念
[工作模式] 线程模式(Thread mode):处理器复位或异常退出时为此模式.此模式下的代码可以是特权代码也可以是用户代码,通过CONTROL[0]控制.处理模式(Handler mode):出现 ...
- mod_conference ESL控制二(事件)
根据上篇所述功能需求,esl需要处理以下几类事件: ESL_EVENT_CHANNEL_* #channel相关事件,用户判断参会者是否应答.计费 DTMF事件 #识别参会者按键,根据按键进行操作( ...