c++ getline(),get()函数笔记
2016-05-04 15:30
751 查看
写这篇blog的起因在于:
function getline()在不指定休止符时,默认以换行作为休止符。
由于我的认识上的不足,一度认为
function cin.getline()的使用中将调用改函数之前的一个回车也进行了读取,导致数据转变的时候出错
可见于/article/10184135.html
的Row95和Row98。
后在vs2010中也做了如下的测试,发现直接输入回车后进行了换行输出。
在调用std下的function getline()时也发生了同样的情况
解决方案:直接在getline()之前进行了调用了get(),将多余的回车吃掉。
分析部分:
istream中function getline()的实现:
这里是两个参数的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时,实际上是函数为我们添加了第三个参数。
接下来调用了如下的函数:
从实现当中我们可以看到,我之前的调用的确被正确执行了,当我直接输入回车时,getline()函数被调用,但有与第一个字符就是休止符,通过调用sbumpc()将指针指向了下一个字符后跳出循环,此时_Str当中什么都没有被存入,我们通过调用
将_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的机制,会事先申请一个固定大小的空间,当空间不足时会重新申请一块更大的空间,将原来的数据复制进新的空间。
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遇到休止符就停止了,输入流队列当中仍然保留有休止符。
function getline()在不指定休止符时,默认以换行作为休止符。
由于我的认识上的不足,一度认为
function cin.getline()的使用中将调用改函数之前的一个回车也进行了读取,导致数据转变的时候出错
可见于/article/10184135.html
的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遇到休止符就停止了,输入流队列当中仍然保留有休止符。
相关文章推荐
- c++ 子类调用父类构造方法 调用父类方法 类声明与实现分离
- C++中的引用和指针
- C语言(链表)
- 整数大数模拟 高精度加法 高精度减法 高精度乘法 高精度除法 c/c++ java
- c++ 八大排序算法
- c语言libcurl库的异步用法
- C语言(算法)
- C语言6(指针)
- C语言中指针变量使用时常见的几个问题
- 【C++】高精度代码运行时间( QueryPerformanceCounter )
- c++ 数据类型整理
- c++中的引用和拷贝构造函数
- C++ placement new与内存池
- C语言5(函数)
- C语言的编译链接过程详解
- 深入理解c语言——'\0','0',"0" ,0之间的区别
- 带你玩转Visual Studio——命令行编译C/C++程序
- C++ 之const关键字
- C语言4(数组)
- (C++)UrlEncode的标准实现