C语言 文件操作 深度解析 #重点知识:文件操作函数的使用#(上)

简介: C语言 文件操作 深度解析 #重点知识:文件操作函数的使用#(上)

前言


  • 相信大家对文件都不陌生,我们在计算机的一系列操作都离不开文件,如果Linux没有了文件,那他就不叫Linux了,有了文件,我们的计算机才能够正常运行,有了文件我们才能够在计算机上写东西并能够帮我们保存下来。
  • C语言也提供了一系列的函数来操控文件,本篇文章只介绍那些常见和常用的函数。


1. 为什么使用文件


我们有可能会写通讯录,写过通讯录的都知道,如果没有文件操作,程序运行后输入的数据在程序结束就没有了,联系人信息也就没有了,如果不能存放联系人的信息,那通讯录还有什么用?所以必然的我们需要文件操作来将输入的联系人的信息存放到文件当中,下一次运行时再将之前已经保存在文件中的联系人的信息拿出来,这一系列的操作就是C语言的文件操作,对应的就需要使用一些相关操作函数。简单来说,文件操作能够将输入的通讯录的数据存放在硬盘文件中,这样就做到了数据的持久化。


所以使用文件,只有好处没有坏处。


2. 什么是文件


  • 硬盘上的文件就是文件。
  • 而文件又分为程序文件和数据文件


程序文件


程序文件就是一段程序,包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。


数据文件


数据文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

本章讨论的是数据文件。

在前面我们所学习所处理的数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。

其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件


3. 文件的打开和关闭


在理解前面的文件介绍后,这里我们开始学习C语言是如何进行文件操作的?

要进行文件操作,当然要知道文件的打开和关闭,在这之前,我们要学习文件指针。


缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。


每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE。


例如,VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:

struct _iobuf {  // 是一个结构体
        // 文件的各类信息
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE; // 取名FILE
  • 不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。
  • 每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,我们使用者不必关心细节。
  • 一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
  • 例如,这里创建一个FILE*的指针变量:
FILE* pf;//文件指针变量


定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说通过文件指针变量能够找到与它关联的文件。

如下图:


21dff942691e4465b898135bc637dd67.png


有了上面的文件指针相关概念的认知后,接下来就可以进行文件的打开和关闭了

  • 文件的打开和关闭
  1. 文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
  2. 在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
  1. ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。
  • fopen


139465bca0f0460fac07f05e999aff35.png


如果打开文件失败,返回一个NULL

