zoukankan      html  css  js  c++  java
  • getline函数彻底说明

    因为之前每次使用这个函数都要在网上查一遍,觉得很麻烦,这次就认真地整理一下,希望写完之后就记住。

    getline函数其实有两个:

      一个是全局函数,include<cstring>, 原型是 istream& getline( istream& is, string& str, char delim) 与 istream& getline( istream& is, string& str) , 得到的字符串存在一个string类型的str里。

      另一个是iostream类的成员函数, include<iostream>, 原型是 istream& getline( char * str, streamsize n, char delim ) 与 istream& getline( char * str, streamsize n ) , 得到的字符串存在一个C-style字符数组str里。(值得注意的是,这个n应该小于字符数组str的长度,因为至少要留一个位置存放结束符'',后面这个还要探讨一下)

    以后可以参考的cin.getline源码:

    _Myt& getline(_Elem *_Str, streamsize _Count, _Elem _Delim)   
    {// get up to _Count characters into NTCS, discard _Delim   
        _DEBUG_POINTER(_Str);    //判断传入指针的合法性  
        ios_base::iostate _State = ios_base::goodbit;    
        _Chcount = 0; //从输入流中读取的字符数  
        const sentry _Ok(*this, true);  
        /*注:上面这句很关键,它关系到下面的if是否执行,也就是是否读输入流。这句从
     
    语法上看,是 
        sentry是一个class, _Ok是sentry类的一个const对象,构造这个对象时需要传入两个
     
    参数 
        第一个是流对象自身的引用,第二个表示对空白字符(如空格、制表符)的处理方式
     
    ,为true时意味着不忽略空白字符,即一个字符一个字符的从输入流中提取。 
        */  
          
        if (_Ok && 0 < _Count)   
        /* 
     
    ************************************************************************** 
        * sentry类内部重载了一个类型转换运算符,它把sentry类的实例转换成了一个bool
     
    表达式。 
        * 这个表达式返回sentry类的私有成员_Ok的值。 
        bool sentry::operator bool() const 
        * { // test if _Ipfx succeeded 
        *       return (_Ok); 
        *   } 
        * _Ok这个成员的值由sentry类的构造函数 
        * 在初始化时设置,设置的过程比较麻烦,这里不做赘述(其实我也没看十分明白)。 
        * 但可以肯定的是,当输入流的状态是正常时,这个成员的值也是true, 
        * 反之,则是false。  
        *  
        * _Count是调用者传入的第二个参数,这里用做循环计数器的初值,以后每读一个字
     
    符, 
        * _Count的值会减一。 
        
     
    ****************************************************************************
     
    **/  
        {  
        // state okay, use facet to extract   
        int_type _Metadelim = _Traits::to_int_type(_Delim);   
        int_type _Meta = _Myios::rdbuf()->sgetc();//从输入流读一个字符   
        for (; ; _Meta = _Myios::rdbuf()->snextc()) //snextc()从输入流中读取下一
     
    个字符  
            if (_Traits::eq_int_type(_Traits::eof(), _Meta))   
                  {// end of file, quit   
                    _State |= ios_base::eofbit;   
                    break;   
                   }//注:遇到文件尾,getline结束   
            else if (_Meta == _Metadelim) {  
                 // got a delimiter, discard it and quit   
                ++_Chcount;    //读取字符数+1  
                _Myios::rdbuf()->sbumpc();  
                /*注:上面这句把结束符读掉了,如果不指定结束符,那就是把' '读掉了
     
    。  
                但回车符本身并没有拷贝到缓冲区中, 
                这样下次的读操作将从回车符后面的第一个字符开始, 
                */  
                break;   
            }/* 注:遇到结束符,getline结束,注意这里的顺序,它是先判断是否遇到结束
     
    符,后判断是否读入了指定个数的。 */  
            else if (--_Count <= 0)   
            {// buffer full, quit   
                _State |= ios_base::failbit;   
                break;   
            }  
            //注:读到了指定个数,执行到这里已经隐含了在指定个数的最后一位仍然不是
     
    结束符,  
            //因此该部分将输入流状态置为了错误。  
            //这直接导致了接下来的getline(或者get)以及>>运算符等读操作都不能正确执
     
    行)   
            else {  
                // got a character, add it to string   
                ++_Chcount;  //读取字符数加1  
                *_Str++ = _Traits::to_char_type(_Meta);   
            }//注:这一分支将读取到的单个字符拷贝到缓冲区中  
        }   
        *_Str = _Elem();  //  
        /* add terminating null character /*注:前面这句为字符串加入了终止符'' 
        因为_Elem()构造了一个ascii码为0的字符对象*/  
        _Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);  
        /*注:如果没有读入任何字符,要保持执行这一次getline之前的输入流状态, 
        否则根据这一次getline执行的情况,设置输入流为相应状态。 */  
        return (*this);   //返回输入流对象本身  
    }   
  • 相关阅读:
    生成器
    迭代器
    闭包函数
    装饰器(2)
    装饰器(1)
    名称空间与作用域(2)
    110.网络编程-mail
    109.网络编程-FTP
    108.网络编程-TCP/UDP
    107.xpath
  • 原文地址:https://www.cnblogs.com/Luxuer/p/5938479.html
Copyright © 2011-2022 走看看