c++游戏小技巧12:输入输出流(存读档超全版)

news2024/10/7 19:19:30

目录

1.前言

2.输入/输出概念

3.流的概念

4.正文

1.标准I/O流

1.get()函数

 2.getline()函数

3.read()函数 

4.ignore()函数

5.gcount()函数

6.peek()函数

7.putback()函数

8.istream集合栗子

9.put()函数

10.write()函数

11.ostream集合栗子

2.文件I/O流

1.流的关闭

2.缓冲区类型

3.设置缓冲区属性

4.缓冲区清空

5.文件结尾检查

6.clearerr()

7.rewind()

8.fgetpos

3.格式化输入输出

格式化输出函数 : 

格式化输入函数:

基于字符的输出

基于字符的输入

基于行的输出

基于行的输入

4.文件存读档

1.freopen()

2.格式化输入输出

3.fstream

5.后文

1.前言

(os:之前技巧1里面提到过用输出输出流进行存档的方法的,但今天来详解一下)

(os:与游戏的关联不大呀!)

∴这一章更多是干货,虽然不好理解(毕竟写文章时zzb的精神状态已经快被搞崩了)

∵zzb是蒟蒻

∴有问题(估计应该会有)尽管提出,zzb会来改正

2.输入/输出概念

c++将输入输出分为三类:

标准I/O 文件I/O 字符串I/O

精确一点:

(1)ifstream类:文件输入流类,支持文件的读操作。

(2)istringstream类:字符串输入流类,支持字符串的输入操作。

(3)ofstream类:文件输出流类,支持文件的写操作。

(4)ostringstream类:字符串输出流类,支持字符串的输出操作。

(5)fstream类:文件输入/输出流类,支持文件的读写操作。

(6)stringstream类:字符串输入/输出流类,支持字符串的输入和输出操作。

3.流的概念

(百度百科)

流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向。流不但可以处理文件,还可以处理动态内存、网络数据等多种数据形式。

(懂了这些,就来讲正文)

4.正文

1.标准I/O流

对象名所属类对应设备含义是否有缓冲
cinistream键盘标准输入yes
coutostream屏幕标准输出yes
cerrostream屏幕标准错误输出no
clogostream屏幕标准错误输出yes

(哦对了,插一句,可以用 fflush(stdin与stdout)清空缓冲 )

 首先很明确,标准输入流,“存在”于

#include<iostream>

当你打开iostream,在翻译一下时:

 再精准一点

所以就去

#include<istream>

里转一转

果然有发现:有一堆右移的重载

 此时,>>操作符(或者说析取器)可用于从缓冲区提取数据并存储在变量中。

