当前位置: 首页 > article >正文

C++练级计划-> 《IO流》iostream fstream sstream详解

如果是想全部过一遍就看完,如果想具体的了解某一个请点目录。因为有三种流的使用可能内容多 

目录

流是什么?

C++IO流(iostream)

io流的注意事项

cin和cout为什么能直接识别出类型和数据

fstream

fstream的使用方法: 

1.以二进制打开文件并写入和读取

2.以文本打开文件并读取或写入

3.用>> << 重载符号读取或写入

sstream

stringstream:

1.提取stringstream流中的数据

2.删除stringstream流中的数据

3.stringstream的常见用法:

4.stringstream能使用的oj题:


流是什么?

首先io流就是iostream,全称 in out stream,输入输出流。

怎么理解流呢?

把它想成一个数据结构(抽象的),里面流动的(存的)是字节流,或者字符流。

字节流就是二进制数据,字符流就是字符数据。二进制数据主要是图片视频等,字符数据就是一个文档全是字的。

 所以流就可以想象成从一个地方拿数据,然后供给另一个地方,南水北调,南边的水,供给北方

这里中间传输的过程就是流。南水放入,北方取出加工使用。

C++IO流

这里的ios_base就是大基类(父类),里面保存的就是每个流都应该有的功能,ios是继承自ios_base的一个类,但是不只是只有一个ios,这里的ios类旨在处理char单字符,而对于wchar这样的宽字符它是无法处理的,所以还有另外一个wios类专门用于处理wchar。

ios就是后面的所有类的基类(父类)

iostream(经常用于屏幕打印数据)

in out stream

cin:流提取(istream),用于从io流中提取数据,比如说读文件、获取键盘的信息等

cout:流插入(ostream),将数据放入io流中,供其他程序提取。比如写文件(将数据写到屏幕上就是打印)

cerr:也是流插入(ostream)。某处出错时,将错误数据放入io流。一般在屏幕打印

clog:也是流插入(ostream)。进行日志的输出,屏幕打印

fstream(文件)

file stream:顾名思义这个流是给文件使用的。

sstream(字符串)

string stream:这个则是给字符串使用的。

io流的注意事项

注意:1.cin是以空格和换行为分隔符的

在使用cin时如果我们在输入时,数据中间加了空格,有人要提取数据,提取到的是空格前的数据。下一次有人又来提取时,这时是先把之前空格后的数据先给出去。

#include <iostream>
using namespace std;
int main()
{
	int a = 0, b = 0;
	cin >> a; //输入:10 20
	cout << a << endl;
	cin >> b; //直接从输入缓冲区提取
	cout << b << endl;
	return 0;
}

如上代码我们输入时输入 10 20,第二次cin时根本不会停下来等你输入数据,而是直接把20给b。然后输出。所以在使用cin时要注意空格的使用

2.输入类型和要输出到的类型必须一致

3.getline函数:用于输入时只把换行当做分隔符。

这个函数只能用于字符串,所以1.中输入数字的情况用不了

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s;
    //cin>>s;          //cin输入,最终只输出hello
	getline(cin, s);   //输入:"hello world"
	cout << s << endl; //输出:"hello world"
	return 0;
}

cin和cout为什么能直接识别出类型和数据

cin重载的>>运算符

 cout重载的<<运算符

在C++标准库中对于内置类型的输入和输出已经全部重载,所以cin和cout能识别类型是这个原因。对于自定义类型而言: class类,在定义类时如果需要使用>> 和 << 需要自己手写接口实现。实现方法对应自己类的功能。

fstream

fstream有三个类和一个filebuf缓冲区

文件流的三个类:

对应操作场景
ofstream只写
ifstream只读
fstream读+写

 文件的打开方式:

打开方式功能
in以读的方式打开文件
out以写的方式打开文件
binary以二进制方式对文件进行操作
ate输出位置从文件的末尾开始
app以追加的方式对文件进行写入
trunc先将文件内容清空再打开文件

文件流的函数:

成员函数功能
put插入一个字符到文件
write插入一段字符到文件
get从文件提取字符
read从文件提取多个字符
tellg获取当前字符在文件当中的位置
seekg设置对文件进行操作的位置
>>运算符重载将数据形象地以“流”的形式进行输入
<<运算符重载将数据形象地以“流”的形式进行输出

fstream的使用方法: 

1.以二进制打开文件并写入和读取

写入文件:

