码迷,mamicode.com
首页 > 编程语言 > 详细

C++之输入(cin)详解

时间:2016-04-22 19:41:50      阅读:3050      评论:0      收藏:0      [点我收藏+]

标签:

1、cin:

         输入操作的原理,程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入,这就是例子中为什么会出现输入语句失效的原因! 

         cin输入结束的条件:Enter、Space、Tab。cin对这些结束符的处理:丢弃缓冲区中这些字符。与cin.get()不同。

案例1:

#include <iostream>
using namespace std;
int main() 
{
	int m, n;
	cin >> m;
	cin >> n;
         cout << m << n << endl;
	return 0;
}

测试正常输入:

技术分享

 

测试异常输入:

技术分享            技术分享

 

案例2:string的输入

void main()
{	string str1;
	cin >> str1;  //遇到空格的地方就停止字符串的读取输入   
	cout << str1 << endl;

	cin.get();
	getline(cin, str1);
	cout << str1 << endl;
}

测试:

技术分享      技术分享

        可以看出cin是遇到“空格”就停止读取输入,并且cin是从第一个“非空格字符”开始读取;

        而getline则是直接从第一个字符开始读取(无论是不是空格,都要读入),并且getline是遇到“回车”停止读入;

        当把上述代码中 的cin.get()去掉,则输入“123”----》回车  后,getline直接读取“回车”,运行完毕!

 

案例3:

int main()
{
	char str[8];
	cin.getline(str, 5);
	cout << str << endl;

	cin.getline(str, 5);
	cout << str << endl;
	return 0;
}

测试一:abcd (回车)abcd (输出)efgh(回车)efgh (输出)当用户第一次输入的字符串字符数小于4时,程序执行正常! 

测试二:abcdefgh (回车)abcd (输出)    (输出-换行)当用户第一次输入的字符数字符数大于4时,第一个字符串接受输入的前四个字符,而第二次的输入操作没有执行,第二个字符串输出为空。

 

2、cin.get():

案例1:

int main()
{
	char str1;
	char str2;
	str1 = cin.get(); //读取单个字符,在屏幕输入
	str2 = cin.get();
	cout << str1 << str2 << endl; //输出刚刚载入的单个字符
	system("pause");  //进行暂停,否则会一闪而过
}

输入:abcd 输出:ab
既然cin.get()是读取第一个字符,那str2为什么不也是a呢?
原理如下:
    在cin这个对象里,有一个储存字符的流,可以想象成缓冲区,事实上是cin里封装的一个东西.当我们在程序上输入字符后,对象cin获得了我们输入的字符。例如获得abcd,然后再通过.get()把流里面的第一个字符去掉,赋给str1,这时,cin里储存的流的数据为bcd,而str1则获得了a。当我们再次运行str2 = cin.get()时,同理把cin里流的数据的b拿出来给了str2,此后,cin里面的流的数据为cd,而str2则为b,所以最后输出时,便能输出ab。

    还有个补充,究竟什么时候才输入数据呢?我们可以再通过上面的代码进行尝试,我们输入单个字母‘a‘,然后按回车,发现并没有输出数据,而是再等待一次输入数据,我们再输入字母‘b‘,按回车后便输出ab了。相信到这里,大家都应该明白了,因为当我们第一次输入a后,通过str1 = cin.get()使cin里的流没有数据,清空了。所以到第二次要再赋给str2值时,它找不到数据,要重新再输入数据。由此来看可以知道,当cin里的流数据清空时,便需要重新输入才能赋值。

 

案例2:

	{
		char str1[10], str2[10];
		cin >> str1;
		cin >> str2;
		cout << str1 << endl;
		cout << str2 << endl;
		return 0;
	}

测试一输入:abcd[Enter]efgh[Enter]       输出:abcdefgh【分析】输入遇到回车符结束,很正常。 

测试二输入:abcd efgh      输出:abcdefgh   【分析】第一次读取字符串时遇到空格则停止了,将abcd读入str1,并舍弃了空格,将后面的字符串给了第二个字符串。这证明了cin读入数据遇到空格结束;并且丢弃空格符;缓冲区有残留数据室,读入操作直接从缓冲区中取数据。 

案例3:

int main()
{
	char str1;
	char str2;
	str1 = cin.get(); //读取单个字符,在屏幕输入
	cin.get();
	str2 = cin.get();
	cout << str1 << str2 << endl; //输出刚刚载入的单个字符
}

输入:abcd 输出:ac

    程序中有3个cin.get(),由此可知,当空回调cin.get()时,cin.get便自动在cin中的流数据中删除一个字母,起了一个删除作用。

 

案例4:

}
	char c1, c2;
	cin.get(c1);
	cin.get(c2);
	cout << c1 << " " << c2 << endl;   // 打印两个字符       cout<<(int)c1<<""<<(int)c2<<endl; // 打印这两个字符的ASCII值
	return 0;
}

测试一输入:a[Enter]输出:a 97 10【分析】会发现只执行了一次从键盘输入,显然第一个字符变量取的‘a‘,第二个变量取的是Enter(ASCII值为10),这是因为该函数不丢弃上次输入结束时的Enter字符,所以第一次输入结束时缓冲区中残留的是上次输入结束时的Enter字符! 

