zoukankan      html  css  js  c++  java
  • c++ 输入与缓冲区

    背景

    对于程序而言,从键盘键入至程序读入,期间会将内容暂存在一个缓冲区中。代码的输入语句会直接从缓冲区中读取内容,所以有时候出现奇奇怪怪的意想不到的状况的时候,就是因为缓冲区也许留存有上一次的残留数据,导致被“错误读入”。
    而且有些函数是对空格,回车不感冒,如cin,而有些却能够读取回车符如cin.get。下面就争对这些情况做个实验:

    cin

    cin 读取程序代码后面的对应的变量类型
    结束标志:空格或者回车

    cin 在读入之前, 会主动清空缓冲区中残余的空格或者回车.

    // 输入:【enter1】【2】【空格】【空格】【c】【enter2】
    int main() {
    	int a;
    	char b;
    	cin >> a >> b;  // enter2 被留在缓冲区
    	cout << a << b;
    }
    
    // 输出:
    2 c
    

    https://en.cppreference.com/w/cpp/io/cin

    cin.getline()

    先看一下函数定义:

    getline 函数从一个输入流(input stream)读入字符,并append至 string

    函数不断读入字符并 append 至 string,其结束条件为:

    a) 输入流读到了一个文件的末尾。getline 设置 eofbit
    b) 下一个读入的字符为 delim, 这种情况下读入 delim 之后就停止读入,且 delim 不会 append 至 string
    c) string 长度已经到了 max_size

    构造函数显示,getline 函数 传入的 input_stream 的引用。所以,返回传入的流引用本身

    template< class CharT, class Traits, class Allocator >
    std::basic_istream<CharT,Traits>& getline( std::basic_istream<CharT,Traits>&& input,
                                              std::basic_string<CharT,Traits,Allocator>& str );
    
    template< class CharT, class Traits, class Allocator >
    std::basic_istream<CharT,Traits>& getline( std::basic_istream<CharT,Traits>&& input,
                                               std::basic_string<CharT,Traits,Allocator>& str,
                                               CharT delim );
    

    第一种用法就是 getline(input_stream, str) —— 此用法则默认 delim 是换行符
    第二种是getline(input_stream, str, delim) —— 不断读入,除非遇到(a、b、c)情况

    getline 函数不会主动清空缓冲区,即会读入 enter 空格。所以会出现读入“异常”的情况
    比如:

    // 测试输入1:【enter1】【5】【enter2】【7777】
    int main()
    {
    	int a;
    	cin >> a;
    	
    	string str;
    	getline(cin, str);
    	cout << str;  // 测试1:没有正确读入我们想要的 7777
    }
    
    // 输出1:
    【enter】
    

    原因就是输入的【enter2】残留在了输入缓冲区,而且默认delim是换行符
    【enter2】被 getline 读入,结束输入

    // 测试输入2: 【enter1】【5】【空格4444】【enter2】
    // 输出2:
    【空格4444】
    

    【空格】不会被geline主动清空,所以依旧读入

    // 测试3:【enter1】【5】【空格】【aaa】【enter2】【123x】
    int main()
    {
    	int a;
    	cin >> a;
    	
    	string str;
    	getline(cin, str, 'x');
    	cout << str;  // 测试1:没有正确读入我们想要的 7777
    }
    
    // 输出3
    【空格aaa】【enter】【123】
    

    我们主动添加了 delim='x' ,所以可继续读入 enter

    解决getline的误读: cin>>std::ws

    int a;
    cin >> a;
    	
    string str;
    
    cin >> std::ws;  // 解决残留的空格换行符
    getline(cin, str);
    	
    cout << str;
    

    如 cppreference 建议的,添加上 cin>>std::ws 即可

    https://en.cppreference.com/w/cpp/string/basic_string/getline
    http://www.augustcouncil.com/~tgibson/tutorial/iotips.html
    http://www.augustcouncil.com/~tgibson/tutorial/UnderstandingComplexExpressions.pdf

  • 相关阅读:
    学指令 emacs篇
    c 排序 总结
    C# WinForm源码下载
    PetShop下载
    Visual Studio常用技巧
    人事信息管理系统(PMS)
    css实现细表格原理
    GridView导出Excel/Word
    dotnet程序员装机必备工具
    容器练习一
  • 原文地址:https://www.cnblogs.com/KongHuZi/p/13708639.html
Copyright © 2011-2022 走看看