C++面向对象程序设计 - 标准输入流

        C++中,头文件iostream.h中定义了cin,cout, cerr, clog等4个流对象,cin是输入流,cout, cerr, clog是输出流。cin是istream类的对象,它从标准输入设备(键盘)获取数据,程序中的变量通过流提取符“>>”从流中提取数据。

        注意的是,在输入完成数据再按回车键后,该行数据才被送入键盘缓冲区,形成输入流,提取运算符“>>”才能从中提取数据。

        当输入流cin处于出错状态时,如果测试cin的值,可以发现它的值为false(假),则cin为0值;如果输入流在正常状态,cin的值为true(真),即cin为一个非0的值。如下所示:

if(!cin)        // 流cin处于出错状态,无法正常提取数据
    cout <<"Error";

        此时,通过一个案例演示下cin为false时情况。当正常输入float类型内容时,一直循环输出;当输入非float类型致使cin出错为0时,而结束循环操作。代码如下:

#include <iostream>
using namespace std;

int main(){
	float grade = -1;
	do{
		if(grade < 0) {
			// nothing...
		}
		else if(grade >= 85) cout <<grade <<" Good!" <<endl;
		else if(grade < 60) cout <<grade <<" Fail!" <<endl;
		else cout <<grade <<endl;
		cout <<"enter grade:";
	} while(cin >> grade);
	cout <<"The end." <<endl;
	return 0;
}

        每次提出浮点型数据如果成功,则值赋给变量grade,cin为真;当输入“Z”时,无法提取为浮点型,cin为假返回0,则程序结束。运行结果如下图:

一、用于字符输入的流成员函数

        除了可以用cin输入标准类型的数据外,还可以用istream类流对象的一些成员函数,实现字符输入。

1.1 用get函数读取一个字符

        流成员函数get有3种形式:无参数的,有一个参数的,有3个参数的。

(1)不带参数的get函数

        调用形式为:

cin.get()

        用来从指定的输入流提取一个字符(包括空白字符),函数的返回值是读入的字符。若遇到输入流中的文件结束符,则函数值返回文件结束标志EOF(End Of File),一般以-1代表EOF,用-1而不用0或正值,是考虑不与字符的ASCII代码混淆,但不同的C++系统所用的EOF值有可能不同。

        使用get读取字符,示例如下:

#include <iostream>
using namespace std;
int main(){
	int c;
	cout <<"Enter Message:" <<endl;
	while((c = cin.get()) != EOF) cout.put(c);
	return 0;
}

        按住Ctrl+Z后,再按Enter回车结束程序,运行后结果如下图:

        C语言中的getchar函数与流成员函数cin.get()的功能相同,C++程序保留了C的这种用法,可以用getchar()从键盘读取一个字符赋给变量c。修改后代码如下:

#include <iostream>
using namespace std;
int main(){
	int c;
	cout <<"Enter Message:" <<endl;
	while((c = getchar()) != EOF) cout.put(c);
	return 0;
}

        其运行结束和之前是一样的。

(2)有一个参数的get函数

        调用形式为:

cin.get(ch)

        其作用是从输入流中读取一个字符,赋给字符变量ch。如果读取成功则函数返回非0值(真),如失败(遇文件结束符)则函数返回0值(假)。

        示例代码如下:

#include <iostream>
using namespace std;
int main(){
	char c;
	cout <<"Enter Message:" <<endl;
    // 读取一个字符赋给字符变量c,如果读取成功,cin.get(c)为真
	while(cin.get(c)) cout.put(c);
	return 0;
}

        运行结果如下图:

(3)有3个参数的get函数

        调用 形式为:

cin.get(字符数组, 字符个数n, 终止字符)

或者

cin.get(字符指针, 字符个数n, 终止字符)

        其作用是从输入流中读取n-1个字符,赋给指定的字符数组(或字符指针指向的数组),如果在读取n-1个字符之前遇到指定的终止字符,则提前结束读取。如果读取成功则函数返回非0值(真),如失败(遇文件结束符)则函数返回0值(假)。

        示例代码如下:

#include <iostream>
using namespace std;
int main(){
	char ch[20];
	cout <<"Enter Message:" <<endl;
	cin.get(ch, 15, '\n');			// 指定换行符为终止字符
	cout <<ch <<endl;
	return 0;
}

        运行结果如下图:

        此时,当输入完“I study C++ very hard.”后,按Enter回车则程序结束,最后输出结果为“I study C++ ve”原因是cin.get中指定字符个数为15。

1.2 用成员函数getline函数读入一行字符

        cin.getline函数的作用是从输入流中读取一行字符,其用法与带3个参数的get函数类似。其调用形式为:

cin.getline(字符数组(或字符指针), 字符个数n, 终止标志字符)

        示例代码如下:

#include <iostream>
using namespace std;
int main(){
	char ch[20];
	cout <<"Please enter all message:" <<endl;
    // 注意:流提取符">>"从流中提取数据时通常跳过输入流中的空格、tab键、换行符等空白字符
	cin >>ch;	
	cout <<"The string read with cin is:" <<ch <<endl <<endl;	// 输出为I
	
	/**
	 * getline读取时指针已移至后面"I"的空格位置
	 * 此时getline指定结束位置为'/',估计遇到终止符位置停止读取
	 */
	cin.getline(ch, 20, '/');
	cout <<"The first message is:" <<ch <<endl;

	cin.getline(ch, 20, '/');
	cout <<"The second message is:" <<ch <<endl;
	
	cin.getline(ch, 20);
	cout <<"The third message is:" <<ch <<endl;
	cout <<"End." <<endl;
	return 0;
}

        运行结果如下图:

        如上图可见,“I like C++.”并未完整输出出来,这是因为cin>>读取字符串时,它会读取直到遇到空白字符(空格、制表符、换行符等)为止。因此,cin >> ch只会读取“I”,并将剩余的输入留在输入流(stdin)中。

        接下来,使用了cin.getline()来尝试从输入流中读取数据,但第一次调用 cin.getline(ch, 20, '/')时,由于输入流中紧接着“I" 之后的就是空格和"like C++.",它会立即读取空格之后的内容(直到遇到换行符或达到指定的20个字符长度,或遇到指定的分隔符"/"),所以The first message对应的则是” like C++“。

        要修复这个问题并读取完整的消息,应该使用getline()而不是cin >>,代码如下:

#include <iostream>
using namespace std;
int main(){
	char ch[20];
	cout <<"Please enter all message:" <<endl;
	
	cin.getline(ch, 20, '/');
	cout <<"The first message is:" <<ch <<endl;

	cin.getline(ch, 20, '/');
	cout <<"The second message is:" <<ch <<endl;
	
	cin.getline(ch, 20);
	cout <<"The third message is:" <<ch <<endl;
	cout <<"End." <<endl;
	return 0;
}

        运行结果如下图:

二、istream类的其他成员函数

        除了以上介绍的用于读取数据的成员函数外,istream类还有其他在输入数据时用的一些成员函数。

1.eof函数

        eof是end of file的缩写,表示”文件结束“。从输入流读取数据,如果到达文件末尾(遇文件结束符),eof函数值为非零值(表示真),否则为0(假)。

        示例代码如下:

#include <iostream>
using namespace std;
int main(){
	char c;
	cout <<"Please enter all message:" <<endl;
	while( !(cin.eof()) ) if((c = cin.get()) != ' ') cout.put(c);
	cout <<"End." <<endl;
	return 0;
}

        运行结果如下图:

2.peek函数

        peek是”观察“的意思,peek函数的作用是观测下一个字符。调用形式为:

c = cin.peek();

        cin.peek函数的返回值是指针指向的当前字符,但它只是观测,指针仍停留在当前位置,并不后移。如果要访问的字符是文件结束符,则函数值是EOF(-1)。

        这里将1.2中示例代码修改下,使用循环输出内容。代码如下:

#include <iostream>
using namespace std;
int main(){
	char c;				// 接受peek()返回值
	char ch[20];		
	int count= 0;		// 记录索引值
	cout <<"Please enter all message:" <<endl;
	
	while((c = cin.peek()) == 'I'){
		count++;
		cin.getline(ch, 20, '/');			//读取字符
		cout <<"The " <<count <<" message is:" <<ch <<endl;
	}
	cout <<"End." <<endl;
	return 0;
}

        cin.peek函数它用于检查输入流的下一个字符,但不会从流中移除该字符。这里cin.peek() == 'I' 表达式,用于检查输入流中的下一个字符是否是字符”I“。

        刚好输入内容”I like C++./I study C++./I am happy./“中每行开始都以I为首字母,因此确保了执行循环时,每次输入都以I字母开头,当首字母不是"I"后则结束循环,结果如下图:

3.putback函数

        调用形式:

cin.putback(ch);

        其作用是将前面用get或getline函数从输入流中读取的字符ch返回到输入流,插入到当前指针位置,以供后面读取。

        在1.2示例中,使用cin >>读取字符串时,它会读取到空字符为止,导致”I like C++“输出不完整。这里可以使用putback函数将字符返回到输入流中,代码如下:

#include <iostream>
using namespace std;
int main(){
	char ch[20];
	cout <<"Please enter all message:" <<endl;
	cin >>ch;	// 注意:流提取符">>"从流中提取数据时通常跳过输入流中的空格、tab键、换行符等空白字符
	cout <<"The string read with cin is:" <<ch <<endl <<endl;	// 输出为I
	// 将I字符返回到输入流中
	cin.putback(ch[0]);
	/**
	 * getline读取时指针已移至后面"I"的空格位置
	 * 此时getline指定结束位置为'/',估计遇到终止符位置停止读取
	 */
	cin.getline(ch, 20, '/');
	cout <<"The first message is:" <<ch <<endl;

	cin.getline(ch, 20, '/');
	cout <<"The second message is:" <<ch <<endl;
	
	cin.getline(ch, 20);
	cout <<"The third message is:" <<ch <<endl;
	cout <<"End." <<endl;
	return 0;
}

        运行结果如下图:

4.ignore函数

        调用形式为:

cin.ignore(n, 终止字符);

        其作用是跳过输入流中n个字符,或在遇到指定的终止字符时提前结束(此时跳过包括终止字符在内有若干字符)。

        示例1:

// 跳过输入流中5个字符,遇到'A'后就不再跳过
cin.ignore(5, 'A');

        示例2:

// n默认值为1,终止字符默认为EOF
cin.ignore();

        当前先通过一个示例,并查看运行后的结果,代码如下:

#include <iostream>
using namespace std;
int main(){
	char ch[20];		
	int count= 0;		// 记录索引值
	cout <<"Please enter all message:" <<endl;
	
	while(cin.peek() == 'I'){
		count++;
		cin.get(ch, 20, '/');			//读取字符
		cout <<"The " <<count <<" message is:" <<ch <<endl;
	}
	cout <<"End." <<endl;
	return 0;
}

        运行结果如下图:

        如上图可见,后面内容并未正常输出,这是遇到第一个字符的终止标志字符'/',读入结束。如果希望输出"I study C++”,则应该设法跳过输入流中第一个'/'(终止标志字符),可以使用ignore函数来实现这目的。代码如下:

#include <iostream>
using namespace std;
int main(){
	char ch[20];		
	int count= 0;		// 记录索引值
	cout <<"Please enter all message:" <<endl;
	
	while(cin.peek() == 'I'){
		count++;
		cin.get(ch, 20, '/');			//读取字符
		cout <<"The " <<count <<" message is:" <<ch <<endl;
		cin.ignore();
	}
	cout <<"End." <<endl;
	return 0;
}

        运行后结果如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值