0x01 scanf、getchar、cin读取单字符:

如下:

  1. //scanf读取字符 回车问题
  2. void Sub_1_1()
  3. {
  4. char v1,v2;
  5. scanf("%c", &v1);
  6. scanf("%c", &v2);
  7. printf("%d %d\n", v1, v2);
  8.  
  9. //回车问题
  10. }
  11.  
  12. /* scanf()和getchar()函数是从输入流缓冲区中读取值的,
  13. 而并非从键盘(也就是终端)缓冲区读取。
  14. 而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,
  15. 所以第一次接受输入时取走字符后会留下字符\n,
  16. 这样第二次的读入函数直接从缓冲区中把\n取走了,显然读取成功了,
  17. 所以不会再从终端读取! */
  18.  
  19. //getchar读取字符 回车问题
  20. void Sub_1_2()
  21. {
  22. char ch1, ch2;
  23. ch1 = getchar();
  24. ch2 = getchar();
  25. printf("%d %d\n", ch1, ch2);
  26.  
  27. //回车问题
  28. }
  29.  
  30. //cin读取单字符 无回车问题
  31. void Sub_1_3()
  32. {
  33. char ch1, ch2;
  34. cin >> ch1;
  35. cin >> ch2;
  36.  
  37. cout << ch1 << endl;
  38. cout << ch2 << endl;
  39.  
  40. }

例如:

Sub_1_1、Sub_1_2 输入 a,输出:

Sub_1_3输入a,输出:

为什么这个形式呢?

先说一下输入操作原理:程序的输入都建有一个缓冲区,即输入缓冲区。当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入,

这里的10恰好是回车符,scanf()和getchar()函数是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,所以第一次接受输入时取走字符后会留下字符\n,这样第二次的读入函数直接从缓冲区中把\n取走了。

0x02 scanf()和gets()读取字符串:

  1. //scanf()读取字符串 空格问题
  2. void Sub_2_1()
  3. {
  4. char str1[], str2[];
  5. scanf("%s",str1);
  6. printf("%s\n",str1);
  7. scanf("%s",str2);
  8. printf("%s\n",str2);
  9.  
  10. //空格问题
  11.  
  12. //hello world ->
  13. //hello
  14. //world
  15. /*第一次输入Hello world!后,
  16. 字符串Hello world!都会被读到输入缓冲区中,
  17. 而scanf()函数取数据是遇到回车、空格、TAB就会停止,
  18. 也就是第一个scanf()会取出"Hello",而"world!"还在缓冲区中,
  19. 这样第二个scanf会直接取出这些数据,而不会等待从终端输入。*/
  20.  
  21. //scanf()读取字符串会舍弃最后的回车符!
  22. //hello ->
  23. //hello ->
  24.  
  25. }
  26.  
  27. //gets()读取字符串 接受空格
  28. void Sub_2_2()
  29. {
  30. char str1[], str2[];
  31. gets(str1);
  32. printf("%s\n",str1);
  33. gets(str2);
  34. printf("%s\n",str2);
  35.  
  36. }

先来看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:自己取出缓冲区里的残留数据。

源代码(包括解决单字符回车问题):

  1. #include <windows.h>
  2. #include <IOSTREAM>
  3.  
  4. using namespace std;
  5.  
  6. void Sub_1_1();
  7. void Sub_1_2();
  8. void Sub_1_3();
  9.  
  10. void Sub_2_1();
  11. void Sub_2_2();
  12.  
  13. int main ()
  14. {
  15. //scanf getchar
  16. //Sub_1_1();
  17. Sub_1_2();
  18. //Sub_1_3();
  19.  
  20. /*****/
  21. //scanf gets
  22. // Sub_2_1();
  23. //Sub_2_2();
  24. }
  25.  
  26. //setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区
  27.  
  28. //scanf读取字符 回车问题
  29. void Sub_1_1()
  30. {
  31. char v1,v2;
  32.  
  33. scanf("%c", &v1);
  34. //setbuf(stdin, NULL); //解决回车问题
  35. scanf("%c", &v2);
  36. //setbuf(stdin, NULL); //解决回车问题
  37. printf("%d %d\n", v1, v2);
  38.  
  39. //回车问题
  40. }
  41.  
  42. /* scanf()和getchar()函数是从输入流缓冲区中读取值的,
  43. 而并非从键盘(也就是终端)缓冲区读取。
  44. 而读取时遇到回车(\n)而结束的,这个\n会一起读入输入流缓冲区的,
  45. 所以第一次接受输入时取走字符后会留下字符\n,
  46. 这样第二次的读入函数直接从缓冲区中把\n取走了,显然读取成功了,
  47. 所以不会再从终端读取! */
  48.  
  49. //getchar读取字符 回车问题
  50. void Sub_1_2()
  51. {
  52. char ch1, ch2;
  53. //setbuf(stdin, NULL); //解决回车问题
  54. ch1 = getchar();
  55. //setbuf(stdin, NULL); //解决回车问题
  56. ch2 = getchar();
  57. printf("%d %d\n", ch1, ch2);
  58.  
  59. //回车问题
  60. }
  61.  
  62. //cin读取单字符 无回车问题
  63. void Sub_1_3()
  64. {
  65. char ch1, ch2;
  66. cin >> ch1;
  67. cin >> ch2;
  68.  
  69. cout << ch1 << endl;
  70. cout << ch2 << endl;
  71.  
  72. }
  73.  
  74. //scanf()读取字符串 空格问题
  75. void Sub_2_1()
  76. {
  77. char str1[], str2[];
  78. scanf("%s",str1);
  79. printf("%s\n",str1);
  80. scanf("%s",str2);
  81. printf("%s\n",str2);
  82.  
  83. //空格问题
  84.  
  85. //hello world ->
  86. //hello
  87. //world
  88. /*第一次输入Hello world!后,
  89. 字符串Hello world!都会被读到输入缓冲区中,
  90. 而scanf()函数取数据是遇到回车、空格、TAB就会停止,
  91. 也就是第一个scanf()会取出"Hello",而"world!"还在缓冲区中,
  92. 这样第二个scanf会直接取出这些数据,而不会等待从终端输入。*/
  93.  
  94. //scanf()读取字符串会舍弃最后的回车符!
  95. //hello ->
  96. //hello ->
  97.  
  98. }
  99.  
  100. //gets()读取字符串 接受空格
  101. void Sub_2_2()
  102. {
  103. char str1[], str2[];
  104. gets(str1);
  105. printf("%s\n",str1);
  106. gets(str2);
  107. printf("%s\n",str2);
  108.  
  109. }
  110.  
  111. //总结
  112. /*
  113. 读取字符时:
  114. scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
  115. getchar()以Enter结束输入,也不会舍弃最后的回车符;
  116. 读取字符串时:
  117. scanf()以Space、Enter、Tab结束一次输入
  118. gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
  119. 第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
  120. 方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
  121. 这个函数是fflush(stdin)//似乎并没有用。
  122. //setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区
  123. 方法2:自己取出缓冲区里的残留数据。
  124. */

基础 - 字符读取函数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. ZCRM_AU_MAIL

    FUNCTION ZCRM_AU_MAIL. *"---------------------------------------------------------------------- ...

  2. [poj P2411] Mondriaan's Dream

    [poj P2411] Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 18023   A ...

  3. mst总结

     1.jsonp跨域 Jsop的原理:利用script不存在跨域的问题,动态创建script标签,把需要请求的数据源地址赋值给其src属性,并且指定一个回调函数,从而接受到我们想要的数据 后台设置下 ...

  4. 深入剖析Java中的装箱和拆箱(缓存池技术)

    以下是本文的目录大纲: 一.什么是装箱?什么是拆箱? 简单一点说,装箱就是  自动将基本数据类型转换为包装器类型:拆箱就是  自动将包装器类型转换为基本数据类型. 二.装箱和拆箱是如何实现的 1:反编 ...

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

  6. copy GC 和 mark & compaction GC的算法异同

    先标记 然后 copy GC是,对所有child,判断, 如果child没有被访问过,那么拷贝到新地址,child的forwording指向新地址,child标记为已访问,把自己对child的引用改为 ...

  7. [BUG]读配置文件中文, 查询不到数据库

    配置文件编码, 要和数据库编码一致

  8. lettuce行为驱动框架实例

    练习: 一:e1_MyFirstBDD 使用方法的方式实现阶乘的计算 zero.feature: Feature: Compute factorial In order to play with Le ...

  9. Cortex-M3的一些概念

    [工作模式] 线程模式(Thread mode):处理器复位或异常退出时为此模式.此模式下的代码可以是特权代码也可以是用户代码,通过CONTROL[0]控制.处理模式(Handler mode):出现 ...

  10. mod_conference ESL控制二(事件)

    根据上篇所述功能需求,esl需要处理以下几类事件: ESL_EVENT_CHANNEL_*  #channel相关事件,用户判断参会者是否应答.计费 DTMF事件 #识别参会者按键,根据按键进行操作( ...