  • fclose
int fclose ( FILE * stream );
// 可以直接这样关闭
fclose(pf);  // pf 是一个 FILE* 的指针变量,他此时指向一个文件,这里将他关闭
// 最后这里最好将这个pf指针置空
pf = NULL;


这两个函数的头文件都是<stdio.h>。

文件的打开方式有很多,如下图:

87301b9b70624cd889141765ea69c0ef.png

当然,这么多方式,我们只要着重熟练使用前5个就Ok了。

说了这么多,下面实例操作一下:

假设不自己创建文件以读的方式打开文件:

#include <stdio.h>
#include <stdlib.h>
int main()
{
  // 这里读文件,如果此时当前目录下没有这个文件,fopen返回一个空指针
  // 假设此时没有这个文件
  FILE* pf = fopen("test.txt", "r");  
  if (pf == NULL)
  {
    // 没有打开成功
    // 打印错误信息
    perror("open fail");
    exit(-1);
  }
  else
  {
    // 打开成功后
    // ......
    // 一系列文件操作
    // 关闭文件
    fclose(pf);  // 传递指向文件的指针
    pf = NULL;
  }
  return 0;
}


fea792363c6b4d978705cbc5da2b8f2e.png

可以看到,报错信息很明显:没有这个文件,说明需要文件已经存在,这也就对应了上面文件打开方式图的内容,如果此时以写(w)的方式打开?根据上面的内容,他会自动创建一个文件。

打开文件代码改为:

FILE* pf = fopen("test.txt", "w");


此时程序运行,终端什么都没有,但是在当前文件多出了一个文件,正是fopen里的那个test.txt文件:


4fb12f188ec2484fb334e77cb7133cbe.png


所以,以何种形式打开文件,其效果是不一样的,这也给了我们更多的选择。


4. 文件的顺序读写


文件的顺序读写当然需要一批函数来帮助我们操作,下面是一系列这样有这样功能的函数,接下来一一介绍和使用:


2be61362a4e6466c86f97ce6be677819.png


fgetc


fgetc是从文件中读取一个字符的函数

下面是函数参数原型:


94b1923392514dcca38cb1b5394f05f2.png

e5b4b283c40b4bbcbcc43af2f5743fa8.png

97bf605720b544cca6a9adfc1514fd49.png

话不多说,先在当前文件创建一个test.txt,并在里面输入abcdef,然后进行fgetc的文件操作:

#include <stdio.h>  // 对应函数头文件
#include <stdlib.h>
int main()
{
  // fgetc 相当于从文件中读取字符,所以这里要以r的形式打开文件
  FILE* pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
    perror("open fail");
    exit(-1);
  }
  // 打开成功
  // 开始读取字符
  int ch = fgetc(pf);  // 得到字符的ASCLL码值
  printf("%c\n", ch);
  ch = fgetc(pf);  // 得到下一个字符的ASCLL码值,函数会自动往下找
  printf("%c\n", ch);
  ch = fgetc(pf);  // 得到下一个字符的ASCLL码值,函数会自动往下找
  printf("%c\n", ch);
  ch = fgetc(pf);  // 得到下一个字符的ASCLL码值,函数会自动往下找
  printf("%c\n", ch);
  ch = fgetc(pf);  // 得到下一个字符的ASCLL码值,函数会自动往下找
  printf("%c\n", ch);
  // 关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


73d902c8ec6642e48c4fc576278d9519.png

当然我们也可以不必这么麻烦,直接写个循环瞬间将文件里的字符弄出来打印。


fputc


fputc是将字符写入文件当中,既然是写入,回顾写(w)的特点,如果文件不存在,自动创建一个文件,如果文件存在,则覆盖那个已经存在的文件。


02ebbaa6c878478fbef8786f81116b32.png

9f108578a34a49d9b054173fcc98b6a0.png

89b47fb1c6d6412f8a0a6668c0fe27a3.png

这里不创建文件,直接使用(当前文件里没有test.txt文件):

#include <stdio.h>
#include <stdlib.h>
int main()
{
  // fputc 将字符写入文件,所以这里用w
  FILE* pf = fopen("test.txt", "w");
  if (pf == NULL)
  {
    perror("open fail");
    exit(-1);
  }
  // 打开文件成功
  // 开始写入
  for (char ch = 'a'; ch <= 'z'; ++ch)
  {
    // 循环写入a-z 26 个字母
    fputc(ch, pf);
  }
  // 关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


我们打开test.txt文件观察是否写入:


23c2c9ffff814279b9b05bd47cf5dfe7.png

可以看到,的确将26个字母写入文件。


相关文章
|
5月前
|
存储 程序员 C语言
c语言文件操作
本文介绍了C语言中文件操作的核心概念,包括文件缓冲区、数据与程序文件的区别、流的概念及标准输入输出流。重点讲解了文件的打开与关闭、读写操作(如fgetc、fputs、fscanf、fwrite等),以及随机读写函数fseek、ftell和rewind的使用方法。同时说明了文本文件与二进制文件的读取结束判定方式,并通过代码示例展示了实际应用。
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
793 23
|
6月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
1258 0
|
8月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
395 15
|
9月前
|
存储 编译器 程序员
c语言的文件操作与文件缓冲区
如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件。磁盘(硬盘)上的文件是文件。但是在程序设计中,我们⼀般谈的⽂件有两种:程序文件、数据文件(从文件功能的角度来分类 的)。就比如说我们电脑中以.txt为后缀的就是文件的一种,他就是数据文件。.exe为后缀的就为程序文件。函数名功能适用范围fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets。
292 0
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
560 1
一文彻底搞清楚C语言的函数
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
737 15
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
324 24
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
722 16
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
625 3

热门文章

最新文章

推荐镜像

更多
  • DNS