当前位置: 首页 > news >正文

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   gggstd::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 gggstd::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 gggstd::cin>>str;std::cout<<str<<std::endl;//fffstd::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 gggstd::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博客

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Blender材质-PBR与纹理材质
  • scratch聊天机器人 2024年6月scratch四级 中国电子学会图形化编程 少儿编程等级考试四级真题和答案解析
  • sql server 连接报错error 40
  • 基于内容的音乐推荐网站/基于ssm的音乐推荐系统/基于协同过滤推荐的音乐网站/基于vue的音乐平台
  • 基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器
  • 这一文,关于 Java 泛型的点点滴滴 一(泛型基础、类型擦除)
  • Javascript面试基础6【每日更新10】
  • MyBatis中的赋值语句:#{}和${}的区别差异(常见面试题)
  • 【Python机器学习】决策树的构造——划分数据集
  • 2024最新Uniapp的H5网页版添加谷歌授权验证
  • linux进程——解析命令行参数——环境变量详解
  • Spring Security面试三道题
  • 查找算法-二分查找(折半查找)
  • 《Unity3D高级编程 主程手记》第四章 用户界面(二) UGUI 系统的原理及其组件使用
  • 简化mybatis @Select IN条件的编写
  • 《深入 React 技术栈》
  • 「译」Node.js Streams 基础
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • android 一些 utils
  • FineReport中如何实现自动滚屏效果
  • HTTP那些事
  • laravel with 查询列表限制条数
  • Linux中的硬链接与软链接
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • PAT A1120
  • SOFAMosn配置模型
  • Spring Cloud中负载均衡器概览
  • 工作手记之html2canvas使用概述
  • 关于List、List?、ListObject的区别
  • 简单易用的leetcode开发测试工具(npm)
  • 那些被忽略的 JavaScript 数组方法细节
  • 前言-如何学习区块链
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 学习使用ExpressJS 4.0中的新Router
  • 终端用户监控:真实用户监控还是模拟监控?
  • k8s使用glusterfs实现动态持久化存储
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • # 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
  • #QT(串口助手-界面)
  • #vue3 实现前端下载excel文件模板功能
  • (12)目标检测_SSD基于pytorch搭建代码
  • (arch)linux 转换文件编码格式
  • (NSDate) 时间 (time )比较
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (windows2012共享文件夹和防火墙设置
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (笔试题)合法字符串
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (分布式缓存)Redis分片集群
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (四)库存超卖案例实战——优化redis分布式锁
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战