cin
我们先介绍c++中最常用的输入流对象cin
我们常用 cin >> num
来从缓冲区中读取数据到 num
中,num
的变量类型可以是多种类型,最常用的有 int
、string
、char
、double
、float
等等
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博客
标签:读取,get,cin,C++,缓冲区,换行符,getline From: https://blog.csdn.net/qq_58158950/article/details/138499272