zoukankan      html  css  js  c++  java
  • 基础

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

    如下:

    //scanf读取字符 回车问题
    void Sub_1_1()
    {
        char v1,v2;
        scanf("%c", &v1);
        scanf("%c", &v2);
        printf("%d %d
    ", v1, v2);
    
        //回车问题
    }
    
    /* scanf()和getchar()函数是从输入流缓冲区中读取值的,
        而并非从键盘(也就是终端)缓冲区读取。
        而读取时遇到回车(
    )而结束的,这个
    会一起读入输入流缓冲区的,
        所以第一次接受输入时取走字符后会留下字符
    ,
        这样第二次的读入函数直接从缓冲区中把
    取走了,显然读取成功了,
        所以不会再从终端读取! */
    
    //getchar读取字符 回车问题
    void Sub_1_2()
    {
        char ch1, ch2;
        ch1 = getchar();
        ch2 = getchar();
        printf("%d %d
    ", 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()函数是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。而读取时遇到回车( )而结束的,这个 会一起读入输入流缓冲区的,所以第一次接受输入时取走字符后会留下字符 ,这样第二次的读入函数直接从缓冲区中把 取走了。

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

     1 //scanf()读取字符串 空格问题
     2 void Sub_2_1()
     3 {
     4     char str1[20], str2[20];
     5     scanf("%s",str1);
     6     printf("%s
    ",str1);
     7     scanf("%s",str2);
     8     printf("%s
    ",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[20], str2[20];
    31     gets(str1);
    32     printf("%s
    ",str1);
    33     gets(str2);
    34     printf("%s
    ",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 /*****/
     22     //scanf gets
     23 //    Sub_2_1();
     24     //Sub_2_2();
     25 }
     26 
     27 //setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区  
     28 
     29 //scanf读取字符 回车问题
     30 void Sub_1_1()
     31 {
     32     char v1,v2;
     33     
     34     scanf("%c", &v1);
     35     //setbuf(stdin, NULL); //解决回车问题
     36     scanf("%c", &v2);
     37     //setbuf(stdin, NULL); //解决回车问题
     38     printf("%d %d
    ", v1, v2);
     39 
     40     //回车问题
     41 }
     42 
     43 /* scanf()和getchar()函数是从输入流缓冲区中读取值的,
     44     而并非从键盘(也就是终端)缓冲区读取。
     45     而读取时遇到回车(
    )而结束的,这个
    会一起读入输入流缓冲区的,
     46     所以第一次接受输入时取走字符后会留下字符
    ,
     47     这样第二次的读入函数直接从缓冲区中把
    取走了,显然读取成功了,
     48     所以不会再从终端读取! */
     49 
     50 //getchar读取字符 回车问题
     51 void Sub_1_2()
     52 {
     53     char ch1, ch2;
     54     //setbuf(stdin, NULL); //解决回车问题
     55     ch1 = getchar();
     56     //setbuf(stdin, NULL); //解决回车问题
     57     ch2 = getchar();
     58     printf("%d %d
    ", ch1, ch2);
     59 
     60     //回车问题
     61 }
     62 
     63 //cin读取单字符 无回车问题
     64 void Sub_1_3()
     65 {
     66     char ch1, ch2;
     67     cin >> ch1;
     68     cin >> ch2;
     69 
     70     cout << ch1 << endl;
     71     cout << ch2 << endl;
     72 
     73 }
     74 
     75 //scanf()读取字符串 空格问题
     76 void Sub_2_1()
     77 {
     78     char str1[20], str2[20];
     79     scanf("%s",str1);
     80     printf("%s
    ",str1);
     81     scanf("%s",str2);
     82     printf("%s
    ",str2);
     83 
     84     //空格问题 
     85 
     86     //hello world -> 
     87     //hello
     88     //world
     89     /*第一次输入Hello world!后,
     90     字符串Hello world!都会被读到输入缓冲区中,
     91     而scanf()函数取数据是遇到回车、空格、TAB就会停止,
     92     也就是第一个scanf()会取出"Hello",而"world!"还在缓冲区中,
     93     这样第二个scanf会直接取出这些数据,而不会等待从终端输入。*/
     94 
     95     //scanf()读取字符串会舍弃最后的回车符!
     96     //hello -> 
     97     //hello -> 
     98 
     99 }
    100 
    101 //gets()读取字符串 接受空格
    102 void Sub_2_2()
    103 {
    104     char str1[20], str2[20];
    105     gets(str1);
    106     printf("%s
    ",str1);
    107     gets(str2);
    108     printf("%s
    ",str2);
    109 
    110 }
    111 
    112 
    113 //总结
    114 /*
    115 读取字符时:
    116 scanf()以Space、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中);
    117 getchar()以Enter结束输入,也不会舍弃最后的回车符;
    118 读取字符串时:
    119 scanf()以Space、Enter、Tab结束一次输入
    120 gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
    121 第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
    122 方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
    123 这个函数是fflush(stdin)//似乎并没有用。
    124 //setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区 
    125 方法2:自己取出缓冲区里的残留数据。
    126 */
  • 相关阅读:
    oracl (一)数据类型
    orcl (二)函数
    数据库锁机制
    Jquery逐行读取txt 文件
    PowerShell导出场中的WSP包到本地
    如何安装Magento 2.0
    WindowsServer2012 R2 64位中文标准版(IIS8.5)下手动搭建PHP环境详细图文教程(二)安装IIS8.5
    WindowsServer2012 R2 64位中文标准版(IIS8.5)下手动搭建PHP环境详细图文教程(一)
    IQueryable 和 IEnumerable
    asp.net读取CSV
  • 原文地址:https://www.cnblogs.com/1228073191Blog/p/7696324.html
Copyright © 2011-2022 走看看