测试环境:VS2013+win32+debug
在工作过程中,发现cin的结束符根据不同的成员函数会存在是否被处理的情况,再次进行记录验证。
1、cin获取缓冲区数据
常用方法包括cin>>, cin.get, cin.getline,getline
cin>>
cin是从键盘中读取想要的数据,以空格,tab以及换行作为结束符。
测试代码:
#include<iostream>
#include<string>
using namespace std;
int main(){
char a;
int b;
double c;
string d;
cin >> a >> b >> c >> d;
cout << a << " " << b << " " << c << " " << d << endl;
system("pause");
return 0;
}
运行上述程序
我们可以看到运行结果如下:
在这里需要特别注意的是,
1、cin在检测到实际有效的数据,即非结束符数据时,会忽略数据前所有的结束符等待实际有效数据。
2、读取到有效数据后,之后的结束符cin不会进行处理,而是把它留在缓冲区,由之后的读取操作进行处理,之所以cin连续的时候,不会出现结束符异常问题。是因为之后的cin会忽略掉之前留下的结束符。
3、如果不想忽略空白字符使用noskipws,noskipws 可以做到不忽略任意地方的空格。std::cin >> std::noskipws >> c1 >> c2 >> c3 >> c4;
cin.get
函数原型:
1、int cin.get();
2、istream& cin.get(char& var);
3、istream& get ( char* s, streamsize n );
4、istream& get ( char* s, streamsize n, char delim )。
其中3和4的差别在于是否可以人为指定结束符,char delim.
单个char:
测试程序(1,2一起测试):
#include<iostream>
#include<string>
using namespace std;
int main(){
char a;
char b;
a = cin.get();
cin.get(b);
cout << a << " " << b << endl;
system("pause");
return 0;
}
结果:
从上面可以看出,
1、cin.get()并没有忽略结束符,而是直接进行了读取,所以出现了上面只输入了一个字符a,然后回车,程序就执行完成的情况。
2、cin.get()的返回值是int类型,成功则返回读取字符的ASCII码值,遇到文件结束符时,返回EOF,即-1。
3、cin.get(char var)如果成功返回的是cin对象,因此可以支持连续操作,如cin.get(b).get©
字符数组:
测试程序:
#include<iostream>
#include<string>
using namespace std;
int main(){
char a[20];
char b;
char c[20];
cin.get(a,20);
cin.get(b);
cin.get(c, 20, '7');
cout << a << " " << b << " " << c << endl;
system("pause");
return 0;
}
运行结果:
从结果我们可以看出,
1、cin.get()的3和4原型在于结束符的人为设定。
2、cin.get()在读取字符数组的时候,仍然不会处理结束符。所以出现,输入完a之后,在进行输入,程序终止。
3、istream& get ( char* s, streamsize n );与cin.getline()功能类似。
cin.getline()
函数原型:
1、istream& getline(char* s, streamsize count); //默认以换行符结束
2、istream& getline(char* s, streamsize count, char delim);
测试程序:
#include<iostream>
#include<string>
using namespace std;
int main(){
char a[20];
char b[20];
cin.getline(a, 20);
cin.getline(b, 20);
cout << a << " " << b << endl;
system("pause");
return 0;
}
结果:
从结果可以看出:
1、cin.getline()。不会把结束符留下来,而是直接在本次输入完成后,就处理掉了。
getline
测试程序:
#include<iostream>
#include<string>
using namespace std;
int main(){
string test;
getline(cin, test);//不阻塞
cout << "test:" << test << endl;
system("pause");
return 0;
}
结果:
可以看出:
1、getline();并不会忽略结束符,而是直接进行读取。
cin清空输入缓冲区
cin在使用过程中,因为结束符导致的问题很多,所以可以通过清空缓冲区的方式来去除影响。
函数原型:
istream &ignore( streamsize num=1, int delim=EOF );
函数的作用,是跳过num的字符或者遇到delim终止字符时提前结束。
测试程序:
#include<iostream>
#include<string>
using namespace std;
int main(){
char a[20];
char b[20];
cin.get(a, 5);
cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
cin.get(b, 20);
cout << a << " " << b << endl;
system("pause");
return 0;
}
结果:
由结果看出:
1、程序中使用cin.ignore()成功的去除掉了之前的结束符,从而使我们的cin.get()成功完成读取,其中,numeric_limitsstd::streamsize::max()代表的是最大值,可以使用任意整数代替。如果清空整个缓冲区,可以使用cin.ignoer(numeric_limitsstd::streamsize::max()).
2、cin.ignore()如果缓冲区没有数据的话,会阻塞等待数据的到来。
但是从上面我们看到,我们最初输入的12345,却没有完整打印,这是因为我们限定了长度5,但是同时需要预留结束位“\0”,之后的5和换行符被留在缓冲区。