C++中get()与getline()的区别

cin.get()与cin.getline()区别在于前者对于终止符(terminator)“不抛弃,不放弃”,后者舍弃。string.h中的getline(istream,string)与cin.getline(string,streamsize)类似,但输入字符串后,回车在VC6下可能要按两次,Dev C++下不会。

cin.get()参数有四种,从0个到3个,其中Ch为模板类型参数:
int_type get(); //获得一个字符,可为eof与terminator
istream& get(Ch& p); //获得一个字符给p,可为terminator,不可为eof
istream& get(Ch *p,streamsize n); //定义最大输入,默认terminator为’\n’
istream& get(Ch *p,streamsize n,Ch term); //重定义terminator,不再为’\n’

cin.getline()参数有两种,从2个到3个:
istream& getline(Ch *p,streamsize n);
istream& getline(Ch *p,streamsize n,Ch term);


一,现在先来测试get()的第一个用法
int_type get(); //获得一个字符,可为eof与terminator

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff = 'n';

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a char : ";
    buff = cin.get();
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a char : ";
    buff = cin.get();
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a char : ";
    buff = cin.get();
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到,我们输入了a,第一次输出的是a,但是第二次并没有直接让我们输入,因为第一次输入的时候stdin缓冲区内保存着a\n,第一次使用cin.get()读取了a,然后第二次的时候,因为缓冲区还有\n,所以直接就读取了\n,没有让用户输入,第三次又能正常输入了
这里写图片描述
然后我们再测试一下当输入两个字符时的情况
从上图可以看出,我第一次输入了aa,之后就没有让我再输入了,原理同上,第一次输入aa,按了回车之后缓冲区保存着aa\n,cin.get()每次读取一个字符,所以第一次输出a,第二次输出a,第三次输出\n


二,我们现在测试cin.get()的第二种用法
istream& get(Ch& p); //获得一个字符给p,可为terminator,不可为eof

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff = 'n';

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a char : ";
    cin.get(buff);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a char : ";
    cin.get(buff);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a char : ";
    cin.get(buff);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
测试结果跟一一样


三,现在测试cin.get()的第三个用法
istream& get(Ch *p,streamsize n); //定义最大输入,默认terminator为’\n’

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到在输入少于函数设定的参数3时,第二和第三次程序没有让我输入,第一次显示bc,之后的buff内容都是空值,而输入大于3时,第二次和第三次程序照样没让我输入,但是第二次和第三次显示了第一次输入没显示完的内容。
原因:
第一次输入bc的时候缓冲区的内容是bc\n,而程序需要读取三个字符,除去字符串最后的\0,从缓冲区内读取了bc,\n依然留在缓冲区,第二次cin.get()时,程序发现缓冲区有内容\n,而\n作为结束标志,于是程序认为输入了空值,把buff内容设为空值,第三次也一样,所以第二第三次显示的是空值,同时,没有让用户输入。
第二次输入abcdef时,缓冲区的内容时abcdef\n,第一次读取了ab,所以输出ab,此时缓冲区内容为cdef\n,所以第二次没有让用户输入,直接读取了缓冲区内的cd,第三次同理读取缓冲区内的ef

当cin.get()设定的参数要读取的字符数比申请的内存多的时候会怎样呢?
我们继续测试,cin.get(buff,6)

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
第一次测试输入跟上面一样,输出也一样。第二次测试输入了abcdefg,可以看到第一次显示buff为abcdef,说明程序按照cin.get()设定的参数7从缓冲区读取数据了,原理是一样的,唯一要注意的是。buff溢出了