(而<<操作符(插入器)也一样,有兴趣可以去看一下.

so,我们也可以手写cin

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

int main()
{
    filebuf buf;
    if(buf.open("/proc/self/fd/0",ios::in)==nullptr)
    {
        cout<<"打开文件出错"<<endl;
        return -1;
    }
    istream is(&buf);
    char c=0x00;
    int i=0;
    is>>c>>i;
    cout<<"c="<<c<<endl<<"i="<<i<<endl;
    return 0;
}

而标准输入输出流也有很多东西······

1.get()函数

get()函数用于从输入流中读取单个字符或多个字符,istream类重载了多个get()函数。

 2.getline()函数

getline()函数用于从输入流中读取字符,直到读取到指定长度的字符或遇到终止字符时结束读取。getline()有两种重载形式。

3.read()函数 

read()函数用于从输入流中读取指定字符个数的字符串。

除此之外,还有:

4.ignore()函数

ignore()函数的作用是跳过输入流中的n个字符

5.gcount()函数

gcount()函数的作用是计算上一次读取到的字符个数

6.peek()函数

peek()函数的作用是检测输入流中待读取的字符

7.putback()函数

putback()函数的作用是将上一次读取的字符放回输入流中,使之可被下一次读取(想想你感冒时的鼻子)

 (这肯定要来一个大栗子)

8.istream集合栗子

全是栗子

#include<windows.h>
#include<bits/stdc++.h>
using namespace std;

int ans;
char ch,s[5];

int main()
{
	//get
	printf("请输入一个字符\n");
	ans=cin.get();
	printf("你输入的是: %c\n",char(ans));
    cin.get();
    printf("请输入任意字符(enter结束)\n"); 
    while(1)
	{
        cin.get();
        if(ch!=13) break;
    }
    fflush(stdin);
    //getline
    printf("请输入一个长度<=5的字符串:\n");
    cin.getline(s,5);
    for(int num:s) cout<<num<<" ";
    printf("\n输入一个长度<=5的字符串(以6结束)\n"); 
	cin.getline(s,5,'6');
    for(int num:s) cout<<num<<" ";
    //read
    fflush(stdin);
	fflush(stdout); 
    printf("\n请输入一个字符串(zzb将为你保留前五个):\n");
    cin.read(s,5);
    for(auto num:s) cout<<num;
    //idnore 
    fflush(stdin);
    printf("\n请输入一个长度为8的字符串(zzb将跳过前6个,跳过时遇T停止):\n");
	cin.ignore(6,'T');//跳过前面6个字符,遇到字符'T'终止跳跃
	cin.getline(s,8);//跳跃结束,读取7个字符并存储到s中 
	cout<<s<<endl;
	//gcount
	fflush(stdin);
	printf("请输入一个长度<=20的字符串,zzb将输出你输入的字符个数:\n");
	cin.getline(s,20);//读取字符串并存储到s中
	ans=cin.gcount();//统计上次读取的字符个数
	printf("字符个数(算上回车):%d\n",ans);
	//peek
	fflush(stdin);
	printf("请输入一个字符\n");
    ch=cin.peek();//检测字符
    printf("此时,输入流里%c待输入\n",ch);
    //putback
    fflush(stdin);
	printf("请输入一个字符(zzb将把ta读取后放回输入流再次读取)\n");
	ch=cin.get();
	printf("你输入的是:%c\n",ch); 
	cin.putback(ch);//将字符重新放回输入流
	printf("再读取一遍:%c\n",cin.get());
	printf("\n-----end-----");
    return 0;
}

9.put()函数

put()函数用于输出单个字符。put()函数将字符插入输出流对象,通过输出流对象将字符输出到指定位置。

10.write()函数

write()函数用于输出一个字符串。write()函数将指定个数的字符串插入输出流对象,通过输出流对象将字符串输出到指定位置。

11.ostream集合栗子

(很水了)

#include<windows.h>
#include<bits/stdc++.h>
using namespace std;

int ans;
char ch,s[5];

int main()
{
	cout.put('a');//输出字符'a' 
	cout.put('\n');//输出换行符 
	cout.put('z').put('z').put('b').put('\n');//连续调用
	cout.write("zzb     zzb",4);//输出前3个 
	cout.write("isisisis",2).write(" good.jsafdaosda",6);//连续调用 
    return 0;
}

2.文件I/O流

C++根据文件内容的数据格式分为二进制文件文本文件。采用文件流对象操作文件的一般步骤:

  • 定义一个文件流对象
    • ifstream ifile(只输入用)
    • ofstream ofile(只输出用)
    • fstream iofile(既输入又输出用)
  • 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系
  • 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
  • 关闭文件

⚡️ 对于二进制的读写:读写简单,高效快捷,但是缺点是除了字符和字符串,其他的类型从内存中写到文件的时候都是乱码。

文件常见的打开方式 :
(1). in 以读的方式打开文件
(2). out 以写的方式打开文件
(3). binary 以二进制方式对文件进行操作
(4). ate 输出位置从文件的末尾开始
(5). app 以追加的方式对文件进行写入
(6). trunc 先将文件内容清空再打开文件

常用成员函数
(1). put 插入一个字符到文件
(2). write 插入一段字符到文件
(3). get 从文件提取字符
(4). read 从文件提取多个字符
(5). tellg 获取当前字符在文件当中的位置
(6). seekg 设置对文件进行操作的位置
(7). >>运算符重载 将数据以“流”的形式进行输入(用于文本文件)
(8). <<运算符重载 将数据以“流”的形式进行输出(用于文本文件)

 所以呢?

(看似很复杂,但实在不行用cin cout 也不是不行)

so?

流的操作

1.流的关闭

很简单也很水

fclose(FILE *fp);//FILE,文件句柄,后面有写法,当然stdin与stdout也可以

2.缓冲区类型

  1. 全缓冲区
  2. 行缓冲区

具体定义不用过度记

大概知道全缓冲区是填满缓冲区再I/O

行缓冲区是遇' \textbackslash n '再I/O

(缓冲区默认128字节)

3.设置缓冲区属性

#include<cstdio>//头文件是这个 
using namespace std;

int main()
{
	setbuf(FILE *fp,char *buf);//fp前面技巧9讲过,buf是设置的指针,作用:改为全缓/无缓
	setbuffer(FILE *fp,char *buf,size_t size);//同setbuf,但可以更改缓冲区大小
	setlinebuf(FILE *buf);//改成行缓
	setvbuf(FILE *fp,char *buf,int mode,size_t size);//可以制定缓冲(mode)
	/*
	_IOFBF(全缓冲类型)
	_IOLBF(行缓冲类型)
	_IONBF(无缓冲类型 )
	建议在流打开还没操作前转换
	不然可能被虫子(bug)咬死 
	*/ 
    return 0;
}

4.缓冲区清空

前面讲到过

fflush(FILE *fp);

5.文件结尾检查

feof(FILE *fp);

feof函数用来检测是否读到文件的结尾,当没有访问到文件的结尾时,返回为0,当访问到文件的结尾时,返回为1,只有执行读操作时候才对文件结束标志进行操作。

ferror(FILE *fp);

ferror函数用来检测是否出现了读写错误,当访问正常接收时候,函数返回值为0,当访问非正常结束时,返回值为非0,并设置errno的值。此时errno的值为错误发生时由读写函数本身所设定的。

6.clearerr()

clearer(FILE *fp)

7.rewind()

rewind(FILE *stream)

重新指定流的开头

8.fgetpos

fgetpos(FILE *stream)

取得当前文件的句柄

3.格式化输入输出

(==王炸)

格式化输出函数 : 

(1) int printf(const *format,…);
(2) int fprintf(FILE *fp,const char *format,…);//可以直接用fp输入进文件里 
(3) int sprintf(char *str,const char *format,…);
(4) int snprintf(char *str,size_t size,const format,…);
(5) int vprintf(const *format,va_list ap);
(6) int vfprintf(FILE *fp,const char *format, va_list ap);//理论这个也可以,但没有用过 
(7) int vsprintf(char *str,const char *format, va_list ap);
(8) int vsnprintf(char *str,size_t size,const format, va_list ap);

格式化输入函数:

(1) int scanf(const char *format,…);
(2) int fscanf(FILE *fp,const char *format,…);//可以直接从文件里提出来 
(3) int vsscanf(char *str,const char *format,…);
(4) int vscanf(const char *format, va_list ap);
(5) int vfscanf(FILE *fp,const char *format, va_list ap);//同vfprintf 
(6) int vsscanf(char *str,const char *format, va_list ap);

基于字符的输出

(1)int fputc(int c,FILE *fp);//c表示要输出的字符,同样"应该"可以直接输入进文件里 
(2)int putc(int c,FILE *fp);//同上 
(3)int putchar(int c);

基于字符的输入

(4)int fgetc(FILE *fp);//应该可以直接从文件里读入
(5)int getc(FILE *fp);//应该可以直接从文件里读入
(6)int getchar(void);// getc比调用fgetc消耗时间少,但 getc的参数是不能有副作用的表达式,而fgetc可以

基于行的输出

(1) int fputs(const char *str,FILE *fp);//理论上可以直接输出进文件里 
(2) int puts(const char *str);


基于行的输入

(1) char *fgets(char *str,int size, FILE *fp);//理论上可以直接从文件里读入 
(2) char *gets(char *str);

流的操作讲完后

文件存读档也给一下吧······

4.文件存读档

1.freopen()

OIer的心头之恨呀!

写法·····简单快捷:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	freopen("输入文件名.类型","操作方式",stdin);
	freopen("输出文件名.类型","操作方式",stdout);
	/*
	操作 
	*/
    return 0;
}

(os:操作方式多种多样,给一下:)

type文件类型是否新建是否清空可读可写读写位置
r文本文件NONOYESNO文件开头
r+文本文件NONOYESYES文件开头
w文本文件YESYESNOYES文件开头
w+文本文件YESYESYESYES文件开头
a文本文件NONONOYES文件结尾
a+文本文件YESNOYESYES文件结尾
rb二进制文件NONOYESNO文件开头
r+b或rb+二进制文件NONOYESYES文件开头
wb二进制文件YESYESNOYES文件开头
w+b或wb+二进制文件YESYESYESYES文件开头
ab二进制文件NONONOYES文件结尾
a+b或ab+二进制文件YESNOYESYES文件结尾

(同为颓废人,建议类型用txt,操作方式不要太离谱(比如a))

2.格式化输入输出

有很多(但不知道都能不能用)

int fprintf(FILE *fp,const char *format,…);
int vfprintf(FILE *fp,const char *format, va_list ap);
int fscanf(FILE *fp,const char *format,…);
int vfscanf(FILE *fp,const char *format, va_list ap);
int fputc(int c,FILE *fp);
int putc(int c,FILE *fp); 
int fgetc(FILE *fp);
int getc(FILE *fp);

(等等,不会有人不会搞fp吧······)

fp写法:

FILE* fp=fopen("名字.类型","操作方式");

所以统一叫做fopen写法吧······

给个栗子

void cd(void)
{
    FILE* fp = fopen("名字.txt","wb");
    fprintf(fp,"%d",变量名);
    fclose(fp);
}

void dd(void)
{
	FILE* fp = fopen("名字.txt","rb");
    if(fp != NULL)
	{
        fscanf(fp,"%d",&变量名);
        fclose(fp);
    }
	else
	{
        cd();
        return;
    }
}

3.fstream

仍然是4件套:

创建流,打开文件,读写,关闭流

#include<bits/stdc++.h>
using namespace std;

int main()
{
	ifstream  fin;//创建流 
	ofstream fout;
	
	//打开流
	/*
	ios::in 读文件
	ios::out 写文件,直接用会丢弃已有数据,即隐含为trunc
	ios::binary 二进制方式
	ios:app 追加写,要配合out使用,直接写会隐含用ios::out
	ios::trunc 覆盖写,要配合out使用
	ios::out|ios::binary 二进制写
	*/
	
//	fin.open("路径/名字.类型",ios::app|ios::out);//这样配合
//	如 
	fout.open("D:/z_z_b.txt",ios::out);
	fin.open("D:/z_z_b.txt",ios::in);
	//写数据
	fout<<"zzb好帅!"<<endl;
	//读数据 
	
	//判断 
	if(!fin.is_open()) std::cerr<<"cannot open the file";
	//或者
	if(!fin) std::cerr<<"cannot open the file";
	else
	{
		string k;
		fin>>k;
		//当然,也可以换变量类型
		//同时,fin.getline(s,sizeof(s))  c=fin.get() 都可以 
		cout<<k<<endl;
	}
	
	fout.close();
	fin.close();
	return 0;
}

5.后文

那么这一篇基本就完了

(写了这么多,能不能给个赞呢?)

上一篇:c++游戏小技巧11:goto_L('ω')┘脏脏包└('ω')」的博客-CSDN博客

下一篇:未完待续······

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/878220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开机时间分析

一、 开机各个阶段分析 1、Bootloader 阶段 Bootloader 阶段 该阶段分为(preloader 和Ik 阶段&#xff09; 从按电源键振动到 kernel 开始启动&#xff0c;这部分高通平台暂无好的方法确认时间&#xff0c;可以从总时间推算大概时间。MTK 项目可以从bootprof 确认 2、kernel…

day18 内部类、包、垃圾回收机制

匿名内部类 // Animal a new Animal(){ // Override // public void eat() { // System.out.println("动物在吃饭"); // } // }; abstract class Animal{ public abstract void eat(); }

git 配置网络代理

提高 git 访问 github 速度 网络代理前提: 请开启代理&#xff08;梯子&#xff09;检查代理端口&#xff08;可能会有所不同&#xff09; 文章目录 1. git 配置参数列表命令&#xff1a;2. git 添加 http 代理3. git 取消 http 代理 1. git 配置参数列表命令&#xff1a; gi…

【AI】《动手学-深度学习-PyTorch版》笔记(十八):卷积神经网络模型

AI学习目录汇总 1、LeNet 1.1 介绍 发布时间:1989年 模型目的:识别手写数字 1.2 网络结构 1.3 定义模型 1.3.1 相关函数原型 1)nn.Conv2d:卷积层 torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, paddin

集群、负载均衡集群、高可用集群简介,LVS模式和haproxy/nginx模式拓扑介绍

一.集群的定义 1.定义 2.分类 &#xff08;1&#xff09;负载均衡集群 &#xff08;2&#xff09;高可用集群 二.使用集群的意义 1.高性价比和性能比 2.高可用性 3.可伸缩性强 4.持久和透明性高 三.常见的两种集群模式拓扑 1.LVS集群模式 2.haproxy/nginx模式 四.常…

Java并发编程(六)线程池[Executor体系]

概述 在处理大量任务时,重复利用线程可以提高程序执行效率,因此线程池应运而生。 它是一种重用线程的机制,可以有效降低内存资源消耗提高响应速度。当任务到达时&#xff0c;任务可以不需要的等到线程创建就能立即执行线程池可以帮助我们更好地管理线程的生命周期和资源使用,…

Jmeter-压力测试工具

文章目录 Jmeter快速入门1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1s内发送大量请求&#xff0c;模拟高QPS&#xff0c;用以测试网站能承受的压力有多大 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0…

DAY2,ARM(特殊功能寄存器,数据操作指令,跳转指令)

1.cmp、sub、b指令的使用&#xff1b; 代码&#xff1a; .text .global _start _start:mov r0,#9mov r1,#15b funfun:cmp r0,r1beq stopsubcc r1,r1,r0subhi r0,r0,r1b funstop:b stop .end结果&#xff1a; 2.汇编指令计算1~100之间和&#xff1b; 代码&#xff1a; .text …

echart 词云图

const graphOut ref(null); const optionGraph reactive({series: [{type: graph,shape: circle,symbolSize: [215, 50],//散点形状设置symbol: circle’, ‘rect’, ‘roundRect’, ‘triangle’, ‘diamond’, ‘pin’, arrow’symbol: rect,layout: force,force: {repulsio…

Docker安装elasticsearch分布式搜索

文章目录 ☀️安装elasticsearch☀️1.部署单点es&#x1f338;1.1.创建网络&#x1f338;1.2.下载镜像&#x1f338;1.3.运行 ☀️2.部署kibana&#x1f338;2.1.部署&#x1f338;2.2.DevTools ☀️3.安装IK分词器&#x1f338;3.1.在线安装ik插件&#xff08;较慢&#xff0…

逗号操作符

逗号表达式&#xff0c;就是用逗号隔开的多个表达式。 逗号表达式&#xff0c;从左向右依次执行。整个表达式的结果是最后一个表达式的结果。 运用&#xff1a;

【字典学习+稀疏编码Sparse Encoding】简单介绍与sklearn的实现方式

文章目录 1、字典学习与稀疏编码2、sklearn的实现3、示例 1、字典学习与稀疏编码 简单来说&#xff0c;稀疏编码就是把输入向量&#xff08;信号&#xff09;/ 矩阵&#xff08;图像&#xff09;表示为稀疏的系数向量和一组超完备基向量&#xff08;字典&#xff09;的线性组合…

BeanFactory与Applicationcontext(1)

BeanFactory是接口&#xff0c;提供了IOC容器最基本的形式&#xff0c;给具体的IOC容器的实现提供了规范。BeanFactory是spring的“心脏”&#xff0c;核心容器&#xff0c;它也是Applicationcontext的父接口。 BeanFactory实质上并未提供过多的方法&#xff0c;spring容器的I…

Mr. Cappuccino的第63杯咖啡——Spring之AnnotationConfigApplicationContext源码分析

Spring之AnnotationConfigApplicationContext源码分析 源码分析 源码分析 以上一篇文章《Spring之Bean的生命周期》的代码进行源码分析 AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig02.class); LifeCycleBe…

通达信接口调用过程需要借助什么?

通达信接口是一种用于获取、传输和处理股票市场相关数据的软件接口&#xff0c;以提供了一种连接股票市场数据源和数据使用者之间的通道&#xff0c;允许开发者通过编程方式获取股票行情数据、交易数据和相关信息等。如果调用通达信接口&#xff0c;需要借助以下几个方面的工具…

9-AJAX-1入门

AJAX 目录 AJAX 概念和 axios 使用认识 URLURL 查询参数常用请求方法和数据提交HTTP协议-报文接口文档案例 - 用户登录form-serialize 插件 01.AJAX 概念和 axios 使用 目标 了解 AJAX 概念并掌握 axios 库基本使用 讲解 什么是 AJAX ? mdn 使用浏览器的 XMLHttpRequest…

前后端分离------后端创建笔记(06)新增接口页面布局

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

[PyTorch][chapter 50][创建自己的数据集 2]

前言&#xff1a; 这里主要针对图像数据进行预处理.定义了一个 class Pokemon(Dataset) 类&#xff0c;实现 图像数据集加载,划分的基本方法. 目录&#xff1a; 整体框架 __init__ load_images save_csv divide_data __len__ denormalize __g…

[NepCTF 2023] crypto 复现

这个赛很不理想&#xff0c;啥都不会。 拿了WP看了几个题&#xff0c;记录一下 random_RSA 这题不会是正常情况&#xff0c;我认为。对于论文题&#xff0c;不知道就是不知道&#xff0c;基本没有可能自己去完成论文。 题目不长&#xff0c;只有两个菜单&#xff0c;共可交…

Springboot 在 redis 中使用 BloomFilter 布隆过滤器机制

一、导入SpringBoot依赖 在pom.xml文件中&#xff0c;引入Spring Boot和Redis相关依赖 <!-- Google Guava 使用google的guava布隆过滤器实现--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><vers…