cin.getline对cin.gcount()的影响

cin.getline对cin.gcount()的影响 - delphiwcdj的专栏 - 博客频道 - CSDN.NET

cin.getline对cin.gcount()的影响

分类: C/C++ 195人阅读 评论(0) 收藏 举报

2011-05-08 wcdj

 

问题

测试下面代码,解释cin.gcount的输出为什么会不同?

 

  1. #include<iostream>  
  2. using namespace std;  
  3. int main()  
  4. {  
  5.     // case 1:  
  6.     char a[10];  
  7.     cin.getline(a,10);              // 123456789  
  8.     cout << a << endl;          // 123456789  
  9.     cout << cin.gcount();     // Note, 10  
  10.     cout << endl;  
  11.     // case 2:  
  12.     char b[10];  
  13.     cin.getline(b,10);              // 1234567890  
  14.     cout << b << endl;          // 123456789  
  15.     cout << cin.gcount();     // Note, 9  
  16.     return 0;  
  17. }  
#include<iostream> using namespace std; int main() { // case 1: char a[10]; cin.getline(a,10); // 123456789 cout << a << endl; // 123456789 cout << cin.gcount(); // Note, 10 cout << endl; // case 2: char b[10]; cin.getline(b,10); // 1234567890 cout << b << endl; // 123456789 cout << cin.gcount(); // Note, 9 return 0; }

 

 

分析

getline()是按行读入字符串,后面可以指定2个参数或3个参数,其在istream中的实现如下:

[cpp:nogutter] view plain copy print ?
  1. _Myt& __CLR_OR_THIS_CALL getline(_Elem *_Str, streamsize _Count)  
  2. {   // get up to _Count characters into NTCS, discard newline  
  3.     return (getline(_Str, _Count, _Myios::widen('/n')));  
  4. }  
_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()函数。
同时当我们单步进入getline()的实现我们会发现这样的判断语句:

[cpp:nogutter] view plain copy print ?
  1. _Myt& __CLR_OR_THIS_CALL getline(_Elem *_Str,  
  2.                                  streamsize _Count, _Elem _Delim)  
  3. {   // get up to _Count characters into NTCS, discard _Delim  
  4.     _DEBUG_POINTER(_Str);  
  5.     ios_base::iostate _State = ios_base::goodbit;  
  6.     _Chcount = 0;  
  7.     const sentry _Ok(*thistrue);  
  8.     if (_Ok && 0 < _Count)  
  9.     {   // state okay, use facet to extract  
  10.         int_type _Metadelim = _Traits::to_int_type(_Delim);  
  11.         _TRY_IO_BEGIN  
  12.             int_type _Meta = _Myios::rdbuf()->sgetc();// 从输入流读一个字符  
  13.         for (; ; _Meta = _Myios::rdbuf()->snextc())  
  14.             if (_Traits::eq_int_type(_Traits::eof(), _Meta))  
  15.             {   // end of file, quit  
  16.                 _State |= ios_base::eofbit;// 遇到文件尾,getline结束  
  17.                 break;  
  18.             }  
  19.             else if (_Meta == _Metadelim)  
  20.             {   // got a delimiter, discard it and quit  
  21.                 ++_Chcount;  
  22.                 _Myios::rdbuf()->sbumpc();// 这句把结束符读掉了,如果不指定结束符,那就是把'/n'读掉了  
  23.                 break;  
  24.             }// 遇到结束符,getline结束,注意这里的顺序,它是先判断是否遇到结束符,后判断是否读入了指定个数的。在这里计数器仍然执行++操作  
  25.             else if (--_Count <= 0)  
  26.             {   // buffer full, quit  
  27.                 _State |= ios_base::failbit;  
  28.                 break;  
  29.             }// 读到了指定个数,执行到这里已经隐含了在指定个数的最后一位仍然不是结束符,由于在执行这部分时,在对长度计数器没有进行++操作  
  30.             else  
  31.             {   // got a character, add it to string  
  32.                 ++_Chcount;  
  33.                 *_Str++ = _Traits::to_char_type(_Meta);  
  34.             }  
  35.             _CATCH_IO_END  
  36.     }  
  37.     *_Str = _Elem();    // add terminating null character  
  38.     _Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);  
  39.     return (*this);  
  40. }  
_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); }

 

所以在对于输入 12345789 时,在最后我们输入了 '/n',因此在判断时,计数器仍然加1,而相对当我们输入 1234567890 时,在判断 a[9] 时,由于--_Count <= 0,所以计数器没有被递加,因此在产生了区别。

 

结论:
通过对getline的分析,可以找到输出结果不同的原因。

 


 

PS:

 

MSDN:

basic_istream::gcount
Returns the number of characters read during the last unformatted input.

[cpp:nogutter] view plain copy print ?
  1. streamsize gcount( ) const;  
streamsize gcount( ) const;

Return Value
The extraction count.
Remarks
Use basic_istream::get to read unformatted characters.
Example
  1. // basic_istream_gcount.cpp  
  2. // compile with: /EHsc  
  3. #include <iostream>  
  4. using namespace std;  
  5. int main( )   
  6. {  
  7.     cout << "Type the letter 'a': ";  
  8.     ws( cin );  
  9.     char c[10];  
  10.     cin.get( &c[0],9 );// a  
  11.     cout << c << endl;// a  
  12.     cout << cin.gcount( ) << endl;// 1  注意,这里为什么是1,分析方法同getline,可以在get的实现中找的具体的原因  
  13. }   
// basic_istream_gcount.cpp // compile with: /EHsc #include <iostream> using namespace std; int main( ) { cout << "Type the letter 'a': "; ws( cin ); char c[10]; cin.get( &c[0],9 );// a cout << c << endl;// a cout << cin.gcount( ) << endl;// 1 注意,这里为什么是1,分析方法同getline,可以在get的实现中找的具体的原因 } 
Requirements
Header: <istream>
Namespace: std

 


参考

istream::getline
http://www.cplusplus.com/reference/iostream/istream/getline/
istream::get
http://www.cplusplus.com/reference/iostream/istream/get/
basic_istream::gcount
http://www.cplusplus.com/reference/iostream/istream/gcount/
http://msdn.microsoft.com/zh-cn/library/3w9exa29%28v=VS.90%29.aspx
cin.getline()
http://blog.csdn.net/kof2001kop/archive/2011/04/03/6299778.aspx
http://social.msdn.microsoft.com/Forums/zh-CN/visualcpluszhchs/thread/bacc495d-1170-4a20-90b6-80a37ba3d5b5

 

posted on 2013-01-22 13:22  lexus 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lexus/archive/2013/01/22/2871216.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值