C语言文件操作(2) “流”的拓展介绍

news2024/9/20 15:06:43

tips

1.  打开一个文件 ->  内存里面就会创建一个对应关联的文件信息区 -> 文件信息区其实就是一个FILE类型的结构体 -> 各个结构体成员记录了该文件的种种信息 -> 结构体(文件信息区)由FILE* 结构体指针来维护 -> 有了指针,一切都好说了

2. 使用文件可以让我们的数据持久化存储,存起来之后无论以后程序关掉电脑关机,下一次重新运行起来,文件数据还在。
3. 电脑硬盘上所放的这些文件就被称为文件。
4. 文件指针非常重要,每次打开一个文件,就会在内存中开辟一个与这个文件关联对应的文件信息区,这个文件信息区用来存放文件的相关信息,说白了它也没什么高级的,就是一个结构体变量,类型为FILE(由系统来声明),本质上就是一个结构体,用来描述文件信息的。
5. fopen需要交代文件名与打开方式。如果正确打开,返回一个结构体指针(指向打开文件相关联的文件信息区在内存中的地址,维护文件信息区的),有了指针之后,就可以进行操作。打开失败会返回NULL,可以去判断一下。
6.当要关闭文件的时候,用fclose,关闭后指针置空。 

7. scanf与printf是只能针对标准输入输出流的 


 “流FILE” / “(外部)输出设备” / “维护流的指针FILE*

1. 什么叫“流”呢?你可以想象成水流。
2. 我们在内存中有数据的时候,这些数据我肯定要输出出来,我们可以打印在屏幕上,我们可以写在文件里面去,也可以放到网络上去,也可以放在硬盘网盘软盘上等其他介质上面,我们把这些叫做输出设备

未完................... 


补充:内存与输入输出/读写的关系 

 

输入输出/读写都是站在内存/程序的角度 

1. 我们写的是程序,程序是载入到内存中的,程序的数据都是存放在内存里面的。
2. 如果我们
     要将内存中的数据打印在屏幕上,叫:输出/写数据。
     要将输入缓冲区(对接键盘)的数据放入内存,叫:输入/读数据。
     要将内存的数据放入文件里面,叫:输出/写。 
     要将文件的数据放入内存中,叫:输入/读。


3. 未来我们的内存中的数据可能会输出到不同的各种各样的输出设备上去。我们内存数据打印在屏幕上,或者放在文件里或者放在网络上等等,这些各自的方式方法肯定都不一样,但是我们写C程序的时候,难道我们给这些外部输出设备(文件啊,甚至打印机啊等等)从内存输出数据的方式我都要一一懂吗?如果各种各样外部输出设备读写方式我都要懂的话,对我来说太复杂了。

4. 这个时候我们就不关心外部输出设备了,C语言在这中间呢抽象出“流”这样一个概念,就像一个蓄水池一样,C语言你呢只要关心我把数据放到这个“流”里面去就可以了至于说这些内存数据是如何到什么文件啊,屏幕啊,打印机啊,网络啊,各种盘啊什么的,不要关心,由C语言帮你分装,所有的这些内存里面要输出的数据我通通放到流里面去就OK了,这样大大简化了C语言程序员写代码的难度。

5. 这个流的类型就是FILE这样一个结构体。这个流其实就是由我们的FILE*stream指针来管理的

流相当于是一个FILE类型的结构体,然后FILE*相当于是维护流的一个指针 

内存(程序就是载入到内存)与外部输出设备的关系

1. 任何一个C语言程序运行的时候,默认会打开三个流:stdin(标准输入), stdout(标准输出), stderr(标准错误)stdin, stdout, stderr就是三个管理标准输入流,标准输出流,标注错误流的FILE*指针

2. 这个stdin针对的外部设备就是键盘,这个stdout针对的就是屏幕,stderr也是针对的屏幕。这三个管理流的指针的类型都是FILE*(流就可以理解为FILE类型的结构体) 

3. 这也是为什么我每次从键盘上读取数据,从屏幕上打印信息,我们什么也不关心,直接无脑printf printf scanf scanf,那么因为已经默认打开了这三个流stdin,stdout stderr(标准流)。

4. 除了这三个C语言本身默认打开的流以外,如果说内存数据要输出到文件里面,你要去看看针对文件的流有没有被打开, 如果说内存数据要输出到网络里面,你要去看看针对网络的流有没有被打开, 如果说内存数据要输出到软盘里面,你要去看看针对软盘的流有没有被打开........ 

内存(程序就是载入到内存)与文件的关系 

1. 但是对于文件这个流来说,C语言是没有默认打开这个流的

2. 我们在操作文件的时候,首先要打开文件拥有这个流

3. 打开文件就好比打开了(没有被C语言默认打开的)针对文件的流,fopen()返回的FILE*指针与维护流的指针是一个道理

4. 打开了这个流就可以对文件输入输出数据了。
5. 这个流与我们打开文件的FILE*文件指针是一个道理的


有了上面有关于流的认识与内存->输出设备(尤其是文件)的关系认识之后........ 我们就来了解一下文件的顺序读写

读写的时候有两大类读写方式:一种是文件的顺序读写;另一种是文件的随机读写,顺序读写都是按照一定的顺序去读写的

要想真正掌握这些函数:只需要抓住一根主线: 


字符输出 fputc()     适用于所有输出流 

 

1. fputc是一个字符一个字符去写进去文件,可以考虑循环。

2. 并且下一个写进去的字符是跟在前一个写进去的字符的屁股后面,像这样子有顺序的一直往后写,不会这儿写一个,那儿写一个这样子乱写,所以也叫顺序读写。

3.  

字符输入 fgetc()     适用于所有输入流 


1. 读的时候道理一样,用函数fgetc去读字符,也是一个一个单独地这么去读.

2. fgets返回的是此次读到的那个字符的ASCII值。可以接受一下,用printf%c打印出来。

3. 当文件里面有多个字符的时候,我们用fgetc一个个去读取,此时定位文件位置的指针在fgetc每次读取完一次之后,就会后移一个字节往后走了一步指到下一个字符去了,因此fgetc一个个读取的话不需要顾虑太多,每次读取的时候只需要传参同一个FILE*结构体指针(事实上你其他的也传不了)
(注:以w的形式打开文件,然后写入,文件里面的相关信息会被销毁与覆盖,重新写)   

1. fgetc与fputc是针对字符的,读一个字符或者写一个字符。
2. fgetc如果读取成功,那么读取的字符的ASCII码值就会被返回,若读取失败,EOF就会被返回。
3. fputc的返回内容与fgetc雷同。
4. 字符与ASCII码要灵活转化,不要太死板。 


文本行(一行字符串)输出  fputs()        适用于所有输出流

1. fputs有两个参数,一个是字符串的首字符的地址,一个是要写进去的文件对应的文件信息区的文件指针。
2. 字符串常量=字符串首字符的地址。
3. 多个fputs使用写字符串进去的时候,如果你想要在互相之间有换行,fputs是不会自己给你弄的,你自己在写入字符串的时候就要自己输入\n换行符。

  

文本行(一行字符串)输入  fgets()        适用于所有输入流 

1. fgets参数有文件指针,还有char* str字符指针(这个就是说把从文件指针指向的文件信息区对应的文件里面读取到的东西拷贝到哪里),还有num(这个就是说在读取文件的时候读取多少个字符)
2. 读取的时候要考虑一下\0,当你写参数说给我读五个字符,而真正发现屏幕上就只有4个字符,是因为它硬要在你的末尾放上一个\0,导致占用了你一个字符。因此,以后你想要读取5个的时候,你就写6就OK了,其他道理一样的。
3. 读取字符串的时候,空格也属于一个字符
4. 注意:这两个函数是只处理一行的,一行处理完了之后我就不会继续去处理下一行的,下一行与我一点关系没有。反正我只处理一行。
5. 并且如果我在读的时候碰着了\n(我们上面的fputs函数能写\n进去的从而导致换行),那么我也就直接换行了。  


格式化输出   fprintf()       适用于所有输出流 

1. fprintf写入数据的话是带有格式化的数据
2. 对于fprintf与printf是非常类似的,我们去看一下它们的函数原型,发现参数里面后面有... ,这个东西其实比较奇怪的,叫做“可变参数列表"。其实也没有什么高级的,我们去回顾一下已经熟悉的不得了的printf的参数,你发现它的参数可以有1个,也可以有2个,3个,4个.....都可以有。后面的参数设计是为了具象化格式化里的模板。
3. 如果用fprintf的话非常简单,就先正常按照printf去写,然后在括号最前面再加上一个参数,即:指向要写入文件的文件信息区的文件指针。这就是把格式化的信息写到文件里面去。

格式化输入   fscanf()       适用于所有输入流 

1. 格式化输出文件有了,那么如何格式化地读取文件呢?用fscanf。
2. fscanf就是从文件里面把里面的信息拿到内存里面去。这个函数又与scanf十分相似,参数比scanf多了一个FILE*指针。
3. 因此你先用scanf一如既往像以前那样正常写好,注意:scanf/fscanf的末尾几个参数都必须是地址形式,因为我是要把数据真真切切地读入到内存里面去,必须给我传地址!当然,数组名是首元素地址就不用&了。再在最前面加上参数:文件指针就OK了。

  


二进制输出     fwrite()          只适用于针对文件的流

1. 它是只能针对文件这个流的。
2. 当此时在打开文件的时候,这个打开方式可不能就用w与r了,因为那是打开一个文本文件.而我现在要打开一个二进制文件,应该用wb或者rb。
3. fwrite有四个参数,我此时此刻是从内存中往文件里面写入二进制数据,那我这个二进制数据到底是什么类型的呢?有各种各样的类型可能,但无论如何,二进制本身而言它就是死的。
4. 勤用sizeof

5. 我们以二进制的形式把内存中的数据写入到文件里面去,然后我们点开文件,确实里面的内容有些貌似可以看懂,有些是看不懂的。那我就让电脑通过二进制的方式在读出来。
6. 道理一样的,虽然我们肉眼看不懂,那就让程序去读。 

二进制输入     fread()          只适用于针对文件的流


顺带着一提:还有两组非常奇葩的函数 

现在并不是流指针在与内存数据打交道了,而是内存数据与内存数据在自己打交道了 

一个格式化的数据与字符串在打交道,站在格式化数据的立场上 

sprintf() 

sscanf() 

sprintf()根本没有打印功能,fprintf()如果里面第一个参数是stdout,那么具有打印功能,否则也没有

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

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

相关文章

文献阅读(45)——使用自监督学习对AMD分类

使用自监督学习对AMD分类 文章目录使用自监督学习对AMD分类一、简介二、先验知识三、文章核心内容四、使用方法1. 非参数化实例歧视(中文翻译过来总是奇奇怪怪,其实就是NPID)a 挑战b 解决方案c 转化!2. 数据集3. 数据预处理五、结…

Python之拉盖尔多项式

文章目录拉盖尔多项式简介微分与积分求根和反演采样和拟合拉盖尔多项式简介 拉盖尔多项式是拉盖尔方程的标准解,但其更著名的应用是薛定谔方程在解氢原子的时候,其径向函数最后要乘上一个Ln−l−12l1(2rnaμ)L^{2l1}_{n-l-1}(\frac{2r}{na_\mu})Ln−l−…

TCP/IP应用层常见协议总结

TCP/IP应用层常见协议总结1.HTTP:超文本传输协议2.SMTP:简单邮件传输(发送)协议3.POP3/IMAP:邮件接收的协议4.FTP:文件传输协议5.Telnet:远程登陆协议6.SSH:安全的网络传输协议1.HTTP:超文本传输协议 超文本传输协议 主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我…

浏览器的通信能力

用户代理 浏览器可以代替用户完成http请求,代替用户解析响应结果,所以我们称之为:用户代理 user agent 在网络层面,对于前端开发者,必须要知道浏览器拥有的两大核心能力 自动发出请求的能力自动解析响应的能力 自动…

『51单片机』串口通信配置

🚩write in front🚩 🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 🏅2021年度博客之星物联网与嵌入式开发TOP5&#xff5…

技术分享 | 黑盒测试方法论—因果图

因果图法是一种利用图解法分析输入与输出的各种组合情况,从而设计测试用例的方法,它适合于检查程序输入条件的各种组合情况。 因果图法比较适合输入条件比较多的情况,可以测试所有的输入条件的排列组合。因果图的 “ 因 ” 就是输入条件&…

Flutter滚动悬浮效果

有以下几种效果 1、tabBar透明度随偏移0-1渐变过度 2、app上下滚动触发tabBar同步滚动 3、tabBar切换触发app上下同步滚动 1、计算每个区块的高度 用keyList保存声明的key&#xff0c;用heightList保存每个key对应的组件高度 // key列表 List<GlobalKey> keyList [Gl…

lower_bound与upper_bound的应用

<1>lower_bound (1). . 上述代码返回在升序排序的序列a中第一个大于等于 t 的元素的地址. 示例: (2) 上述代码返回在升序排序的序列a中第一个大于等于 t 的元素的下标. 示例: 例题: P2249 【深基13.例1】查找 P2249 【深基13.例1】查找 - 洛谷 | 计算机科学教育新生…

JavaSE(多态、abstract、接口)

1.多态 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同 的状态。 向上转型 向上转型&#xff1a;实际就是创建一个子类对象&#xff0c;将其当成父类对象来使用。 语法格式&…

