c++ 流

目录

流对象与文件

输出流

构造输出流对象的方法

文件输出流成员函数

 操纵符

width:

set: 

对齐: 

设置对齐中的setiosflags操纵符:

输出精度:

向二进制文件输出

向字符串输出

输入流

构造输入流对象的方法

 输入流相关函数

输入流相关函数应用举例

get:

getline:

以二进制形式读文件到另一个结构中:

 用seekg函数设置位置指针:

从字符串输入

两个重要的输入/输出流

fstream类

 stringstream类

流对象与文件

        程序建立一个流对象,当程序与外界环境进行信息交换时,存在两个对象,一个是程序中的对象,另一个是文件对象。流是一种抽象,他负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动

        我们可以指定一个流对象与某个文件对象建立连接,通过程序操作流对象,流对象通过文件系统对所链接的文件对象产生作用

        读操作在流数据抽象中被称为(从流中)提取

        写操作被称为(向流中插入) (网文件中写,比如std::cout往显示器上显示(也可以看做文件))

常用流类表
类名说明包含文件
抽象流基类
ios流基类ios
输入流类
istream通用输入流类和其他输入流的基类istream
ifstream文件输入流类fstream
istringstream字符串输入流类sstream
输出流类
ostream通用输出流类和其他输出流的基类ostream
ofstream文件输出流类

fstream

ostringstream字符串输出流类sstream
输入/输出流类
iostream通用输入/输出流类和其他输入/输出流的基类istream
fstream文件输入/输出流类fstream
stringstream字符串输入/输出流类sstream
流缓冲区类
streambuf抽象流缓冲区基类streambuf
filebuf磁盘文件的流缓冲区类fstream
stringbuf字符串的流缓冲区类sstream

输出流

        最重要的三个输出流: ostream、ofstream、ostringstream

构造输出流对象的方法

//ofstream类支持磁盘文件输出
//如果在构造函数中指定一个文件名,当构造这个对象时改文件是自动打开的
ofstream myFile("filename");

//可以在调用默认构造函数之后使用open成员函数打开文件
ofstream myFile; //声明一个静态文件输出流对象
myFile.open("filename"); // 打开文件,使流对象与文件建立联系

//在构造对象或用open打开文件时可以指定模式
ofstream myFile("filename", ios_base::out | ios_base::binary);

文件输出流成员函数

三种类型

        1.与操纵符等价的成员函数

        2.执行非格式化写操作的成员函数

        3.其他修改流状态且不同于操纵符或插入运算符的成员函数

open函数

        把流与一个特定的磁盘文件夹关联起来

        需要指定打开模式

put函数

        把一个字符写到输出流中

write函数

        把内存中的一块内容写到一个文件输出流中

seekp函数和tellp函数

        操作文件流的内部指针

close函数

        关闭一个与文件输出流关联的磁盘文件

错误处理函数

        在写到一个流时进行错误处理

操纵符

插入运算符与操纵符一起工作

        控制输出格式

很多操纵符都定义在ios_base类中(如hex()、<iomanip>头文件(如setprecision))

可以控制输出流度

        在流中放入setw操纵符或者调用width成员函数为每一项指定输出宽度

setw和width仅影响紧随其后的输出项,但其他流格式操纵符保持有效直到发成改变

dec、oct和hex操纵符设置输入和输出的默认进制

以下是操纵符的使用: 

width:
//例,使用width控制输出宽度
#include <iostream>
using namespace std;

int main(){

	double values[] = {1.23, 35.36, 653.7, 435824};
	
	for(auto it : values){
		cout.width(10);
		cout << values[i] << endl;
	}
	
	return 0;
} 

/*
以上输出结果(每一行宽度为10)
	   1.23
	  35.36
	  653.7
	4358.24 
*/
//例,使用width控制输出宽度 - 写到文件中
#include <fstream>
using namespace std;

int main(){
	
	ofstream tetout("filename");
	
	double values[] = {1.23, 35.36, 653.7, 435824};
	
	for(auto it : values){
		tetout.width(10);
		tetout << values[i] << endl;
	}
	
	txtout.close();
	
	return 0;
} 

/*
以上输出结果(每一行宽度为10)
	   1.23
	  35.36
	  653.7
	4358.24 
*/
set: 
//例,使用set控制输出宽度
#include <iostream>
#include <iomanip> //setw头文件 
#include <string>
using namespace std;

int main(){

	double values[] = {1.23, 35.36, 653.7, 435824};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	for(int i = 0; i < 4; i ++){
		cout << setw(6) << names[i] 
		<< setw(10) << values[i] << endl;
	}
	
	return 0;
} 

/*
以上输出结果
	Zoot	   1.23
   Jimmy	  35.36
	  Al	  653.7
	Stan	4358.24 
*/
//例,使用set控制输出宽度 - 写到文件 
#include <fstream>
#include <iomanip> //setw头文件 
#include <string>
using namespace std;

int main(){

	ofstream txtout("filename");

	double values[] = {1.23, 35.36, 653.7, 435824};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	for(int i = 0; i < 4; i ++){
		txtout << setw(6) << names[i] 
		<< setw(10) << values[i] << endl;
	}
	
	txtout.close();
		
	return 0;
} 

/*
以上输出结果
	Zoot	   1.23
   Jimmy	  35.36
	  Al	  653.7
	Stan	4358.24 
*/
对齐: 
//例,设置对齐方式 
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main(){

	double values[] = {1.23, 35.36, 653.7, 435824};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	for(int i = 0; i < 4; i ++){
		cout << setiosflags(ios_base::left)//左对齐
			<< setw(6) << names[i]
			<< resetiosflags(ios_base::left)
			<< setw(10) << values[i] << endl; 
	}
		
	return 0;
} 

/*
以上输出结果
Zoot        1.23
Jimmy      35.36
Al         653.7
Stan      435824
*/
//例,设置对齐方式 - 写到文件 
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

int main(){

	ofstream txtout("filename"); 

	double values[] = {1.23, 35.36, 653.7, 435824};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	for(int i = 0; i < 4; i ++){
		txtout << setiosflags(ios_base::left)//左对齐
			<< setw(6) << names[i]
			<< resetiosflags(ios_base::left)
			<< setw(10) << values[i] << endl; 
	}
		
	txtout.close();
		
	return 0;
} 

/*
以上输出结果
Zoot        1.23
Jimmy      35.36
Al         653.7
Stan      435824
*/
设置对齐中的setiosflags操纵符:

        上面这个程序中,通过使用带参数的setiosflags操纵符来设置左对齐,setiosflags定义在头文件iomanip中。

        参数ios_base::left是ios_base的静态常量,因此引用时必须包括ios_base::前缀。

        这里的resetiosflags操纵符关闭左对齐标志,setiosflags不同于width和setw,它的影响力是持久的,直到用resetiosflags重新回复默认值为止。

        setiosflags的参数是该流的格式标志值,可用按位或(|)运算符进行组合。

setiosflags的参数(流的格式标识)
ios_base::skipws在输入中跳过空白
ios_base::left左对齐值,用填充字符填充右边
ios_base::right右对齐值,用填充字符填充左边(默认对齐方式)
ios_base::internal在规定的宽度内,指定前缀符号后,数值之前,插入指定的填充字符
ios_base::dec以十进制形式格式化数值(默认进制)
ios_base::oct以八进制形式格式化数值
ios_base::hex以十六进制形式格式化数值
ios_base::showbase插入前缀符号以表明整数的数制
ios_base::showpoint对浮点数值显示小数点和尾部的0
ios_base::uppercase对于十六进制数制显示大写字符A到F,对于科学格式显示大写字母E
ios_base::showpos对于非负数显示正号(“+”)
ios_base::scientific以科学格式显示浮点数值
ios_base::fixed以定点格式显示浮点数值(没有指数部分)
ios_base::unitbuf在每次插入之后转储并清楚缓冲区内容
输出精度:

浮点数输出精度的默认值是6,例如3466.98

要改变精度:setprecision操纵符(定义在头文件<iomanip>)

如果不指定fixed或scientific,精度值表示有效数字位数

如果设置了ios_base::fixed或ios_base::scientific精度值表示小数点之后的位数

//例,控制输出精度 - 未指定fixed或scientific 
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main(){
 
	double values[] = {1.23, 35.36, 653.7, 435824};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	for(int i = 0; i < 4; i ++){
		cout << setiosflags(ios_base::left)
			<< setw(6) << names[i]
			<< resetiosflags(ios_base::left)
			<< setw(10) << setprecision(1) << values[i] << endl; 
	}
		
		
	return 0;
} 

/*
以上输出结果
Zoot           1
Jimmy     4e+001
Al        7e+002
Stan      4e+005
*/
//例,控制输出精度 - 指定fixed
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main(){
 
	double values[] = {1.23, 35.36, 653.7, 4358.24};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	cout << setiosflags(ios_base::fixed);
	for(int i = 0; i < 4; i ++){
		cout << setiosflags(ios_base::left)
			<< setw(6) << names[i]
			<< resetiosflags(ios_base::left)
			<< setw(10) << setprecision(1) << values[i] << endl; 
	}
		
		
	return 0;
} 

/*
以上输出结果
Zoot         1.2
Jimmy       35.4
Al         653.7
Stan      4358.2
*/
//例,控制输出精度 - 指定scientific
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

int main(){
 
	double values[] = {1.23, 35.36, 653.7, 4358.24};
	string names[] = {"Zoot", "Jimmy", "Al", "Stan"};
	
	cout << setiosflags(ios_base::scientific);
	for(int i = 0; i < 4; i ++){
		cout << setiosflags(ios_base::left)
			<< setw(6) << names[i]
			<< resetiosflags(ios_base::left)
			<< setw(10) << setprecision(1) << values[i] << endl; 
	}
		
		
	return 0;
} 

/*
以上输出结果
Zoot    1.2e+000
Jimmy   3.5e+001
Al      6.5e+002
Stan    4.4e+003
*/

向二进制文件输出

二进制文件流:

使用ofstream构造函数中的模式参量指定二进制输出模式

以通常方式构造一个流,然后使用setmode成员函数,在文件打开后改变模式

通过二进制文件输出流对象完成输出

//例,向二进制文件输出 
#include <fstream>
using namespace std;

struct Date{
	int mon, day, year;
};

int main(){
 
	Date dt = {6, 10, 92};
	
	ofstream file("data.dat",ios_base::binary);

	file.write(reinterpret_cast<char*>(&dt), sizeof(dt));
		
	file.close();
		
	return 0;
} 

向字符串输出

将字符串作为输出流的目标,可以实现将其他数据类型转换为字符串的功能

字符串输出流(ostringstream):

用于构造字符串

功能:

        支持ofstream类的除open、close外的所有操作

        str函数可以返回当前已构造的字符串

典型应用

        将数值转换为字符串

//例,用ostringstream将数值转换为字符串 
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

template<class T>
inline string toString(const T &v){
	ostringstream os; //创建字符串输入流
	os << v; //将变量v的值写入字符串流
	return os.str(); //返回输出流生成的字符串 
}

int main(){
 
	string str1 = toString(5);
	cout << str1 << endl;
	string str2 = toString(1.2);
	cout << str2 << endl; 
		
	return 0;
} 

/*
以上输出结果
5
1.2
*/

输入流

重要的输入流类:

        istream类最适合用于顺序文本输入,cin是其实例

        ifstream类支持磁盘文件输入

        istringstream

构造输入流对象的方法

//如果在构造函数中指定一个文件名,当构造这个对象时改文件是自动打开的
ifstream myFile("filename");

//在调用默认构造函数之后使用open成员函数打开文件
ofstream myFile; //建立一个文件流对象
myFile.open("filename"); // 打开文件

//打开文件时可以指定模式
ifstream myFile("filename", ios_base::in | ios_base::binary);

使用提取运算符从文本文件输入:

        提取运算符(>>)对于所有标准c++数据类型都是预先设计好的

        对于自定义数据类型则需要重载>>操作符               

        是从一个输入流对象获取字节最容易的方法

        ios类中的很多操纵符都可以应用于输入流,但是只有少数几个对输入流对象有实际影响,其中最重要的是进制操纵符dec、oct、hex(10,8,16进制)

输入流相关函数

open函数把该流与一个特定磁盘文件相关联

get函数的功能与提取运算符(>>)很像,主要的不同点是get函数在读入数据时包括空白字符

getline的功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从读取内容中删除终止字符

read成员函数从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取

seekg函数用来设置文件输入流中读取数据位置的指针

tellg函数返回当前文件读指针的位置

