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的長度,因為至少要留一個位置存放結束符'\0',后面這個還要探討一下)

以后可以參考的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();  
            /*注:上面這句把結束符讀掉了,如果不指定結束符,那就是把'\n'讀掉了
 
。  
            但回車符本身並沒有拷貝到緩沖區中, 
            這樣下次的讀操作將從回車符后面的第一個字符開始, 
            */  
            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 /*注:前面這句為字符串加入了終止符'\0' 
    因為_Elem()構造了一個ascii碼為0的字符對象*/  
    _Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);  
    /*注:如果沒有讀入任何字符,要保持執行這一次getline之前的輸入流狀態, 
    否則根據這一次getline執行的情況,設置輸入流為相應狀態。 */  
    return (*this);   //返回輸入流對象本身  
}   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM