C++中 cin、cin.get()、cin.getline()、getline() 的区别

cin

我们先介绍c++中最常用的输入流对象cin

我们常用 cin >> num 来从缓冲区中读取数据到 num 中,num 的变量类型可以是多种类型,最常用的有 intstringchardoublefloat等等

void cin_test()
{
    std::cout<<"----------- cin test ---------"<<std::endl;
    std::string str;
    //fff ggg
    //fff   ggg
    std::cin>>str;
    std::cout<<str<<std::endl;

}

 在上述示例中,输入流的过程是这样的

  • 在键盘输入一个字符串“fff”,按下回车键
  • 字符串“fff”被存储到缓冲区中
  • cin读取缓冲区中的内容,并将内容存放到内存变量str中
  • 标准输出流cout将内存变量str的值进行输出

在上述过程里有两个步骤需要关注,分别是第二步和第三步

在第二步中,字符串“fff”被存储到缓冲区中,存储的内容其实是“fff”和一个换行符,因为我们在键盘输入字符串的最后按下的回车键

而在第三步中,cin读取缓冲区中的内容的时候,读取的是第一个非空白字符开始到第一个结束符之间的字符串,而这个结束符可以是空格,也开始是制表符,也可以是换行符。除此以外,空格、制表符、换行符是内置的 cin 的结束符,如果想用其他的字符来提前结束读取数据,需要自定义

 整个过程如下图所示

因此,当我们在键盘输入“fff空格ggg”时,经过cin的读取之后,内存变量被读取的内容应该fff,因为cin把空格视作结束符,而缓冲区中仍旧残留着“空格ggg\n”,如下图所示

但是同时我们可以利用该原理,从以空格或者制表符为分隔符的缓冲区数据中读取多个数据,按下相应的结束符,才会从缓冲区读取数据到变量中,cin 每次从缓冲区中读取一个字符串,以空格作为字符或者字符串的分隔符。如下所示 

void cin_test()
{
    std::cout<<"----------- cin test ---------"<<std::endl;
    std::string str;
    //fff ggg
    std::cin>>str;
    std::cout<<str<<std::endl;//fff
    
    //此时缓冲区中仍旧残留着ggg和换行符
    std::cin>>str;
    std::cout<<str<<std::endl;

}

由于 cin 在遇到空格或者制表符(/tab)时,会停止读取输入,因此第一个 cin 只会读取第一个字符串(第一个非空白字符开始到下一个空格字符结束之间的字符串)。这时候缓存区中还有残留的数据,因此下一个 cin 会直接从缓冲区中读取数据,而不会请求输入。

因此当我在键盘输入"fff ggg"时,第一次可以读取到“fff”,而缓冲区中仍旧残留着“ggg”,因此我可以继续读取,从而读取到ggg。

但是需要注意的是最后一个换行符会放在缓冲区中

void cin_test()
{
    std::cout<<"----------- cin test ---------"<<std::endl;
    std::string str;
    //fff ggg
    std::cin>>str;
    std::cout<<str<<std::endl;//fff
    std::cin>>str;
    std::cout<<str<<std::endl;
    
    char ch;
    std::cin.get(ch);//读取到缓冲区中的空格
    std::cout<<static_cast<int>(ch)<<std::endl;
}

如上所示,当我依旧输入"fff ggg",并按下回车后,cin依次从缓冲区中读取字符串fff和ggg,但是最后剩下的换行符会残留在缓冲区中

由于我们接下来要介绍的cin.get()每次只读取一个一个字符,因此我们可以从结果看出,当读取完fff和ggg之后,cin.get()把缓冲区中残留的换行符也读取出来了,其ASCII值为10

cin.get()

cin.get() 是C++标准库中的函数,用于从输入流中获取字符,包括空白字符(如空格、制表符和换行符)与 cin 不同,cin.get() 不会将制表符、空白字符(空格)视为终止输入的标志,因此您可以使用它来获取包括空白字符在内的整行文本。但是默认情况下,cin.get() 使用换行符(\n)作为定界符(终止读取数据的结束符),表示读取到换行符时结束

cin.get分别有以下几种重载

// single character (1)	从标准流中读取单个字符;
int get();
istream& get (char& c);

// c-string (2)	从标准流中读取字符串并存储在c标准的s字符串中;
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);

可以看到,cin.get()会读取指定个数的字符并遇到换行符时终止读取,而cin则连续读取,只要遇到空白字符(空格、制表符、换行符等)就终止读取

