您的位置:首页 > 其它

cin的个人理解

2011-08-09 18:48 148 查看
标准输入设备cin是指从键盘输入数据 , 而我们知道从键盘输入的时候是使用了缓冲的(windows中是行缓冲) ,系统将输入数据放到程序的缓存内存中是以Enter键为标志的。

也就是说 我们输入了一行数据(可以只一个字符或者N个字符时)时,这些数据先是被系统检测到后存放在系统的某处(如系统中的内存,但不是程序的内存中), 而只有当我们按下Enter键后,系统才会将输入的这一行数据存放到我们的程序的输入缓存中.

例如:假设我们程序的输入缓存用char buf[MAX_SIZE]数组表示,

那么当我们遇到第一条输入语句cin>>x>>y>>z;(假设为char类型),由于是第一次程序中的第一条输入,故此时的输入缓存还是空的。程序运行到此处时会先检测自已的输入缓存是否为空。如果为空,则会再检测是否遇到结束符EOF (EOF标志并不出现在输入缓存中) 。如果遇到EOF,则输入语句直接返回;如果没有遇到EOF结束标志,则输入操作将阻塞,即程序暂停等待用户输入。

然后我们开始输入数据,但是在我们按下回车符之前,行缓存都一行为空,程序就一直等待。直到我们按下Enter后,

我们输入的数据比如为"abcde"才会被系统存放到程序的输入缓存中。这时候cin>>x>>y>>z;就会发现输入缓存不为空了。然后x,y,z就会分别读入数据了。x='a' ,y ='b', z= 'c'; 注意,此时程序的输入缓存中的数据并没完 即”de" 还在缓存里。

程序继续运行到某处的输入语句cin>>u>>v >>w; (也为char类型) ,然后发现输入缓存中还有数据,则u = 'd' ,v = 'e'; 但将给w赋值的时候发现没数据了,此同就同上了,程序又开始等待 (同上) .

验证程序(c++):

int main()
{
char x,y,z,u,v,w;
cout<<"Please enter the data :";
cin>>x>>y>>z;
cout<<"then x = "<<x<<",y = "<<y<<",z = "<<z<<endl;
//再次输入u,v,w
cin>>u>>v>>w;
cout<<"u = "<<u<<" , v = "<<v<<" , w = "<<w<<endl;
return 0;
}


第一次输入abcde

第二次输入f

输出结果:x='a',y='b',z='c',u='d',v='e',w='f'

再来看看输入类型不相符时的情况:
再此之前,先来简单说下cin这个istream类的个人理解。

cin为输入流对象,在iostream头文件中.

这个cin对象,里面有个标志位成员变量flag(假设)是用来指示cin是否遇到过错误(0为error, 1 为OK)。比如:cin>>x; (x为int型) , 但是我们确输入的是字母. 这时候cin的那个错误标志就会被置为false(即遇到错误) 。 此标志位被置为false后,就代表cin对象遇到错误了,这个位不会自动恢复正常。 然后后面的输入语句cin>>y等等,就都会直接结束了。而不会阻塞等待用户输入了。 直接结束的意思是后面的输入无效(但程序并不会中止),比如上面的y 就不变,相当于没有执行cin操作一样.

要使cin从错误变为正常可以用 cin.clear()语句清除错误.

大家应该见过此类的表达式

if(cin) 或者while(cin)

//do process

这个表达式是什么意思呢? cin本来是一个istream对象呀,如何用非bool来来作测试条件呀? 这里cin的实现里应该重载了一个(bool)cin强制转换为bool量,那这个强制转换成啥呀? 即上面的标志位flag了, 若flag为真,则此条件也为真,若为假,则此条件也就为假了.

下面看个具体的例子:

当为语句int x; 程序中有条输入语句cin>>x; 我们来看看情况会如何?
程序运行的流程还是会一样,先检测输入缓存,若为空,则检测EOF标志。若无EOF标志,则等待输入。

当程序运行到cin>>x时,我们输入了一个字符a,再按下回车。输入缓存中就为 'a'了。

程序检测输入缓存,发现不为空。然后就读依到字符'a'了。但是发现a不是数字呀!! 此时cin的标志位就会置为false,即遇到错误。

但是现在的输入缓存中会变成什么样呢? 程序发现'a'不是数字后,会将其再次放到输入缓存中.即输入缓存还是为'a';

验证程序如下:

int main()
{
int x = 0;
cout<<"enter a data for int x:";
cin>>x;
cout<<x<<endl;

char c = 'p';
cout<<"cin的标志位:"<<(bool)cin<<endl; //重载的bool强制转换,可以试试(int)cin等发现编译错误。
cin>>c;
cout<<"c = "<<c<<endl; //有变化吗?c并未改变
cin.clear(); //清除cin的错
cout<<"cin的标志位:"<<(bool)cin<<endl;
cin>>c;
cout<<"c = "<<c<<endl; //现在成功输入了吗?
}


再来看看while(cin>>x)结束的方式 (x为任意类型)

1.可以用 上面的方法,使cin的标志位置为false.但这种方法得在while后面再用cin前,使用cin.clear()清除错误。 (cin>>x的返回值为cin的引用.相当于cin>>x,while(cin){})

2.可以在输入新的一行时输入^z (键盘上按下 ctrl+z) 回车,这种情况下cin也标志位也会置为false. 注意:^z得出现在输入的每行的第一个才有效!

下面就我个人理解来解释下 ^z:

^z 相当于文件输入流的EOF标志。

从上面可知cin>>x的时候,程序是先检测输入缓存是否为空。若为空,则再检测EOF标志。若无EOF,则程序等待用户输入。注:^z并不会进入到输入缓存中

每按一次回车时候,程序就执行下上面的步骤。

我们可以认为 ^z 符号只在一次回车时有用。即当输入 'abc'^z的时候, 程序执行不到检测EOF时,就已经有输入了(此时这次的^z就已经失效了,因为它的前面有输入了)

故:^z ( ctrl+z)结束时,得在行首输入! 后面要再次使用cin时,得再调用cin.clear();

验证如下:

int main()
{
int c;
while(cin>>c){
cout<<"in while"<<endl;
cout<<"请在行首按下^z结束(ctrl+z) 或者输入字母结束 "<<endl;
}
cout<<"cin 的状态:"<<(bool)cin<<endl; //观察cin的状态
cin.clear();//然后就可以接着用cin了
}


本文完。如有错误,还请各个高手指正。

转载请注明出处.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: