一、getline函数的功能
istream& getline(istream& iss,string& str, char delim), istream是输入流类型,主要功能就是将输入流iss中的数据读入str中,delim是设置的截断字符(delim前的字符串会写入str中,其中不会包含delim),当不指定时,delim默认是'\n',即回车。
二、案例分析
案例一:
只调用一次getline():
2.1.1
输入:Hello, My name is LiHua, I'm fine!
#include<iostream>
using namespace std;
void main(){
string str;
getline(cin, str, ',');
cout<<str<<endl;
}
输出:Hello //“ ,”并不会被写入str
案例二:
getline与istringstream(包含的的头文件是sstream)结合使用:
2.2.1
#include<iostream>
#include<sstream>
using namespace std;
void main(){
string str = "2022,08;2023,09;";
istringstream iss(str); // 将字符串str装入输入流对象iss中
string str_1;
getline(iss, str_1, ';');
cout<<str_1<<endl; //输出的str_1是 2022,08
getline(iss, str_1, ';');
cout<<str_1<<endl; //输出的str_1是 2023,09
getline(iss, str_1, ';');
cout<<str_1<<endl; //输出的str_1为空
}
这里想说明三个问题:
1、istream不一定非要用cin,也可以使用istringstream类型对象;
2、多次对同一个输入流对象调用getline会一段一段取出 ' ; ' 前的string;
3、如果getline次数超过原输入流中' ; '的个数,说明iss内的string都分批次取完了,再getline取入str则为空;
案例三:
getline和while结合使用:
2.3.1
#include<iostream>
using namespace std;
void main(){
string str;
while(getline(cin, str)){ //输入 Hello world!(并且回车,getline默认截断字符为'\n')
cout<<str<<endl; //输出 Hello world!
}
}
上述输入Hello world!(按下回车),getline识别到回车,所以将 Hello world! 写入str中;并且while循环不会结束,如果想要结束循环可以按下ctrl + z;
2.3.2
#include<iostream>
using namespace std;
void main(){
string str = "2022,08;2023,09;";
istringstream iss(str);
string str_1;
while(getline(iss, str_1, ';')){
cout<<str_1<<endl;
}
}
输出结果:
2022,08
2023,09
上述想说明两个问题:
1、针对 iss 对 str _1
进行一次读入后,会执行循环内操作,即输出str_1,然后进入下一轮循环;
2、getline的返回值是是一个输入流的引用,所以当读入成功时,返回的是个引用,对这个引用使用cout输出是一个地址(这里不确定,个人是这么理解的),while进行判断时为true,如果iss内的数据流全部读取完毕,继续getline则会读入失败,getline的返回为false,结束循环,故不会想上一个案例一样持续循环输入;(针对getline的返回值,有兴趣的读者可以自行查阅相关资料,本人理解有限)
2.3.3
思考题:
#include<iostream>
using namespace std;
void main(){
string str;
while(getline(cin, str, ' ')){ //' '内有一个空格,即以空格为截至符
cout<<"***"<<str<<"***"<<endl;
}
}
如果我们在控制台输入一下内容会有什么结果呢?
输入:
My name is LiHua! //按下回车
输出:
***My***
***name***
***is***
有没有答对呢?哈哈,我们继续。通过上面的学习(2.3.1)我么知道这个循环是不会结束的,因此,我们继续在控制台输入空格并且回车如下:
输入:
(有输入一个空格并且回车)
输出:
***LiHua!
***
那么这个结果有没有想到呢?这里为什么输出不是***LiHua!***呢?实际上,注意到“按下回车”被标红了吗,其实是'\n'同样被视为写入了cin中,因此我在这里输入了一个空格,就有了截断的符号,可以将此空格之前的字符输出,读入到str的实际内容应该是LiHua!\n,故此才有这样的输出;(可能解释的不太明白,读者可以自己尝试一遍,有助于相关理解)
鉴于上述表述有点乱,以下是相关输入输出在控制台结果:
My name is LiHua! //输入
***My***
***name***
***is***
//输入空格
***LiHua!
***
三、结语和问题
本篇文章是我在学习拆分字符串时针对getline相关的学习和理解,仍有相当不足之处,例如:
1、getline的返回值,其实迷迷糊糊;
2、下面的代码可以带来那些思考呢?第一点,事先对 str_1 赋值了,数据长度明显大于输出的结果 2018,09 的数据长度,是否可以猜测每次 getline 对 str_1进行了清空操作;第二点,该程序输出的结果是 iss.str()的值 ,结果是“2018,09;2019,09;”,也就说,getline并不是将 iss 中是数据类似剪切效果读入 str_1 ,而是类似复制效果读入str_1,那么可以猜测getline会记录上次输出结果在iss中的位置。
#include<iostream>
using namespace std;
void main(){
string str = "2018,09;2019,09;" ;
istringstream iss_1(str);
string str_1 = "123456789";
while(getline(iss, str_1, ';')); //这里将iss的数据都输入到str_1中
cout<<iss.str()<<endl;
}
3、本人也是个初学者,很多东西还不会,只是这两天一直不明白getline的底层实现,搜寻相关只是也是无果,以上都是我按照自身理解所写,以作记录,欢迎补充指正。