getline 细节

from: http://zhidao.baidu.com/link?url=J1er202u3NAx1A_wlx1Tym4Px-nCPqQq37D7w2v-uYFztCexSf7_JPsS7FvXnNaSFk9SHyVQ9sJlmGCM1971i_


getline后面可以指定2个参数或3个参数,
2个参数时,第2个参数就是读取的位数,
3个参数时,第3个参数是终止符,只要2个参数中有一个满足了,就停止读入,
如楼上方式,将会是读5个字符或者遇到'\n'停止

—————————————————

哎,今天用到getline,仔细研究一番才发现楼主这问题问的这么深刻,来看一下getline的实现吧,共同学习之~~

以下为getline函数的实现,在头文件istream中。
下面具体分析一下,太深奥的分析不了,只简述一下,已经足够用了:

_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实际也是调用了以'\n'为结束符的三参数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是否执行,也就是是否读输入流,整个函数流程太多了,也没看十分明白,但可以肯定的是,当输入流的状态是正常时,该函数的返回值也是true,反之,则返回false。
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;
break;
}//注:遇到文件尾,getline结束
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;
}//注:读到了指定个数,执行到这里已经隐含了在指定个数的最后一位仍然不是结束符,因此该部分将输入流状态置为了错误。这直接导致了接下来的getline(或者get/>>等等都是不能正确执行的)
else
{// got a character, add it to string
++_Chcount;
*_Str++ = _Traits::to_char_type(_Meta);
}//注:正常读取一个字符
_CATCH_IO_END
}
*_Str = _Elem();// add terminating null character
//注:前面这句为字符串加入了终止符'\0'
_Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);//注:如果没有读入任何字符,要保持执行这一次getline之前的输入流状态,否则根据这一次getline执行的情况,设置输入流为相应状态。
return (*this);
}

分析完这些就很容易理解楼主所说的情况了:
(1)输入abcd"回车",getline(s,5)遇到换行符结束,输入流状态仍然正确。
(2)输入abcd"空格""回车",getline(s,5)在第5位遇到了空格,因已读满字符串而结束,输入流状态变为了错误,此后的getline(s2,4)是无法读输入流的。但如果在执行getline(s,5)后加一句cin.clear();将输入流状态重新设置为正常,之后再执行getline(s2,4)你就会发现此时是可以继续从输入流读数据的了。

至于你说换行符被s2接收?那是因为你输出完s之后又endl的现象吧,看结果是换了一行,实际s2里是什么都没有。

楼主有兴趣的话可以单步跟踪调试去看一下getline的执行过程的,还是很有意思的~~

你可能感兴趣的:(study,notes,C++)