#include <iostream>
#include<fstream>
using namespace std;
void ofsteam_test_binary()
{
	//为什么o是写入,output是输出的意思,意味着我们要从流中输出给文件
	ofstream ofs;
	ofs.open("binoptest.txt", ofstream::binary | ofstream::out);//以二进制写的方式打开文件
	char str[] = "中国无敌";
	ofs.write(str, strlen(str));
	ofs.put('!');//put是单字符的写入
	//使用任何类时都要记得close
	ofs.close();
}
int main()
{
	ofsteam_test_binary();
	return 0;
}

解释:我们创建一个ofstream对象,用二进制out的方式打开文件binoptest.txt,为什么out是输出这里我们要把视角看成是流的视角:流把数据output进了binoptest.txt,所以ofstream是输出流。

结果:

1.在当前目录生成一个binoptest.txt文件 

2.文件内容为:

读取文件:

void ifstream_test_binary()
{
	ifstream ifs;
	ifs.open("binoptest.txt", std::ios::binary | std::ios::in);
	char str[32];
	//计算文档内容的大小
	ifs.seekg(0,std::ios::end);
	int len = ifs.tellg();
	ifs.seekg(0,std::ios::beg);
	//读取文件放入str
	ifs.read(str, len);
	ifs.close();
	//字符串末尾置为0
	str[len] = '\0';
	printf("%s", str);
}

解释:创建ifstream对象,打开文件创建str储存读取出来的数据。

注意:计算文档大小没有什么size函数但是可以用下面的代码

//计算文档内容的大小
	ifs.seekg(0,std::ios::end);
	int len = ifs.tellg();
	ifs.seekg(0,std::ios::beg);

seekg用来定位读指针,第一个参数是偏移量,代表从哪里开始定位,第二个参数是根据偏移量后从哪里开始end代表结尾,beg代表开始,我们一开始就把定位移到了最后,然后tellg是用来计算当前读指针的偏移量的(从头开始计算),然后再让读指针回到beg开始,就完成了一次文档计数

结果 :

2.以文本打开文件并读取或写入

写入文件:

void ofstream_test_text()
{
	ofstream ofs;
	//默认的output方式是文本的
	ofs.open("text.txt");
	char str[] = "中国无敌";
	ofs.write(str, strlen(str));
	ofs.put('!');//put是单字符的写入
	//使用任何类时都要记得close
	ofs.close();
}

 和二进制的区别只是,在open时二进制文件和文本文件不同,open默认打开文件是以文本方式打开的,如果要使用二进制打开就需要设置打开方式。

结果:

读取文件:

void ifstream_test_text()
{
	ifstream ifs;
	ifs.open("text.txt");
	char str[32];
	//计算文档内容的大小
	ifs.seekg(0, std::ios::end);
	int len = ifs.tellg();
	ifs.seekg(0, std::ios::beg);
	//读取文件放入str
	ifs.read(str, len);
	ifs.close();
	//字符串末尾置为0
	str[len] = '\0';
	printf("%s", str);
}

和写入文件一样:和二进制的区别就是open的打开方式。

结果: 

注意:除了指定二进制外,我们还可以指定读和写:默认的情况下:ifstream打开文件是以读的方式,ofstream打开文件是以写的方式打开,而fstream是以读加写的方式打开。

3.用>> << 重载符号读取或写入

写入文件:

void writefile()
{
	ofstream ofs;
	ofs.open("file.text");
	string s = "中国无敌!";
	ofs << s;
}

结果:

读取文件:

void readfile()
{
	ifstream ifs;
	ifs.open("file.text");
	string s;
	ifs >> s;
	cout << s;
	ifs.close();
}

结果:

 

可以看出如果以重载符来写入或者读取时使用方法和cout 和 cin 类似区别只是在于 cout 和 cin的默认设备分别是屏幕和键盘,而我们用文件流的写入和读取,可以自己选择文件。键盘和屏幕也是文件。 

sstream

对应操作场景
ostringstream输出操作
istringstream输入操作
stringstream输入操作+输出操作

介绍一下:sstream 全称 stringstream 字符串流:顾名思义一定和字符串有关,而这里的stringstream就是用来解决字符串转换的问题,在c语言时要进行字符串转换就要用到itoa等函数,在c++中用stringstream就可以完成 

stringstream:

因为用法类似所以这里只介绍stringstream,stringstream是在底层维护了一个字符串,在这个字符串中完成对应的操作,放进这个字符串的数据默认就变成字符了。

1.提取stringstream流中的数据

有两种从流中提取数据的方法:

    s.str(""); //将stringstream底层管理的string对象设置为""。
	s.clear(); //将上次转换状态清空掉

1.使用>>从流中提取

    int a = 10;
	string sa;
	stringstream s;
	s << a; //将int类型的a放入输入流
	s >> sa; //从s中抽取前面插入的int类型的值,赋值给string类型(方式一)
	cout << sa << endl;