(牛客)小杜跑酷

链接&#xff1a;https://ac.nowcoder.com/acm/contest/49244/F?&headNavacm 来源&#xff1a;牛客网 题目描述 小杜又在玩游戏了&#xff01;这回他玩的是跑酷游戏&#xff01; 已知该跑酷地图长为n&#xff0c;有3层&#xff0c;可以理解为一张3n的地图。令人新奇的是&…

Shiro学习看这一篇文章就够了

第一章 Shiro简介 第1节 shiro介绍 1官网地址: http://shiro.apache.org/Apache Shiro 是一个功能强大,易于使用的Java安全框架,他执行认证、授权、加密、会话管理等功能,使用Shiro易于理解的API,使你能够轻松的保护任何应用,如移动端应用,大型web应用以及企业级应用. Shiro可…

当前主流的后端语言,谁能夺得桂冠,果然是后生可畏!

主流后端语言 如今编程语言遍地开花&#xff0c;烟花迷乱&#xff0c;小编整理了最流行的几种编程语言如下&#xff1a; 这几种语言都是经久不衰&#xff0c;占领着后端编程界的半壁江山。TIOBE上的语言排名&#xff1a; C、Java、python&#xff0c;C&#xff0c; C#鏖战榜首…

元宇宙浪潮下,数智人拒绝“标品”

作者 | 曾响铃 文 | 响铃说 在各地文博会、生活节等大型文娱活动上&#xff0c;在博物馆等各类场馆的线上平台&#xff0c;在企业与用户交互的窗口&#xff0c;在政务平台滚动政策宣讲片中&#xff0c;尤其是&#xff0c;在各大卫视的跨年晚会上…… 2022年末、2023年年初&a…

MyBatis Generator ORM层面的代码自动生成器

在日常开发工作中&#xff0c;我们往往需要自己去构建各种数据表所对应的持久化对象&#xff08;POJO&#xff09;、用于操作数据库的接口&#xff08;DAO&#xff09;以及跟 DAO 所绑定的对应 XML。这都是一些重复性的操作&#xff0c;不需要多大技术含量。MyBatis Generator工…

优思学院|Minitab中的子组大小应该怎样填写?

关于SPC中的均值极差控制图&#xff08;X-bar-R Chart&#xff09;&#xff0c;都是质量管理和六西格玛最常用的工具之一&#xff0c;学生经常都会问及SPC和子组的问题。 所谓的子组&#xff08;Subgroup&#xff09;&#xff0c;是指在同一组条件&#xff08;包括人、机、物、…

人工智能辅助药物发现(2)苗头化合物筛选

目录AI辅助苗头化合物筛选概述AI辅助CPICPI数据库蛋白质和化合物的特征表示深度学习CPI预测经典Y型架构基于注意力的架构基于复合物的架构CPI性能评估苗头化合物筛选的发展前景挑战与趋势实际应用AI辅助苗头化合物筛选概述 新型小分子药物的开发通常从生物学家确定疾病靶标开始…

oracle数据库初始化问题及处理方法记录

环境&#xff1a; 服务器装机是redhat7.9&#xff0b;oracle19&#xff0c;用户是oracle&#xff0c;用户组dba 装机后进行初始化&#xff1a; 1.配置oracle用户环境变量&#xff1a;~/.bash_profile export ORACLE_SIDxxx export ORACLE_BASE/oracle/app/oracle export OR…

海康visionmaster-在WPF中使用Winform控件的方法

描述 环境&#xff1a;VM4.0.0 VS2013及以上 现象&#xff1a;在算子SDK开发过程中&#xff0c;用户如何使用封装好的Winform模板匹配等控件&#xff1f; 解答 首先添加对如下两个dll文件的引用&#xff1a;WindowsFormsIntegration.dll&#xff0c;System.Windows.Forms.…

深入MySQL字符编码与对照规则

前言 本篇和大家一起深入MySQL的字符集与对照规则&#xff0c;剖析下我们存储在MySQL中的字段是如何进行存储和校验比对的。 先看问题&#xff1a;unique key为什么失效了&#xff1f;拉齐共识&#xff1a;回顾下字符编码的基础知识&#xff0c;回炉下ASCII和Unicode。深入了解…

算法训练营 day22 二叉树 二叉搜索树的最近公共祖先 二叉搜索树中的插入操作 删除二叉搜索树中的节点

算法训练营 day22 二叉树 二叉搜索树的最近公共祖先 二叉搜索树中的插入操作 删除二叉搜索树中的节点 二叉搜索树的最近公共祖先 235. 二叉搜索树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度…