C++输入流和输出流


1 流和流类库

1.1 流的概念

程序输入:将数据输入文件传送给程序
程序输出:将数据程序传送给输出文件

C++的输入与输出
(1)标准I/O: 对系统指定标准设备的输入和输出,即从键盘输入数据,将数据输出至显示器屏幕,称为标准的输入输出
(2)文件I/O:以外存磁盘文件为对象的输入和输出,即从磁盘文件输入数据,将数据输出至磁盘文件,称为文件的输入输出
(3)串I/O: 对内存指定空间的输入和输出,通常指定1个字符数组作为存储空间,称为字符串的输入输出


1.2 流的类库

C++提供强大的I/O流类库,实现标准I/O文件I/O串I/O等3种输入输出。

流的种类 类名 作用 声明的头文件
流的顶层基类 ios 抽象基类 iostream
标准I/O istream
ostream
iostream
标准输入流和其它输入流的基类
标准输出流和其它输出流的基类
标准输入输出流和其它输入输出流的基类
iostream
文件I/O ifstream
ofstream
fstream
输入文件流类
输出文件流类
输入输出文件流类
fstream
串I/O istrstream
ostrstream
strstream
输入字符串流类
输出字符串流类
输入输出字符串流类
strstream

C++ I/O流类的层次结构IO流类的层次结构

注:iostream类分别继承istream类ostream类,构成菱形/钻石继承关系。
通过虚继承(虚基类指针vbptr、虚基类表vbtable)解决菱形继承中的二义性


2 标准输入流(istream)

标准输入流对象cin的成员函数
(1)get():每次只从输入缓冲区读取单个字符(包括换行符)。
函数原型int get();


(2)get(1个参数):每次只从输入缓冲区读取单个字符(包括换行符)。
函数原型istream& get(char &ch);
参数
ch:从输入缓冲区读取1个字符后,用于存储的字符变量。

注:get()get(1个参数)功能完全相同,仅调用方式不同


(3)get(2个参数):从输入缓冲区读取1行(字符串),并存储至字符数组中,且不清空输入缓冲区。【遗留Enter的换行符
函数原型istream& get(char* buffer, streamsize count);
参数
buffer:从输入缓冲区读取字符串后,用于存储的字符数组
count:字符数组的最大长度。

扫描二维码关注公众号,回复: 12490829 查看本文章

注:从输入缓冲区读取的字符串存入buffer字符数组中,但换行符\n仍遗留在输入缓冲区中
解决方法:可使用cin.get(ch)读取输入缓冲区中遗留的换行符。
例:

char buffer[1024];
cin.get(buffer, sizeof(buffer));

(4)getline(2个参数):从输入缓冲区读取1行(字符串),并存储至字符数组中,且清空输入缓冲区。【自动舍弃Enter的换行符
函数原型istream& getline(char* buffer, streamsize count);
参数
buffer:从输入缓冲区读取字符串后,用于存储的字符数组
count:字符数组的最大长度。

注:从输入缓冲区读取的字符串存入buffer字符数组中,且换行符\n不会遗留在输入缓冲区中,被自动舍弃

例:

char buffer[1024];
cin.getline(buffer, sizeof(buffer));

(5)ignore()忽略输入缓冲区的1个字符
ignore(int n)忽略输入缓冲区的多个字符


(6)peek():从输入缓冲区观测并返回1个字符不从输入缓冲区取走字符


(7)putback():将字符放回输入缓冲区的起始位置

示例:输入流对象cin的成员函数

#include <iostream>
using namespace std;

//get():每次只从输入缓冲区读取单个字符(包括换行符)
void func1() {
    
    
	//键盘依次输入:qw(Enter回车)
	//控制台打印:(1)ch = q  (2)ch = w (3)ch =  (4)阻塞:等待下一次输入
	char ch;
	ch = cin.get();
	cout << "ch = " << ch << endl;

	ch = cin.get();
	cout << "ch = " << ch << endl;

	ch = cin.get();
	cout << "ch = " << ch << endl;

	ch = cin.get();
	cout << "ch = " << ch << endl;
}

//get(1个参数):每次只从输入缓冲区读取单个字符(包括换行符)
//`get()`和`get(1个参数)`功能完全相同,仅调用方式不同。
void func2() {
    
    
	//键盘依次输入:qw(Enter回车)
	//控制台打印:(1)ch = q  (2)ch = w (3)ch =  (4)阻塞:等待下一次输入 
	char ch;
	cin.get(ch);
	cout << "ch = " << ch << endl;

	cin.get(ch);
	cout << "ch = " << ch << endl;

	cin.get(ch);
	cout << "ch = " << ch << endl;

	cin.get(ch);
	cout << "ch = " << ch << endl;
}

//get(2个参数):从输入缓冲区读取1行(字符串),并存储至字符数组中,且不清空输入缓冲区。【遗留Enter的换行符】
void func3() {
    
    
	//初始化字符数组
	char buffer[1024] = {
    
     0 };
	cin.get(buffer, sizeof(buffer));	//换行符会遗留在缓冲区
	cout << "buffer = " << buffer << endl;
	
	char ch;
	ch = cin.get();	//取走输入缓冲区的当前字符
	if (ch == '\n') {
    
    
		cout << "Enter的换行符遗留在输入缓冲区" << endl;
	}
	else {
    
    
		cout << "Enter的换行符未遗留在输入缓冲区" << endl;
	}

	//键盘输入:hello
	//控制台打印:
	//buffer = hello
	//Enter的换行符遗留在输入缓冲区
}

//getline(2个参数):从输入缓冲区读取1行(字符串),并存储至字符数组中,且清空输入缓冲区。【自动舍弃Enter的换行符】
void func4() {
    
    
	//初始化字符数组
	char buffer[1024] = {
    
     0 };
	cin.getline(buffer, sizeof(buffer));	//换行符不会遗留在缓冲区
	cout << "buffer = " << buffer << endl;

	char ch;
	ch = cin.get();	//取走输入缓冲区的当前字符
	if (ch == '\n') {
    
    
		cout << "Enter的换行符遗留在输入缓冲区" << endl;
	}
	else {
    
    
		cout << "Enter的换行符未遗留在输入缓冲区" << endl;
	}

	//键盘输入:hello
	//控制台打印:
	//buffer = hello
	//(阻塞:等待下一次输入)
	//Enter的换行符未遗留在输入缓冲区
}

//ignore():忽略输入缓冲区的1个字符。
//ignore(int n):忽略输入缓冲区的n个字符。
void func5() {
    
    
	//键盘输入:qwer
	//控制台打印:ch = r
	cin.ignore(3);	//忽略输入缓冲区的3个字符
	char ch = cin.get();
	cout << "ch = " << ch << endl;
}

//peek():从输入缓冲区观测并返回1个字符,不从输入缓冲区取走字符。
void func6() {
    
    
	//键盘依次输入:qwe
	//控制台打印:(1)ch = q  (2)ch = q (3)ch = w
	char ch = cin.peek();	//观测1个字符
	cout << "ch = " << ch << endl;

	ch = cin.get();
	cout << "ch = " << ch << endl;
	ch = cin.get();
	cout << "ch = " << ch << endl;
}

//putback():将字符放回输入缓冲区的起始位置。
void func7() {
    
    
	cin.putback('x');	//将字符放回输入缓冲区的起始位置
	cin.putback('y');	//将字符放回输入缓冲区的起始位置
	
	char buffer[1024] = {
    
     0 };
	cin.getline(buffer, sizeof(buffer));
	cout << "buffer = " << buffer << endl;

	//键盘输入:hello
	//控制台打印:buffer = yxhello	//依次将字符x、y放回输入缓冲区的起始位置
}

void main() {
    
    
	func7();
}

3 标准输入流案例练习

案例:输入1~10之间的整数,若输入有误则重新输入。
思路
(1)while(true)死循环实现重复输入;
(2)使用整型变量接收键盘输入时,若键入非数字时,会导致程序死循环(string型无法转换为int型),即输入缓冲区异常(标志位异常),需要重置标志位刷新缓冲区

标准输入流对象的成员函数
fail()查看输入缓冲区的标志位,0表示正常,1表示异常。
clear()重置输入缓冲区的标志位为正常状态(0)。
sync():使输入流与对应数据源同步,丢弃之前未处理的数据,刷新并清空输入缓冲区

注:成员函数sync()在Visual Studio 2019中无效,可使用getline()函数手动取走输入缓冲区的内容

示例

#include <iostream>
using namespace std;
#include <string>

void func(){
    
    
	cout << "请输入1~10的整数:" << endl;

	while (true) {
    
    
		int num;
		//当键入string类型时,程序进入死循环(string类型无法转换为int类型)
		cin >> num;

		if (num >= 1 && num <= 10) {
    
    
			cout << "输入正确,整数为:" << num << endl;
			break;	//退出死循环
		}
		cout << "输入有误,请重新输入!" << endl;

		//查看输入缓冲区的标志位(0正常,1异常)
		cout << "输入缓冲区的标志位:" << cin.fail() << endl;

		//1.重置输入缓冲区的标志位为0(正常)
		cin.clear();
		//2.刷新并清空输入缓冲区
		//cin.sync();	//Visual Studio 2019中无效

		//使用cin.getline()手动取走输入缓冲区的内容
		char buffer[1024] = {
    
     0 };
		cin.getline(buffer, sizeof(buffer));
	}
}

void main() {
    
    
	func();
}

4 标准输出流(ostream)

4.1 标准输出流对象cout的成员函数

标准输出流对象cout成员函数,但通常配合左移运算符<<进行输出

(1)flush()刷新输出缓冲区,仅对Linux系统有效。


(2)put():向输出缓冲区中写入单个字符,支持链式编程
函数原型ostream& ostream::put(char ch)


(3)write():向输出缓冲区中写入多个字符
函数原型ostream& ostream::write(const char *buffer, streamsize count)
参数
buffer:向输出缓冲区写入的字符数组。
count:向输出缓冲区写入的字符数组的字符个数。

示例

#include <iostream>
using namespace std;

//put():向输出缓冲区中写入单个字符,支持链式编程
void func1() {
    
    
	cout.put('h').put('e').put('l').put('l').put('o');	//hello
}

//write():向输出缓冲区中写入多个字符
void func2() {
    
    
	char buffer[1024] = "hello world";
	//cout.write(buffer, 3);	//hel
	cout.write(buffer, strlen(buffer));		//hello world
}

void main() {
    
    
	func2();
}

4.2 格式化输出

格式化输出:使数据按指定格式输出数据。通常情况下,由系统根据数据类型采用默认格式进行输出。

C++控制输出格式的2种方式:
(1)使用cout流对象的成员函数,控制输出格式。
示例

/* 控制输出格式:使用流对象的成员函数 */
void func() {
    
    
	int num = 99;
	//设置宽度
	cout.width(5);		//   99
	//设置填充字符
	cout.fill('*');		//***99
	//设置左对齐
	cout.setf(ios::left);	//99***

	//取消十进制
	cout.unsetf(ios::dec);	//99***	
	//设置十六进制
	cout.setf(ios::hex);	//63***
	//设置显式进制的基数
	cout.setf(ios::showbase);	//0x63*
	//取消十六进制
	cout.unsetf(ios::hex);	//99***
	//设置八进制
	cout.setf(ios::oct);	//0143*

	cout << num << endl;
}

(2)使用控制符,控制输出格式,需包含头文件#include <iomanip>
示例

/* 控制输出格式:使用控制符 */
//需包含头文件<iomanip>
void func() {
    
    
	int num = 99;

	cout << setw(5)			//设置宽度	//   99
		<< setfill('*')		//设置填充	//***99
		<< setiosflags(ios::showbase)	//设置显式进制的基数	//***99
		<< setiosflags(ios::left)		//设置左对齐			//99***
		<< hex				//设置十六进制	//0x63*
		<< num << endl;
}

猜你喜欢

转载自blog.csdn.net/newson92/article/details/113875277