2.使用.str()函数的方式提取

    double b = 3.14;
	s << b;
	sa = s.str(); //获取stringstream中管理的string类型(方式二)
	cout << sa << endl;

二者没什么差别>>是将stringstream中的内容通过复制的方式给出,而 .str()是通过 返回一个字符串的方式然后在赋值给出。

2.删除stringstream流中的数据
    s.str(""); //将stringstream底层管理的string对象设置为""。
	s.clear(); //将上次转换状态清空掉

上面的代码,首先将stringstream中的字符串给变为空字符串,然后用clear函数将状态清空。关于这个状态又是一个知识点:

stringstream底层在一次转换完成后会把标志位记成badbit这时代表的是流不可转换数据,使用clear后变成goodbit流才可转换。但是clear只是更改标记位而不会对内置的字符串进行更改所以这时需要将str置为空。

3.stringstream的常见用法:

1.将数据转换为字符类型

    int a = 10;
	string sa;
	stringstream s;
	s << a; //将int类型的a放入输入流
	s >> sa; //从s中抽取前面插入的int类型的值,赋值给string类型(方式一)
	cout << sa << endl;

2.字符串的拼接

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
	string rets;
	stringstream s;
	s << "2021" << "dragon"; //将多个字符串放入stringstream中
	s >> rets; //方式一获取
	cout << rets << endl;
	s.str(""); //将stringstream底层管理的string对象设置为空字符串
	s.clear(); //将上次转换状态清空掉
	s << "Thanks" << " " << "for" << " " << "reading"; //将多个字符串放入stringstream中
	rets = s.str(); //方式二获取
	cout << rets << endl;
	return 0;
}
4.stringstream能使用的面试题:

1.统计字符串的个数

输入:“hello world c plus plus”
输出:5

#include <iostream>
#include <sstream>
#include <string>
 
using namespace std;
 
int main() {
	string str = "hello world c plus plus";
	int count = 0;
	stringstream ss(str);
	string word;
	while (ss >> word)
		count++;
	cout << count << endl;
	return 0;
}

很简单因为使用 >> 符号是以空格或者换行为分割符的,所以只要统计总共有几次输入进流中即可。 

2.反转字符串中的单词

class Solution {
public:
    string reverseWords(string s) 
    {
         string res,temp;
         stringstream ss(s);
         while(ss>>temp)
         {
            cout<<temp<<endl;
            res = temp + " " + res;
         }
         if(!res.empty())
         {
            res.pop_back();
         }
         return res;
    }
};

这题也很简单,将s 传入 ss的构造函数中,这时ss的底层里保存的就是s。此时通过>>流提取符号放入temp中,将数据类似头插的方法将temp放到res前面最后再把最后的空格删除。从这里也可以看出stringstream的>> 流插入符号是从字符串头的位置开始插入的,所以才能让temp中每次只出现一个字符串。


http://www.kler.cn/a/414620.html

相关文章:

  • sqlmap使用过程中的每个步骤及其相关命令
  • Harbor安装、HTTPS配置、修改端口后不可访问?
  • 乐鑫发布 esp-iot-solution v2.0 版本
  • ubuntu20.04更换安装高版本CUDA以及多个CUDA版本管理
  • @[TOC](【接口调试】OpenAI ChatGPT API)
  • PL/I语言的起源?Objective C语言起源哪里?JavaScript的起源?Java的起源?B语言的起源?C++语言的起源?C#的起源?
  • 操作系统 | 学习笔记 | 王道 | 2.1 进程与线程
  • 若依前端报错 components.at is not a function
  • JVM(JAVA虚拟机)内存溢出导致内存不足,Java运行时环境无法继续
  • 外卖点餐系统小程序
  • LeetCode --- 424周赛
  • 光伏功率预测!Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN五模型时序预测
  • Springboot项目搭建(7)-Layout界面布局
  • Vue.js - axios网络请求
  • C/C++ 中volatile 关键字
  • 【DERPNSTINK靶场渗透】
  • [在线实验]-Redis Docker镜像的下载与部署
  • C++中智能指针的使用及其原理 -- RAII,内存泄漏,shared_ptr,unique_ptr,weak_ptr
  • vue安装cypress及其部分用法
  • 基于C#+SQLite开发数据库应用的示例
  • 从传统IT运维到智能化运维的转型之路
  • 数据结构 (10)队列
  • linux基础2
  • 分布式搜索引擎Elasticsearch(一)
  • golang每日一题:context、goroutine相关
  • 【Ubuntu 24.04】How to Install and Use NVM