close函数关闭与一个文件输入流相关联的磁盘文件

输入流相关函数应用举例

get:
//例,get函数的应用 
#include <iostream>
using namespace std;

int main(){
 
	char ch;
	while((ch = cin.get()) != EOF){
		cout.put(ch);
	}//windows系统下结束这个循环Ctrl+Z 
	
	return 0;
} 
getline:
//例,为输入流指定一个终止字符 
#include <iostream>
#include <string>
using namespace std;

int main(){
 
	string line;
	//Type a line terminated by '\t'
	getline(cin, line, '\t');
	cout << line << endl;
	
	return 0;
} 
以二进制形式读文件到另一个结构中:
//例,从文件读一个二进制记录到一个结构中 
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

struct Salarylnfo{
	unsigned id;
	double salary;
};

int main(){
 
	Salarylnfo employee1 = {600001, 8000};
	
	ofstream os("filename", ios_base::binary);
	os.write(reinterpret_cast<char*>(&employee1), sizeof(employee1));
	os.close();	
	
	ifstream is("payroll", ios_base::in | ios_base::binary);
	if(is){
		Salarylnfo employee2;
		is.read(reinterpret_cast<char*>(&employee2), sizeof(employee2));
	} else {
		cout << "ERROR: Cannot open file payroll." << endl;
	}
	is.close();
	
	return 0;
} 
用seekg函数设置位置指针:
//例,用seekg函数设置位置指针 
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

int main(){

	int values[] = {3, 17, 0, 65, 234};
	
	ofstream os("filename", ios_base::out | ios_base::binary);
	os.write(reinterpret_cast<char*>(values), sizeof(values));
	os.close();
	
	ifstream is("integers", ios_base::in | ios_base::binary);
	if(is){
		is.seekg(3*sizeof(int));
		int v;
		is.read(reinterpret_cast<char*>(&v), sizeof(int));
		cout << "The 4th integer in the file 'integers' is" << v << endl;
	} else {
		cout << "ERROR: Cannot open file integers." << endl;
	}
		
	return 0;
} 
 读一个文件并显示出其中0元素的位置:
//例,读一个文件并显示出其中0元素的位置 
#include <iostream>
#include <fstream>
using namespace std;

int main(){

	ifstream file("integers", ios_base::in | ios_base::binary);
	
	if(file){
		while(file) {//读到文件尾file为0 
			streampos here = file.tellg(); 
			int v;
			file.read(reinterpret_cast<char*>(&v), sizeof(int));
			if(file && v == 0)
				cout << "Position" << here << "is 0." << endl;
		}
	} else {
		cout << "Error:Cannot open file 'integers'." << endl;		
	}
	
	file.close();
		
	return 0;
} 

从字符串输入

将字符串作为文本输入流的源,可以将字符串转换为其他数据类型

字符串输入流(istringstream)

用于从字符串读取数据

在构造函数中设置要读取的字符串

功能:

        支持ifstream类的除open、close外的所有操作

典型应用

        将字符串转换为数值

例, 用istringstream将字符串转换为数值 

//例,用istringstream将字符串转换为数值 
#include <iostream>
#include <sstream>
using namespace std;

template <class T>
inline T fromString(const string &str){
	istringstream is(str); //创建字符串输入流
	T v;
	is >> v; //从字符串输入流中读取变量v 
	return v; //返回变量v 
}

int main(){

	int v1 = fromString<int>("5");
	cout << v1 <<endl;
	
	double v2 = fromString<double>("1.2");
	cout << v2 <<endl; 
		
	return 0;
} 

两个重要的输入/输出流

一个iostream对象可以使数据的源或目的

两个重要的I/O流都是从iostream派生的,他们是fstream和stringstream

这些类继承了前面描述的istream和ostream类的功能

fstream类

fstream类支持磁盘文件输入和输出

如果需要在同一个程序中从一个特定磁盘文件读并写到该磁盘文件,可以构造一个fstream对象

一个fstream对象是有两个逻辑子流的单个流,两个子流一个用于输入,一个用于输出

stringstream类

stringstream类支持面向字符串的输入和输出

可以用于对同一个字符串的内容交替读写,同样是由两个逻辑子流构成

本文参考自b站郑莉教授所讲授的视频 算是一篇学习笔记吧

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值