C语言之文件操作篇(2)

news/2024/10/23 5:40:46/

目录

文件状态指针

文件流

文件的顺序读写

 fgetc

fputc

fgets

fputs

fscanf

fprintf

fread

fwrite


今天接下来我们讲解文件读写函数。🆗🆗🆗

文件状态指针

  • 文件状态指针也就是文件指示器。(可以理解为光标) 
  •  文件在不断被操作读取的过程中,文件状态指针是一直在移动的。

文件流

  • 流是怎样一个概念呢?我们简单通俗的介绍下。本篇我们把所有输入输出流分为两个标准输入出流文件流

流是一个高度抽象的概念!!在我们写程序的时候,我们需要将数据传到屏幕,存在硬盘上,传到网络上,U盘光盘等外部设备。不同的外部设备的读写方式不同,传输方式也不同。 有人觉得程序员也太难了,于是抽象化了流的概念。我们先将数据统一传输到流里面(文件流等),然后再传输到各个外部设备。

 

我们在写文件的时候,需要打开文件,关闭文件。我们用scanf从键盘上读取数据,printf向屏幕上打印数据,直接操作了为什么没有打开标准输入输出流呢? 

那是因为C语言程序运行起来,就默认打开了3个流。

  • stdin : 标准输入流(键盘)
  • stdout : 标准输出流(屏幕)
  • stderr : 标准错误流
  • 特别提醒:所有的流都是FILE*的指针类型

用打开标准输出流的方式打印26个字母

#include<stdio.h>
int main()
{char ch = 0;for (ch = 'a'; ch <= 'z'; ch++){if (ch % 5 == 0)fputc('\n', stdout);//标准输出流fputc(ch, stdout);}//a-97//b-98//c-99//100换行了return 0;
}

 

用打开文件流的方式打印26个字母。------>下面fputc

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}char ch = 0;for (ch = 'a'; ch <= 'z'; ch++){if (ch % 5 == 0)fputc('\n', pf);//文件流fputc(ch, pf);}//a-97//b-98//c-99//100换行了fclose(pf);pf = NULL;return 0;
}

文件的顺序读写

记住:站在内存数据的角度去理解!! 其次文件要用输入输出函数去输入输出操作,别手动键盘修改文本文件,这样达到不到想要的效果哦!!

功能                 函数名        适用于字符输入函数          fgetc         所有输入流
字符输出函数          fputc         所有输出流
文本行输入函数        fgets         所有输入流
文本行输出函数        fputs         所有输出流
格式化输入函数        fscanf        所有输入流
格式化输出函数        fprintf       所有输出流
二进制输入            fread         文件
二进制输出            fwrite        文件

 

 

我们接下来详细的介绍以上各个函数。函数头文件 参数 返回值 使用去介绍


 fgetc

 fgetc - C++ Reference (cplusplus.com)

 

  • fgetc是以读的形式字符输出文件,内存读取数据。
  • 头文件 #include<stdio.h>
  • 参数FILE *stream 文件指针类型的指针变量 指向了一个文件信息区
  • 返回值是int类型(字符发生了整型提升)
  1. 成功后,将返回字符读取(提升为 int 值)ASCII码。
  2. 返回类型为 int 以适应特殊值 EOF,该值表示失败-1
  3. 如果位置指示器位于文件末尾,则该函数返回 EOF 并设置的 eof 指示器 (feof)。
  4. 如果发生其他读取错误,该函数还会返回 EOF,但改为设置其错误指示器 (ferror)。
#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch=fgetc(pf);printf("%c", ch);ch=fgetc(pf);printf("%c", ch);ch=fgetc(pf);printf("%c", ch);ch=fgetc(pf);printf("%c", ch);ch=fclose(pf);pf = NULL;return 0;
}

fputc

fputc - C++ Reference (cplusplus.com)

  

  • fputc以写的形式输入字符到文件中。
  •  头文件#include<stdio.h>
  • 参数int character 是整型 也就是字符整型提升 直接写字符即可
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • 返回值
  1. 成功后,将返回所写字符(整型提升)
  2. 如果发生写入错误,则返回 EOF 并设置错误指示器(ferror)。
#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}fputc('a', pf);//文件流fputc('b', pf);fputc('c', pf);fputc('d', pf);fclose(pf);pf = NULL;return 0;
}

 

请在文件中输入26个英文字母。 

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}char ch = 0;for (ch='a'; ch <= 'z'; ch++)fputc(ch, pf);fclose(pf);pf = NULL;return 0;
}
//换行
#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}char ch = 0;for (ch = 'a'; ch <= 'z'; ch++){if (ch % 5 == 0)fputc('\n', pf);//文件流fputc(ch, pf);}//a-97//b-98//c-99//100换行了fclose(pf);pf = NULL;return 0;
}

 


fgets

 fgets - C++ Reference (cplusplus.com)

 

从流中获取字符串

中读取字符并将其作为 C 字符串存储到 str 中,直到读取 num-1 个字符或到达换行符或文件末尾,以先发生者为准。
换行符使 fgets 停止读取,但它被函数视为有效字符,并包含在复制到 str 的字符串中。
终止空字符会自动附加到复制到 str 的字符之后

 

  • fgets是从文本文件stream读取输出字符串num str的函数 
  • 头文件#include<stdio.h>
  • 参数str是字符指针,指向一个字符数组的指针
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • 参数num是要复制到 str 的最大字符数(包括终止空字符)(整型提升)
  • 返回值是char*类型
  1. 成功后,函数返回 str
  2. 如果在尝试读取字符时遇到文件末尾,则设置 eof 指示器 (feof)。
  3. 如果在读取任何字符之前发生这种情况,则返回的指针为空指针(str 的内容保持不变)。
  4. 如果发生读取错误,则设置错误指示器(ferror),并返回空指针(但str指向的内容可能已更改)。
  •  读取停止情况
  1. 读取到了num-1个字符
  2. 到达换行符\n
  3. 到达文件末尾

只会读num-1个字符 

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}char str[10] = { 0 };int ret=fgets(str,7,pf);//实际上只会读6个字符if (ret == EOF){perror("fgets");}elseprintf("%s", str);fclose(pf);pf = NULL;return 0;
}

 

读到\n停止不读了 

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}char str[100] = { 0 };int ret=fgets(str,12,pf);//实际上只会读6个字符if (ret == EOF){perror("fgets");}elseprintf("%s", str);fclose(pf);pf = NULL;return 0;
}

 

fputs

fputs - C++ Reference (cplusplus.com)  

  • fputs是将str里的字符输出到文本文件stream 
  • 头文件#include<stdio.h>
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • 参数str 是字符指针 指向存放字符串的数组(由const修饰,防止被修改)
  • 返回值是int类型
  1. 成功时,将返回非负值。
  2. 出错时,该函数返回 EOF 并设置错误指示器(ferror)
#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}char str[] = "abcdef";fputs(str,pf);fputs("abcdef", pf);
//两种写法fclose(pf);pf = NULL;return 0;
}

 


下面两个函数用结构体去举例子 fscanf是输入 fpirntf是输出,先看下对比。

你发现了什么?? 

  • scanf------->键盘-------->读取到程序中   fscanf-------->文件-------->读取到程序中 
  • printf-------->程序中的数据-------->输入到屏幕上   fprintf-------->程序中的数据------>输入到文件

fscanf

fscanf - C++ Reference (cplusplus.com)

 

  • fscanf是从文件读取数据
  • 头文件#include<stdio.h>
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • 其他和scanf是一样的,不用关心
  • 返回值是int类型
#include<stdio.h>
struct S
{char c;int i;float a;
};
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//输入//struct S s = { 't',7,3.14 };//fprintf(pf,"%c  %d  %f",s.c,s.i,s.a);//格式必须一摸一样//输出struct S s = {0};fscanf(pf, "%c %d %f", &(s.c), &(s.i), &(s.a));printf("%c %d %f", s.c, s.i, s.a);fclose(pf);pf = NULL;return 0;
}

 

fprintf

fprintf - C++ Reference (cplusplus.com) 

 

  • fprintf是输入数据到文本文件
  • 头文件#include<stdio.h>
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • 其他和printf是一样的,不用关心
  • 返回值是int类型
  1. 成功后,将返回写入的字符总数。
  2. 如果发生写入错误,则设置错误指示器(ferror)并返回负数。
  3. 如果在写入宽字符时发生多字节字符编码错误,errno 将设置为 EILSEQ 并返回负数。
#include<stdio.h>
struct S
{char c;int i;float a;
};
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}struct S s = { 't',7,3.14 };fprintf(pf,"%c  %d  %f",s.c,s.i,s.a);fclose(pf);pf = NULL;return 0;
}

 


前面的函数都是针对于文本文件的,下面这组函数针对的是二进制文件。 

fread

 fread - C++ Reference (cplusplus.com)

 

从流中读取数据块

中读取计数元素数组,每个元素的大小为字节并将它们存储在 ptr 指定的内存块中。
流的位置指示器按读取的总字节数前进。
如果成功,则读取的总字节数为(大小*计数)。

 

  • fread是向二进制文件读取数据
  • 头文件#include<stdio.h>
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • size_t size是每个元素的大小(以字节为单位)
  • size_t count是数组元素的个数
  • 参数void *ptr指向大小至少为 (size*count) 字节的内存块的指针(const修饰防止修改,void*类型的指针是因为不知道读取的是哪种类型的指针,void*不能被解引用操作,可以强制转换)
  • 返回值是size_t类型
  1. 返回成功读取的元素总数。
  2. 如果此数字与 count 参数不同,则表示读取时发生读取错误或到达文件末尾。在这两种情况下,都会设置正确的指标,可以分别用 ferror 和 feof 进行检查。
  3. 如果大小计数为零,则该函数返回零,并且流状态和 ptr 指向的内容保持不变。
    size_t 是无符号整数类型。
#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}int arr[20] = { 0};//10个整型40个字节fread(arr, 4, 10, pf);int i = 0;for (i = 0; i < 10;i++){printf("%d ", arr[i]);}fclose(pf);pf = NULL;return 0;
}

 

fwrite

fwrite - C++ Reference (cplusplus.com) 

 

写入要流式传输的数据块

计数元素数组(每个元素的大小为字节从 ptr 指向的内存块写入中的当前位置。
流的位置指示器按写入的总字节数前进。
在内部,该函数解释所指向的块,就好像它是一个类型的元素数组,并按顺序写入它们,就好像为每个字节调用一样。

  • fwrite是向二进制文件写输入数据的
  • 头文件#include<stdio.h>
  • 参数FILE*stream 是文件指针类型的指针变量 指向了一个文件信息区
  • 参数void *ptr是指向写入元素数组的的指针变量(const修饰防止修改,void*类型的指针是因为不知道输入的输入是哪种类型的指针,void*不能被解引用操作,可以强制转换)
  • size_t size是每个元素的大小(以字节为单位)
  • size_t count是数组元素的个数
  • 返回值size_t类型
  1. 返回成功写入的元素总数。
  2. 如果此数字与 count 参数不同,则写入错误阻止函数完成。在这种情况下,将为设置错误指示器(ferror)。
  3. 如果大小计数为零,则该函数返回零,错误指示器保持不变。
    size_t 是无符号整数类型。
#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//10个整型40个字节fwrite(arr, 4, 10, pf);fclose(pf);pf = NULL;return 0;
}

 

文件的随机读写

文件结束的判定

✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!

希望大家继续坚持在每天敲代码的路上。其实,没有人会一直带着你往前走,你自己一定要成为自己的救赎。

代码---------→【唐棣棣 (TSQXG) - Gitee.com】

联系---------→【邮箱:2784139418@qq.com】


http://www.ppmy.cn/news/1152758.html

相关文章

云原生Kubernetes:K8S集群版本升级(v1.20.6 - v1.20.15)

目录 一、理论 1.K8S集群升级 2.集群概况 3.升级集群 4.验证集群 二、实验 1.升级集群 2.验证集群 三、问题 1.给node1节点打污点报错 一、理论 1.K8S集群升级 &#xff08;1&#xff09;概念 搭建K8S集群的方式有很多种&#xff0c;比如二进制&#xff0c;kubeadm…

英语学习工具推荐

无论您是初学者还是想要巩固英语能力的学习者&#xff0c;我们都为您提供了一个高效而便捷的英语学习工具。 英语复读机&#xff0c;您可以随时输入您想要复读的英语单词、句子或者文章。我们的复读机会循环播放您输入的内容&#xff0c;帮助您加深记忆、提高听力和口语表达能力…

Maven 密码加密

一、简介 Maven支持服务器密码加密。该解决方案解决的主要用例是&#xff1a; 多个用户共享同一台生成计算机&#xff08;服务器、CI 框&#xff09;有些用户有权将 Maven 工件部署到存储库&#xff0c;有些则没有。 这适用于任何需要授权的服务器操作&#xff0c;而不仅仅是…

如何使用ChatPPT生成PPT文档

简介 ChatPPT是一个基于人工智能的PPT生成工具&#xff0c;可以帮助用户快速生成高质量的PPT文档。ChatPPT使用自然语言处理技术&#xff0c;可以根据用户的指令生成PPT内容、设计和排版。 使用方法 ChatPPT提供了两种使用方式&#xff1a;在线体验版和Office插件版。 在线…

【最长上升子序列】【博弈论】Game on Permutation—CF1860C

Game on Permutation—CF1860C 思路 假设 Alice 最初选择的是 a i a_i ai​。 如果先手必胜&#xff0c;那么 a i a_i ai​ 左边必须存在比它小的元素&#xff0c;并且不管 Bob 多么“聪明”&#xff0c;Alice 都能赢。 在 Bob 很聪明的情况下&#xff0c;Bob 最多移动一…

舍弃Java模式,从头开始,用Rust书写编程的未来

沉迷于Rust之美&#xff1a;类型安全、内存安全、注重正确性&#xff0c;这叫人如何不爱呢&#xff1f; 在开发Apollo&#xff08;一款Python应用&#xff09;时&#xff0c;遇到了许多错误。如果我使用Rust&#xff0c;大多数错误都能被编译器捕获&#xff08;虽然无法做到百…

设计模式~备忘录模式(memento)-22

目录  (1)优点&#xff1a; (2)缺点&#xff1a; (3)使用场景&#xff1a; (4)注意事项&#xff1a; (5)应用实例&#xff1a; 代码 备忘录模式(memento) 备忘录模式&#xff08;Memento Pattern&#xff09;保存一个对象的某个状态&#xff0c;以便在适当的时候恢复对…

Idea执行Pom.xml导入jar包提示sun.misc.BASE64Encoder jar找不到---SpringCloud工作笔记197

奇怪之前都是好好的,这个是因为,jdk的版本不对,重新打开以后自动被选择成jdk11了...记录一下 原因是从jdk9的时候,这个jar包已经被删除了,所以会报错,如果你用的是jdk自带的这个jar包就会报错,那么还可以,修改,不让他用jdk的,让他用 用org.apache.commons.codec.binary.Base64…