c++ getline(),get()函数笔记

写这篇blog的起因在于:
function getline()在不指定休止符时,默认以换行作为休止符。
由于我的认识上的不足,一度认为
function cin.getline()的使用中将调用改函数之前的一个回车也进行了读取,导致数据转变的时候出错
可见于http://blog.csdn.net/qq_30490125/article/details/51308877
的Row95和Row98。
后在vs2010中也做了如下的测试,发现直接输入回车后进行了换行输出。

    char a[100];
    memset(a,0,sizeof(a));
    cin.getline(a,100);
    cout<<"start"<<endl;
    cout<<a<<endl;
    cout<<"end"<<endl;

在调用std下的function getline()时也发生了同样的情况

    string a;
    getline(cin,a);
    cout<<"start"<<endl;
    cout<<a<<endl;
    cout<<"end"<<endl;

解决方案:直接在getline()之前进行了调用了get(),将多余的回车吃掉。


分析部分:
istream中function getline()的实现:

_Myt& __CLR_OR_THIS_CALL getline(_Elem *_Str, streamsize _Count)  
{   // get up to _Count characters into NTCS, discard newline  
    return (getline(_Str, _Count, _Myios::widen('/n')));  
}  

这里是两个参数的getline()的入口。


std::istream::getline
原型:
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );
detail:http://www.cplusplus.com/reference/istream/istream/getline/


可以看到,在调用两个参数的getline时,实际上是函数为我们添加了第三个参数。
接下来调用了如下的函数:

_Myt& __CLR_OR_THIS_CALL 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 (_Ok && 0 < _Count)  
    {   // state okay, use facet to extract  
        int_type _Metadelim = _Traits::to_int_type(_Delim);  
        _TRY_IO_BEGIN  
            int_type _Meta = _Myios::rdbuf()->sgetc();// 从输入流读一个字符  
        for (; ; _Meta = _Myios::rdbuf()->snextc())  
            if (_Traits::eq_int_type(_Traits::eof(), _Meta))  
            {   // end of file, quit  
                _State |= ios_base::eofbit;// 遇到文件尾,getline结束  
                break;  
            }  
            else if (_Meta == _Metadelim)  //休止符的判断
            {   // got a delimiter, discard it and quit  
                ++_Chcount;  
                _Myios::rdbuf()->sbumpc();// 这句把结束符读掉了,如果不指定结束符,那就是把'/n'读掉了  
                break;  
            }// 遇到结束符,getline结束,注意这里的顺序,它是先判断是否遇到结束符,后判断是否读入了指定个数的。在这里计数器仍然执行++操作  
            else if (--_Count <= 0)  
            {   // buffer full, quit  
                _State |= ios_base::failbit;  
                break;  
            }// 读到了指定个数,执行到这里已经隐含了在指定个数的最后一位仍然不是结束符,由于在执行这部分时,在对长度计数器没有进行++操作  
            else  
            {   // got a character, add it to string  
                ++_Chcount;  
                *_Str++ = _Traits::to_char_type(_Meta);  
            }  
            _CATCH_IO_END  
    }  
    *_Str = _Elem();    // add terminating null character  
    _Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);  
    return (*this);  
}  

从实现当中我们可以看到,我之前的调用的确被正确执行了,当我直接输入回车时,getline()函数被调用,但有与第一个字符就是休止符,通过调用sbumpc()将指针指向了下一个字符后跳出循环,此时_Str当中什么都没有被存入,我们通过调用

  *_Str = _Elem();    // add terminating null character  

将_Str首位置为空字符’\0’。
接下来对_Str进行了输出,输出为空。


std::getline (string)
原型:
(1)
istream& getline (istream& is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
(2)
istream& getline (istream& is, string& str);
istream& getline (istream&& is, string& str);


detail:http://www.cplusplus.com/reference/string/string/getline/
从输入流冲获取获取数据直到遇到delim休止符或文件结束符,将获得的数据放入到str当中,
关于读取到休止符的处理可以参考之前的_Myt& __CLR_OR_THIS_CALL getline()。
我们知道c++的string有类似vector的机制,会事先申请一个固定大小的空间,当空间不足时会重新申请一块更大的空间,将原来的数据复制进新的空间。

    string a="fyb";
    string b;
    b=a;
    a.push_back('b');
    cout<<a<<endl;
    cout<<&a<<endl;
    cout<<b<<endl;
    cout<<&b<<endl;

std::getline()实质就是每次将一个字符添加string的末尾,所以中间可能会存在内存空间的申请,和string数据的复制。


std::istream::get
原型:
single character (1)
int get();
istream& get (char& c);

c-string (2)
istream& get (char* s, streamsize n);
istream& get (char* s, streamsize n, char delim);

stream buffer (3)
istream& get (streambuf& sb);
istream& get (streambuf& sb, char delim);


detail:http://www.cplusplus.com/reference/istream/istream/get/
单字符的get可以进行逐字符地读入,类似getchar();
这里我们主要说的还是第二类,这里的应用跟getline及其类似,但get有一点需要注意,getline会将休止符一起读入后舍弃,但get遇到休止符就停止了,输入流队列当中仍然保留有休止符。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值