测试二输入:a b[Enter]输出:a 97 32【分析】显然第一个字符变量取的‘a‘,第二个变量取的是Space(ASCII值为32)。原因同上,没有丢弃Space字符。 

 

案例5:

	{
		char ch, a[20];
		cin.get(a, 5);
		cin >> ch;
		cout << a << endl;
		cout << (int)ch << endl;
		return 0;
	}</span>

测试一输入:12345[Enter]输出:123453【分析】第一次输入超长,字符串按长度取了"1234",而‘5‘仍残留在缓冲区中,所以第二次输入字符没有从键盘读入,而是直接取了‘5‘,所以打印的ASCII值是53(‘5‘的ASCII值)。

测试二输入:1234[Enter]a[Enter]输出:123497【分析】第二次输入有效,说明该函数把第一次输入后的Enter丢弃了!

3、cin.getline:

       cin.getline()与 cin.get(array_name,Arsize)的读取方式差不多,以Enter结束,但是接受空格字符。按照长度(Arsize)读取字符, 会丢弃最后的Enter字符。但是这两个函数是有区别的:cin.get(array_name, Arsize)当输入的字符串超长时,不会引起cin函数的错误,后面的cin操作会继续执行,只是直接从缓冲区中取数据。但是cin.getline()当输入超长时,会引起cin函数的错误,后面的cin操作将不再执行。

	char str1[200];
	char str2[200];
	cin.getline(str1, sizeof(str1), 'X');  //以单个英文字母'X'作为终止标识符
	cin.getline(str2, sizeof(str2), 'Y');  //以单个英文字母'Y'作为终止标识符
	cout << "第一行是:" << str1 << endl; //输出
	cout << "第二行是:" << str2 << endl;
	system("pause");
}

技术分享

 

4、cin异常:

ios类定义了这四个常量badbit, eofbit, failbit, goodbit,其实这四个标志常量就是取对应标志位的掩码,也即输入的四种异常情况!
以上四个常量对应的取值为:
       ios::badbit       输入(输出)流出现致命错误,不可挽回 

       ios::eofbit       
已经到达文件尾
       ios::failbit     
输入(输出)流出现非致命错误,可挽回 

       ios::goodbit     
流状态完全正常, 各异常标志位都为0

我们可以用输出语句来验证这几个常量的值:
       cout << ios:: failbit << endl;           //2
       cout << ios:: eofbit << endl;          //1
       cout << ios:: badbit << endl;
         //4

       cout << ios:: goodbit << endl;       //0

 

cin.fail()、cin.clear()、cin.sync()例子:

int main()
{
	int a;
	while (true)
	{
		cin >> a;
		if (!cin) //条件可改写为cin.fail()
		{
			cout << "输入类型错误,请重新输入!" << endl;
			cin.clear(); //复为标志,将cin中的所有标志设置为有效状态
			cin.sync(); //清空流
		}
		else
		{
			cout << a << endl;
			break;
		}
	}
	system("pause");
}

     上面的cin默认值为非0,当输入为非整形时,它的状态标识符改为fail(即0),再用cin.clear()让错误标识改回为非0,可以继续输入,再清空流数据继续输入。如果没有了cin.clear(),则会进入死循环,其过程为我们输入了英文字母,它的状态标识便为fail,当运行到条件判断时,便总是回到错误的条件表示里,并且再也没有办法输入,因为错误的表示关闭了cin,所以会进入死循环。可以分别注释掉cin.clear()和cin.sync()进行验证。

 

5、in.ignore()

       这个函数用来丢弃输入缓冲区中的字符,第一参数定义一个数(_Count),第二个参数定义一个字符变量(_Delim)。下面解释一下函数是怎样执行的:函数不停的从缓冲区中取一个字符,并判断是不是_Delim,如果不是则丢弃并进行计数,当计数达到_Count退出,如果是则丢弃字符退出。

        这个函数的默认值,第一个参数默认为1,第二个参数默认为EOF。所以cin.ignore()就是丢弃缓冲区中的第一个字符。

        用cin.get()读取字符,get函数不丢弃回车符,所以回车符仍残留在缓冲区中,导致第二次读取数据直接从缓冲区中取得回车符!既然cin.get()不会自动丢弃输入结束时的回车符,这里我们就用ignore()函数,手动丢弃回车符!

int main()
{
	char c1, c2;
	cin.get(c1);
	cin.ignore(); // 用该函数的默认情况,丢弃一个字符,即上次输入结束的回车符  
	cin.get(c2);
	cout << c1 << " " << c2 << endl;   // 打印两个字符  
	cout << (int)c1 << " " << (int)c2 << endl; // 打印这两个字符的ASCII值  
	return 0;
}

 

        清空整个缓冲区:——其实该函数最常用的方式是这样的,将第一个参数设的非常大,将第二个参数设为‘\n‘,这样就可以缓冲区中回车符中的所有残留数据,因为一般情况下前面输入残留的数据是没有用的,所以在进行新一次输入操作前将缓冲区中所有数据清空是比较合理。
如:cin.ignore(1024, ‘\n‘); 

C++之输入(cin)详解

标签:

原文地址:http://blog.csdn.net/songshimvp1/article/details/51206429

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!