C++中字符串分为C风格字符串(就是char数组)和string字符串类型(需要包含string头文件),针对这两种类型,C++提供了很多方法可供输入:cin
, cin.get()
, cin.getline()
, getline()
。
cin
这是最常用的方法,cin可以接收一个字符串,无论是string对象还是char []数组都可用cin输入。用cin输入时,会跳过开头的空白字符(“空格”, “TAB”, “回车”),并且结尾遇到空白字符就会认为输入结束。
下面的代码分别创建了字符数组a和string对象b,接收输入并打印出来。
#include <iostream>
#include <string>
using namespace std;
int main()
{
char a[10];
string b;
cout << "Enter char[]: ";
cin >> a;
cout << "Enter string: ";
cin >> b;
cout << endl
<< "char[]:" << a << " string: " << b << endl;
return 0;
}
不输入空白字符的情况下,一切正常,分两次输入的abc和def,都正常打印出来:
输入空白字符的情况下,此时只进行了一次输入”abc<空格>def“。cin遇到空格认为输入结束,于是将abc保存在字符数组a中,剩下的”<空格>def“仍然保存在缓冲区中。在第二个cin执行时,由于缓冲区中仍有字符,所以没有让用户进行输入。第二个cin跳过了开头的空白字符,遇到认为输入结束,所以读取了”def“并保存在string对象b中:
cin.get()
cin.get()
主要用于读取单个字符或字符数组,可以接收空白字符。它有很多重载的版本,无论哪个版本都不能输入string对象。
无参数
无参数的cin.get()
用来从指定的输入流中提取一个字符(包括空白字符),函数的返回值就是读入的字符,返回类型为int类型。 若遇到输入流中的文件结束符,则函数值返回文件结束标志EOF(End Of File),一般以-1代表EOF,用-1而不用0或正值,是考虑到不与字符的ASCII代码混淆,但不同的C ++系统所用的EOF值有可能不同。
#include <iostream>
using namespace std;
int main()
{
char c;
while ((c = cin.get()) != EOF)
cout << c;
cout << "ctrl+z ,Done" << endl;
return 0;
}
执行效果如下:
注意:cin.get()
不会消耗缓冲区中的回车。其另一种常见用法为通过cin.get()
(不赋给任何变量)来消耗缓冲区中的回车。
一参数
其调用形式为cin.get(ch)
,其作用是从输入流中读取一个字符,赋给字符变量ch。如果读取成功则函数返回true(真),如失败(遇文件结束符) 则函数返回false(假)。
#include <iostream>
using namespace std;
int main()
{
char c;
while (cin.get(c))
cout << c;
cout << "ctrl+z ,Done" << endl;
return 0;
}
执行效果如下:
二参数
其调用形式为cin.get(字符数组名, 接收字符数n)
。主要用来接收一行字符串(可以接收空格),这个最大的用途是可以定量的接收字符的个数。但是要注意,如果定义的数组的个数是n,则实际上只能接收n-1个字符,还要加上’\0’。
#include <iostream>
using namespace std;
int main()
{
char a[5], b[5];
cin.get(a, 5);
cin.get(); // 用于消耗缓冲区中的回车
cout << a << endl;
cin.get(b, 5);
cout << b << endl;
cout << "done" << endl;
return 0;
}
执行效果如下:
前面说过,cin.get()
不会消耗缓冲区中的回车,所以在上述代码中,用了一次无参数版本的cin.get()
来消耗回车,从而保证输入的正确。
如果没有第9行的代码,第二次的输入遇到缓冲区中的回车就结束了,从而认为用户输入了空字符串,执行效果如下。
三参数
其调用形式为cin.get(字符数组名, 接收字符数n, 终止字符)
。其作用是从输入流中读取n-1个字符,赋给指定的字符数组(或字符指针指向的数组),如果在读取n-1个字符之前遇到指定的终止字符,则提前结束读取。如果读取成功则函数返回true(真),如失败(遇文件结束符) 则函数返回false(假)。
#include <iostream>
using namespace std;
int main()
{
char a[5];
cin.get(a, 5, '#');
cout << a << endl;
return 0;
}
执行效果如下:
第一次输入了很多字符,只读取了4个;第二次由于遇到了’#',提前结束输入。
cin.getline()
cin.getline()
和cin.get()
的作用差不多,都能接收空白字符的输入,都不能输入string对象。其用法也大致相同,但是cin.getline()
只有二参数和三参数版本,没有无参数和一参数版本。
cin.getline()
和cin.get()
的一个重要区别是:cin.getline()
会消耗缓冲区中的回车,而cin.get()
不会。
二参数
其调用形式为cin.getline(字符数组名, 接收字符数n)
。
#include <iostream>
using namespace std;
int main()
{
char a[5], b[5];
cin.getline(a, 5);
cout << a << endl;
cin.getline(b, 5);
cout << b << endl;
cout << "done" << endl;
return 0;
}
这段代码和cin.get()
二参数版本中的代码类似,除了将cin.get()
换成cin.getline()
,还去掉了用于消耗回车的cin.get()
。执行效果如下:
由于cin.getline()
会消耗回车,所以不需要cin.get()
。
三参数
其调用形式为cin.getline(字符数组名, 接收字符数n, 终止字符)
。代码类似cin.get()
三参数版本,就不放了。
getline()
getline()
可以接受一个字符串输入,包括空格,但需要引入头文件string。因为cin.getline()
属于istream流,而getline()
属于string流。getline()函数不能输入char数组,只能输入string对象。
getline()
返回输入流对象的引用。通过检查这个返回值,可以判断读取操作是否成功。
二参数
定义:std::getline(std::istream& is, std::string& str);
is
:输入流对象,通常是std::cin
。str
:存储读取内容的字符串对象。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
while (getline(cin, str))
cout << "You entered: " << str << endl;
cout << "done" << endl;
return 0;
}
执行效果如下:
三参数
定义:std::getline(std::istream& is, std::string& str, char delim);
is
:输入流对象,通常是std::cin
。str
:存储读取内容的字符串对象。delim
(可选):指定的分隔符,默认是换行符 \n。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
getline(cin, str, '#');
cout << str << endl;
return 0;
}
执行效果如下:
总结
下表总结了上述方法的区别
输入char数组 | 输入string字符串 | 输入空白字符 | 其他 | |
---|---|---|---|---|
cin | √ | √ | × | |
cin.get() | √ | × | √ | 不消耗回车 |
cin.getline() | √ | × | √ | 消耗回车 |
getline() | × | √ | √ |