此外,接收cin.get()读取的内容的内存变量类型需要时字符数组或者字符类型,不能是std::string流

如下所示,我们做个实验

void cinget_test()
{
    std::cout<<"----------- cin.get() test ---------"<<std::endl;
    char str[100];
    //fff ggg
    std::cin.get(str,100);//最多读取100个字符并存储到字符数组str中
    std::cout<<str<<std::endl;

    char ch;
    //读取缓冲区中最后一个换行符
    std::cin.get(ch);
    std::cout<<static_cast<int>(ch)<<std::endl;
    std::cout<<"------------------------------"<<std::endl;
}

 在键盘输入"fff ggg",可以看到,cin.get一次性把字符串"fff ggg"读取到了,但是将最后的换行符残留在了缓冲区中,而我们再次从缓冲区中使用cin.get读取一个字符时,读取到的正是这个残留的换行符(ASCII值为10)

因此,cin.get() 与 cin 都是遇到相应的结束符才会结束从缓冲区读取数据,它们都不对换行符进行处理,换行符都会残留在缓冲区中。如果下次不想从上一次的缓冲区中读取数据,可以使用 cin.ignore() 忽略上一个缓冲区中的数据,或者使用 cin.getline()。 

cin.getline()

cin.getline() 是C++标准库中的函数,用于从输入流中读取一行文本,并允许您指定一个定界符字符来结束读取。默认的定界符是换行符 (\n),表示读取到换行符时结束。但您可以通过提供第三个参数来指定自定义的定界符字符。

cin.getline() 与 cin >> 、cin.get() 的使用基本一致,唯一的区别就是 cin >> 、cin.get() 遇到结束符终止从缓存区读取数据时,换行符会残留在缓冲区中,而使用 cin.getline() 换行符不会残留在缓冲区中。

我们使用这段代码进行测试,这段代码与上述测试cin.get()的代码完全一样,只是函数换成了cin.getline,但是呈现的效果是不同的 

void cingetline_test()
{
    std::cout<<"----------- cin.getline() test ---------"<<std::endl;
    char str[100];
    std::cin.getline(str,100);
    std::cout<<str<<std::endl;

    char ch;
    std::cin.get(ch);
    std::cout<<static_cast<int>(ch)<<std::endl;
    std::cout<<"------------------------------"<<std::endl;
}

 

如图所示,当我从键盘输入"fff ggg"并按下回车后,cin.getline会一次性将字符串"fff ggg"读取出来,但是并不会将换行符残留在缓冲区中,因此当执行到cin.get(ch) 时,缓冲区中并没有数据,它会等待我们从键盘输入数据,图片里显示的那个空行是我再次在键盘敲下了一个回车键之后,cin.get()读取到之后输出的

getline()

getline是单独的一个函数,它的作用与cin.getline几乎一样,它可以连续从缓冲区中读取数据,并遇到换行符终止读取,同时不会将换行符残留在缓冲区中,而它与cin.getline的区别,除了用法稍显不同,它可以从缓冲区中读取到的数据可以存储到std::string中,而cin.getline只能存储到字符数组或字符中

void getline_test()
{
    std::cout<<"----------- getline() test ---------"<<std::endl;
    std::string str;
    //读取缓冲区的数据并存储到std::string类型的str变量中
    getline(std::cin,str);
    std::cout<<str<<std::endl;

    char ch;
    std::cin.get(ch);
    std::cout<<static_cast<int>(ch)<<std::endl;
    std::cout<<"------------------------------"<<std::endl;
}

可以看到,其效果呈现出来与cin.getline是一样的

用法总结

  • cin.get() 和 cin.getline() 是输入流中的,使用之前需要包含头文件 。cin 是输入输出流中的,使用之前需要包含头文件 。getline() 是字符串流的,使用之前需要包含头文件 。
  • 从标准输入读取单个或者是多个变量(以空格、制表符、换行符隔开),尤其是整型变量,或者从多行读取整型变量到数组,使用 cin。
  • 从标准输入读取单个字符,推荐使用输入流中的 cin.get()。
  • 从标准输入读取单行字符串、多行字符串的,推荐使用字符串流中的 getline()。
  • cin、cin.get() 会将换行符残留在缓冲区中,getline() 和 cin.getline() 不会。

参考

【C/C++基础】C++中 cin、cin.get()、cin.getline()、getline() 的区别-CSDN博客

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值