四,现在测试cin.get()的第四个用法
istream& get(Ch *p,streamsize n,Ch term); //重定义terminator,不再为’\n’

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3,'s');
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到如果输入后面加个s,当cin.get()参数为3时结果与第三种用法的结果一样

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7,'s');
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到当cin.get()参数为7的时候结果也和第三个用法一样,说明s成功替换了’\n’的作用,但是在使用这种方法的时候注意’\n’将会被当成正常字符对待
如下图的测试(cin.get()的参数采用3)
这里写图片描述
由上图可以看到第一次输入的时候我只输入了b就按了回车,当输入没有达到规定的参数(3个),又没有遇到结束符,所以程序让我继续输入,我输入了c之后,此时缓冲区的内容是b\nc\n,所以结束后第一次输出是b\n,第二次输入的时候,缓冲区只有两个字符,于是让我输入,我输入了d,回车之后缓冲区的内容是c\nd\n,所以第二次输出是c\n,同理第三次输出是d\n


五,cin.getline()的第一种用法
istream& getline(Ch *p,streamsize n);

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到在第一次输入bc后,cin.getline()会将缓冲区里的\n丢弃,而且,只要输入的数量低于cin.getline()的参数(这里是3),也不会让我重新输入,但是在输入超过cin.getline()的第二个参数时,便会出现异常,导致后面的cin.getline()接受的输入都变成空,具体解决办法在后面。
然后我们继续测试cin.getline()是否会溢出(将参数设为7)

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,7);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,7);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,7);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到,buff【5】同样可以输出留个字符,产生溢出,跟上面一样,输入超了之后就会产生异常,让后面的cin.getline()接受的输入为空值


六,cin.getline()第二种用法
istream& getline(Ch *p,streamsize n,Ch term);

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
这里写图片描述
可以看到第一次输入的时候,产生异常了,那是因为现在的\n也会被当做正常的字符被读取,(\n占两个字符),溢出了,第二次测试的时候只输入了一个字母b,但是输入却检测到才一个字符,不够,所以让我继续输入,之后缓冲区的内容是b\nc\n,cin.getline()读取的时候发现溢出了,所以抛出异常,让后面的cin.getline()的输入为空。而当我们在bc后面加上s后,cin.getline()读取的时候遇到s结束,只接受了bc,此时缓冲区的内容是\n,第二次输入的时候,输入了des\n.所以缓冲区的内容是\ndes\n,所以此时输出\nd,但是输入的内容超出了第二个参数,抛出异常,导致后面的输入为空。


七,总结问题
1.cin.getline(),在换了结束符后,输入的数据多于给定的第二个参数时都会抛出异常,导致后面的输入为空
2.cin.get()不会清除缓冲区的结束符,而cin.getline()则会清除缓冲区的结束符
3.程序中,cin.get()和cin.getline()接受的输入都可能超出定义的数组的大小,所以在接受多个字符的输入时最好加上第二个参数,且保证第二个参数大于数组大小(不然还不是会溢出,接受的输入超出定义的大小)
4.怎么清空缓冲区,避免上述问题的产生
i)针对cin.get()不清空缓冲区由于回车符产生的\n,可以用一次cin.get()读取\n

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3).get();
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3).get();
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3).get();
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到用了cin.get().get()之后成功清除了缓冲区的\n

ii)使用ignore()函数
cin.clear()是将错误状态更改为有效状态
cin.ignore()是忽略缓冲区中指定个数的字符
以下代码用于输出failbit、eofbit、badbit、goodbit几个标志当前的状态,1表示可用,0表示错误状态

cout<<"cin.fail():"<<cin.fail()<<endl;  
cout<<"cin.eof():"<<cin.eof()<<endl;  
cout<<"cin.bad():"<<cin.bad()<<endl;  
cout<<"cin.good:"<<cin.good()<<endl;  
#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到,没有出现异常,\n被正常清除
接下来再试一试是否可以清除

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

这里写图片描述
可以看到第一次输入bc的时候faildbit位出错了,但是被clear()函数清空了,所以第二次的输入正常,但是第二次输入bc时,因为没有清除failbit位的出错信息,所以导致第三次的输入位空。

以上,全部由本人上网查找资料,并做实验,结合自己的理解写成,如有遗漏之处欢迎指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值