学习的流程
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
文件操作原理
———————————————————————————————————————————
为什么使用文件
———————————————————————————————————————————
什么是文件
———————————————————————————————————————————
二进制文件 和文本文件
二进制编译器的方式打开 二进制文件,二进制文件是我们不能直接看懂的文件
文本文件就是肉眼看得懂的
———————————————————————————————————————————
文件流
文件使用流程是,打开 读写 关闭
并且文件的使用是需要依靠媒介的,也就是流
就比如你需要开电视,你不可能是用手把电视打开,你还得跑过去,很麻烦,所以我们发明了遥控器,这个遥控器也就是中间媒介,不需要你大费周章的再去开电视,只需要遥控器一按,就打开了。
下面进行图解举例。
———————————————————————————————————————————
文件指针
因为需要流,所以需要文件指针
在C语言中,文件操作是通过所谓的“流”来进行的,而文件指针就是这种流的抽象表示。FILE
结构体是C标准库中定义的一个数据结构,它用于封装关于文件的信息和用于操作文件的数据。
文件指针通常是指向FILE
结构体的指针变量,它用于表示一个打开的文件流。通过文件指针,您可以执行诸如读取、写入、定位和关闭文件等操作。
当您使用fopen
函数打开一个文件时,它会返回一个FILE
*类型的指针,这就是文件指针。然后,您可以使用这个指针来调用其他文件操作函数,如fread
、fwrite
、fgets
、fputs
、fprintf
等
FILE结构指针 称为文件指针
今天我们讲的主要就是用FILE打开文件
在C语言中,`FILE`结构体定义在标准输入输出库`stdio.h`中,它用于表示一个打开的文件流。`FILE`结构体的定义如下:
```c
typedef struct _iobuf {int _flag; /* 文件状态标志 */char *_ptr; /* 当前读/写的指针 */char *_base; /* 缓冲区的基地址 */char *_end; /* 缓冲区的结束地址 *//* 以下成员用于缓冲区管理 */void *_lock; /* 用于文件锁 */struct _io_functions {int (*read) (struct _iobuf *, char *, int);int (*write) (struct _iobuf *, const char *, int);int (*seek) (struct _iobuf *, long int, int);int (*close) (struct _iobuf *);/* 可能还有其他函数指针 */} _functions;/* 以下成员用于系统特定的信息 */void *_data; /* 用于存放系统特定的数据 */
} FILE;
```
这个结构体包含了多个用于文件操作的成员变量和函数指针。下面是这些成员的简要说明:
- `_flag`:这个整数成员用于存储文件的状态标志,如是否为末尾(`FEof`)、是否出错(`FError`)等。
- `_ptr`:这个指针成员指向当前读/写的文件位置。
- `_base`:这个指针成员指向缓冲区的开始位置,即文件数据的内存缓冲区。
- `_end`:这个指针成员指向缓冲区的结束位置。
- `_lock`:这个指针成员用于文件锁,它可以用于多线程环境中的同步。
- `_functions`:这个结构体成员包含了文件操作的函数指针,分别用于读取(`read`)、写入(`write`)、定位(`seek`)和关闭(`close`)文件。
- `_data`:这个指针成员用于存放系统特定的数据,通常用于实现特定的文件操作。
文件信息区通常指的是`FILE`结构体中用于存储文件信息和控制文件操作的这部分内容。这些信息包括文件的状态、当前的读写位置、缓冲区信息等。通过操作这些成员,可以实现对文件的读写和控制功能。
———————————————————————————————————————————
文件信息区
文件信息区 也就是FILE的类型
所以我们通过pf来维护 文件信息区的写和读
进行操作的时候 一定要通过文件指针变量找到与他关联的文件
———————————————————————————————————————————
文件的打开和关闭
使用
这里是如果有 也就是打开 没有也就是报错
r--只读
w--创建一个新文件(没有)
——————————————————————————————————————————
顺序读写函数的介绍
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
读取文件方式
可以和fopen打开文件,配合使用
- "r":只读模式,打开一个已经存在的文本文件。
- "w":写入模式,打开一个文本文件用于写入。如果文件已经存在,则之前的内容会被删除。
- "a":追加模式,打开一个文本文件用于写入。如果文件不存在,则会创建一个新文件。
- "rb":只读模式,打开一个二进制文件。
- "wb":写入模式,打开一个二进制文件用于写入。
- "ab":追加模式,打开一个二进制文件用于写入
打开文件需要用流,也就是一个介质,
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fopen(打开文件)和fclose(关闭文件)
fopen` 和 `fclose` 是C语言中用于文件操作的两个基本函数。
fopen语法介绍
`fopen` 函数用于打开一个文件,并返回一个指向该文件的指针。如果打开文件失败,`fopen` 会返回 `NULL`。
函数原型:
```c
FILE *fopen(const char *path, const char *mode);
```
参数:
- `path`: 要打开的文件的路径。
- `mode`: 文件的打开模式(例如:`"r"` 读取模式,`"w"` 写入模式,`"a"` 追加模式等)。
返回值:
fopen参数介绍
如果成功,返回一个指向 `FILE` 对象的指针。
如果失败,返回 `NULL`。
——————————————————————————————————————————
fclose语法介绍
`fclose` 函数用于关闭由 `fopen` 函数打开的文件。在关闭文件后,相关的文件指针也会被清空,此后不能再使用该指针进行文件操作。
函数原型:
```c
int fclose(FILE *stream);
```
fclose参数介绍
- `stream`: 由 `fopen` 函数返回的文件指针。
返回值:
- 如果成功,返回 `0`。
- 如果出错,返回 `EOF`。
使用示例
下面是一个简单的使用 `fopen` 和 `fclose` 的例子:
```c
#include <stdio.h>
int main() {FILE *filePtr;char *filename = "example.txt";// 打开文件filePtr = fopen(filename, "r"); // 以读取模式打开文件if (filePtr == NULL) {perror("Error opening file");return -1;}// ... 在这里进行文件操作 ...// 关闭文件fclose(filePtr);filePtr=NULL;return 0;
}
```
在这个例子中,首先以读取模式(`"r"`)打开一个名为 `example.txt` 的文件。如果文件打开成功,我们就有了一个指向该文件的 `FILE` 类型的指针,可以用来读取文件内容。操作完成后,使用 `fclose` 函数关闭文件,释放系统资源。
在使用 `fopen` 和 `fclose` 进行文件操作时,应该始终检查 `fopen` 的返回值以确保文件是否成功打开,
1,并在操作完成后使用 `fclose` 关闭文件,以避免资源泄露和数据丢失。
2,在关闭文件之后让他指向空指针,防止因为是野指针而导致出错(因为这里本质还是指针,指针指向的文件关闭后,指向的是一个空的地址,所以此时也就变成了野指针,所以我们需要指向NULL,防止出现问题)
3,这两个函数没有详细介绍就说了一下语法格式的问题
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fputc(写入字符)
语法格式
fputs(const char *str, FILE *stream):将一个字符串写入文件。
但是这里只能写入一个字符单次
——————————————————————————————————————————
写进去a b c
——————————————————————————————————————————
写进去a-z
读文件,这里需要打印的话需要读取文件,然后才能打印
代码,这这里补充说明一下,fputc函数的使用只能一次写一个字符,要么就是循环输入,并不能直接输入字符串
——————————————————————————————————————————
代码1写进去a
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
int main()
{FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}fputc('a', pf);fclose(pf);pf = NULL;return 0;
}
我们发现写进去是没有问题的
——————————————————————————————————————————
代码2写进去字符串
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
int main()
{FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}fputc('a', pf);//我们预计写入afputc('bcd', pf);//我们预计写入bcdfclose(pf);pf = NULL;return 0;
}
这里我们发现,这里不能输入字符串,还是只能输入一个字符
——————————————————————————————————————————
代码3循环输入A-Z
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
int main()
{FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}//fputc('a', pf);//fputc('bcd', pf);for (int i = 'A'; i < 'Z'; i++){fputc(i, pf);}fclose(pf);pf = NULL;return 0;
}
这里我们发现是可以的,但是一次只能输入一个字符,并且是连续输入的,这里我们可以知道,fputc输入字符是连续输入的
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fgetc(读字符)
函数的语法格式
语法格式getc函数是C语言中的标准库函数之一,用于从指定的文件流中逐个字符地读取字符。它的函数原型如下:
int fgetc(FILE *stream)
上面我们描述过函数需要
fopen(打开)+读取+打印
中间可能还有写入等等,但是基本上是步骤是这个步骤
——————————————————————————————————————————
函数的返回参数
getc函数正常读取结束返回的是读取到的字符值。返回值是int类型,范围是0到255,或者是EOF(-1),表示读取结束。
-1 本质是整数 所以返回类型需要是整形
当你使用 fgetc
时,以下规则适用:
-
如果成功读取一个字符,
fgetc
返回该字符的 ASCII 码值。在ASCII
表中,控制字符(如换行符\n
、回车符\r
等)和空格字符也有对应的数值。 -
如果读取遇到文件末尾(即文件中再也没有字符可以读取),
fgetc
返回EOF
。在 C 标准库中,EOF
定义为-1
。 -
如果读取失败(例如,文件指针无效或文件无法打开),
fgetc
也会返回EOF
。
请注意,fgetc
函数只能读取一个字符,而不是字符串。如果你需要读取多个字符,你需要循环调用 fgetc
或者使用其他函数如 fgets
,后者可以读取一行文本。
——————————————————————————————————————————
函数的读取方式
一个字符一个字符的读取
如果需要所有内容一起读取
那么你需要进行循环读取,读取的字符最好存起来,不等于eof 也就是继续循环,等于的时候也就是停止循环,写一个字符读取一个字符 写一堆字符 读取一堆字符。
——————————————————————————————————————————
代码1(单个读取)
当你使用 fgetc 时,以下规则适用:如果成功读取一个字符,fgetc 返回该字符的 ASCII 码值。在 ASCII 表中,控制字符(如换行符 \n、回车符 \r 等)和空格字符也有对应的数值。如果读取遇到文件末尾(即文件中再也没有字符可以读取),fgetc 返回 EOF。在 C 标准库中,EOF 定义为 -1。如果读取失败(例如,文件指针无效或文件无法打开),fgetc 也会返回 EOF。请注意,fgetc 函数只能读取一个字符,而不是字符串。如果你需要读取多个字符,你需要循环调用 fgetc 或者使用其他函数如 fgets,后者可以读取一行文本。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
int main()
{//打开文件并且写入FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}//fputc('a', pf);//fputc('bcd', pf);//这里已经输入A-Z的字符for (int i = 'A'; i <= 'Z'; i++){fputc(i, pf);}//int c = 0;//c = fgetc(pf);//printf("%c ", c);这里会发现不能读取成功并且打印出来fclose(pf);pf = NULL;//这里说明一下为什么需要进行二次打开文件,因为上面的是的写入,不是读取,所以需要关闭文件之后再进行读取// 如果你想要可以读取又可以写入,你也可以用a+,我这里主要是进行举例说明。//打开文件FILE* ps = fopen("text.txt", "r");if (ps == NULL){perror("fopen:w:");return 1;}//单个进行读取 这里需要进行一个变量进行接收,因为这个函数的返回值是返回正确的情况下就会返回数值的ASCII码值,//读取不正确的情况就会返回eof 读取到末尾也会返回eof 所以我们需要用一个变量进行接收,你可以是char 也可以是intint ch = 0;ch =fgetc(ps);printf("%c ", ch);//循环一次进行读取 ,这里你可以用while,也可以用whilefclose(ps);pf = NULL;return 0;
}
可以看到只是读取一个字符A
——————————————————————————————————————————
代码2(循环读取)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
int main()
{//打开文件并且写入FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}//fputc('a', pf);//fputc('bcd', pf);//这里已经输入A-Z的字符for (int i = 'A'; i <= 'Z'; i++){fputc(i, pf);}//int c = 0;//c = fgetc(pf);//printf("%c ", c);这里会发现不能读取成功并且打印出来fclose(pf);pf = NULL;//这里说明一下为什么需要进行二次打开文件,因为上面的是的写入,不是读取,所以需要关闭文件之后再进行读取// 如果你想要可以读取又可以写入,你也可以用a+,我这里主要是进行举例说明。//打开文件FILE* ps = fopen("text.txt", "r");if (ps == NULL){perror("fopen:w:");return 1;}//单个进行读取 这里需要进行一个变量进行接收,因为这个函数的返回值是返回正确的情况下就会返回数值的ASCII码值,//读取不正确的情况就会返回eof 读取到末尾也会返回eof 所以我们需要用一个变量进行接收,你可以是char 也可以是intint ch = 0;ch =fgetc(ps);printf("%c \n", ch);//循环一次进行读取 ,这里你可以用while,并且你这里可以发现 之前读取之后A后面进行读取的时候,只是读取A之后的字符//也就是我们只是读取一次int ca = 0;while ((ca = fgetc(ps)) != EOF){printf("%c ", ca);}fclose(ps);pf = NULL;return 0;
}
——————————————————————————————————————————
代码3(循环读取)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
int main()
{//打开文件并且写入FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}//fputc('a', pf);//fputc('bcd', pf);//这里已经输入A-Z的字符for (int i = 'A'; i <= 'Z'; i++){fputc(i, pf);}//int c = 0;//c = fgetc(pf);//printf("%c ", c);这里会发现不能读取成功并且打印出来fclose(pf);pf = NULL;//这里说明一下为什么需要进行二次打开文件,因为上面的是的写入,不是读取,所以需要关闭文件之后再进行读取// 如果你想要可以读取又可以写入,你也可以用a+,我这里主要是进行举例说明。//打开文件FILE* ps = fopen("text.txt", "r");if (ps == NULL){perror("fopen:w:");return 1;}//单个进行读取 这里需要进行一个变量进行接收,因为这个函数的返回值是返回正确的情况下就会返回数值的ASCII码值,//读取不正确的情况就会返回eof 读取到末尾也会返回eof 所以我们需要用一个变量进行接收,你可以是char 也可以是intint ch = 0;ch =fgetc(ps);printf("%c \n", ch);//循环一次进行读取 ,这里你可以用while,并且你这里可以发现 之前读取之后A后面进行读取的时候,只是读取A之后的字符//也就是我们只是读取一次int ca = 0;//while ((ca = fgetc(ps)) != EOF)//{// printf("%c ", ca);//}for (ca = fgetc(ps); fgetc(ps) != EOF; ca++){printf("%c ", ca);}fclose(ps);pf = NULL;return 0;
}
这种循环方式也是可以的,但是很显然,这个还需要修改,有点麻烦,没有while循环好用,所以不详细说明了
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fputs(写入文本)
`fputs` 函数的语法
如下所示:
```c
int fputs(const char *str, FILE *stream);
```
这里的参数含义如下:
- `str`:这是一个指向要写入文件的 C 字符串的指针。字符串可以是任何以 null 字符 `'\0'` 结尾的字符序列。
- `stream`:这是一个指向 `FILE` 对象的指针,该对象标识了输出流,即文件或其他 I/O 设备。
函数返回值:
- 如果写入成功,`fputs` 返回 `str` 指针。
- 如果写入失败,`fputs` 返回 `EOF`。
`fputs` 函数会尝试将 `str` 指向的字符串写入到由 `stream` 指针指向的文件流中。写入操作会一直进行,直到遇到字符串末尾的 null 字符,或者在写入过程中发生错误。如果写入成功,`fputs` 函数会更新文件的位置指针。
下面是一个简单的例子,展示如何使用 `fputs` 函数将一个字符串写入到文件中:
```c
#include <stdio.h>
int main() {FILE *file;// 打开文件用于写入,如果文件不存在则创建它file = fopen("example.txt", "w");if (file == NULL) {perror("Error opening file");return 1;}// 使用 fputs 写入字符串fputs("Hello, World!", file);// 关闭文件fclose(file);return 0;
}
```
———————————————————————————————————————————
在这个例子中,`fputs` 函数会写入 "Hello, World!" 到 "example.txt" 文件中。如果文件已经存在,它的内容将被这个字符串覆盖;如果文件不存在,它将被创建。写入完成后,文件将被关闭。
写到一行上面去
除非两个主动加上换行\n
———————————————————————————————————————————
代码1单个输入
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
//写入字符串
int main()
{FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("foopen:w:");return 1;}fputs("hellow word", pf);fputs("你好世界", pf);fclose(pf);//关闭pf = NULL;//防止成为野指针,置为空指针return 0;
}
这里我们可以发现,我们不仅可以写入字符串,还可以写入文本
——————————————————————————————————————————
代码2循环输入
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
//写入字符串
int main()
{//写入文件FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("foopen:w:");return 1;}fputs("hellow word", pf);fputs("你好世界", pf);for (int i = 0; i < 10; i++){fputs("hellow 世界\n", pf);//这里采取换行符,进行换行}fclose(pf);//关闭pf = NULL;return 0;
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fgets(读取文本)
语法格式
`fgets` 函数用于从文件读取一行文本。其语法如下:
```c
char *fgets(char *str, int n, FILE *stream);
```
这里的参数含义如下:
- `str`:这是一个指向字符数组的指针,用于存储从文件中读取的一行文本。
- `n`:这是一个整数,表示 `str` 数组的最大长度(以字符为单位)。
- `stream`:这是一个指向 `FILE` 对象的指针,该对象标识了输入流,即文件或其他 I/O 设备。
函数返回值:
- 如果读取成功,`fgets` 返回 `str` 指针。
- 如果读取失败,`fgets` 返回 `NULL`。
`fgets` 函数会从由 `stream` 指针指向的文件流中读取最多 `n-1` 个字符(因为最后一个字符是为了放置字符串结束符 `'\0'` 而保留的),并将它们存储在 `str` 指向的字符数组中。读取操作会一直进行,直到读取到换行符、文件结束符或发生错误。读取到的字符串末尾会自动加上 null 字符 `'\0'`。
下面是一个简单的例子,展示如何使用 `fgets` 函数从文件中读取一行文本:
```c
#include <stdio.h>
int main() {FILE *file;char line[100]; // 创建一个足够大的数组来存储一行文本// 打开文件用于读取file = fopen("example.txt", "r");if (file == NULL) {perror("Error opening file");return 1;}// 使用 fgets 读取一行文本if (fgets(line, sizeof(line), file) != NULL) {printf("Read line: %s\n", line);} else {printf("Failed to read line.\n");}// 关闭文件fclose(file);return 0;
}
```
在这个例子中,`fgets` 函数会读取 "example.txt" 文件中的一行文本,并将其存储在 `line` 数组中。然后,程序会打印出读取到的文本。
如果文件中的文本超过 `line` 数组的大小,那么超出部分将不会被读取,并且 `fgets` 函数仍然会成功返回。如果文件已经到达文件末尾,`fgets` 函数会读取到空字符串并返回 `NULL`。
———————————————————————————————————————————
-1 本质是整数 所以返回类型需要是整形
读取方式
一个字符一个字符的读取
所有内容一起读取
循环读取
读取的字符最好存起来
不等于eof 也就是继续循环
等于的时候 也就是停止循环
写一个字符读取一个字符 写一堆字符 读取一堆字符
———————————————————————————————————————————
读取函数的返回参数
fgetc
如果读取正常,返回的是读取到字符的ASCII码值
如果读取的过程中遇到文件末尾,或者发生错误,就返回EOF
fgets
如果读取正常,返回的是存储读取到的字符串的字符数组的地址
如果读取的过程中遇到文件末尾,或者发生错误,返回NULL
———————————————————————————————————————————
代码1不是循环读取文本
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
//写入字符串
int main()
{//写入文件FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("foopen:w:");return 1;}fputs("hellow word", pf);fputs("你好世界", pf);for (int i = 0; i < 10; i++){fputs("hellow 世界\n", pf);}fclose(pf);//关闭pf = NULL;//读取文件//重申一遍,文件只有读取之后才能打印出来FILE* ps = fopen("text.txt", "r");if (ps == NULL){perror("fopen:r:");return 1;}//不是循环读取文件char arr[1000] = { 0 };fgets(arr, 100, ps);printf("%s ", arr);fclose(ps);//关闭文件ps = NULL;return 0;
}
这里特地我给出100字节,当然的读取不完的,这里说明单次读取只能读取一行
循环读取可以不遇见NULL之前可以读取全部
———————————————————————————————————————————
代码2循环读取文本
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdio.h>
//写入字符串
int main()
{//写入文件FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("foopen:w:");return 1;}fputs("hellow word", pf);fputs("你好世界", pf);for (int i = 0; i < 10; i++){fputs("hellow 世界\n", pf);}fclose(pf);//关闭pf = NULL;//读取文件//重申一遍,文件只有读取之后才能打印出来FILE* ps = fopen("text.txt", "r");if (ps == NULL){perror("fopen:r:");return 1;}//循环读取//这里循环读取的需要知道的是,只要是循环读取,其实不管是多少字符读取,其实最后都会读取出来//因为你没有遇见,NULL说明你的文本没有读取完毕,如果你是一次直到读取100字符,那么就会一次读取100字符直到读取完毕遇见NULLchar arr[1000] = { 0 };//这里是字符串 或者长的文本,所以接收的时候,需要给一个数组,不能给一个变量 while (fgets(arr, 100, ps) != NULL){printf("%s ", arr);}fclose(ps);//关闭文件ps = NULL;return 0;
}
这里特地我给出100字节,当然的读取不完的,这里说明单次读取只能读取一行
循环读取可以不遇见NULL之前可以读取全部
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fprintf(指定的格式写到文件里面。适用于所有的输出流,可以打印在屏幕上面)+fscanf(指定的格式读取出来,适用于所有的输入流)
fprintf(指定的格式写到文件里面)
两个函数是一样的
打开文件
写文件 fprintf以指定的格式写到信息里面
同时这里是文本的形式写进去的 因为我们都读得懂
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct MyStruct
{char name[20];int age;
};
int main()
{struct MyStruct s = { "张三",23 };FILE* ps = fopen("fprintf.txt", "w");//这里我们进行写入一个文件,没有的话会自动创建一个文件if (ps == NULL){perror("fopen:w:");return 1;}fprintf(ps, "%s %d", s.name, s.age);//以指定格式写入文件fclose(ps);//关闭文件ps = NULL;//指针指向空指针return 0;
}
——————————————————————————————————————————
fscanf(指定的格式读取出来,适用于所有的输入流)
同理这个和scanf是一样的
数组名本身就是地址
fscanf
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct MyStruct
{char name[20];int age;
};
int main()
{struct MyStruct s = { "张三",23 };FILE* ps = fopen("fprintf.txt", "w");if (ps == NULL){perror("fopen:w:");return 1;}//这里是把内容写到文件里面fprintf(ps, "%s %d", s.name, s.age);//写入文件fclose(ps);ps = NULL;//只读,因为你剩下的操作是文件读取,所以这里不行w,但是可以是只读,读取文件FILE* pf = fopen("fprintf.txt", "r");if (pf == NULL){perror("fopen:r:");return 1;}//这里是读取内容,不读取是无法直接打印文件内容的fscanf(pf, "%s %d", s.name, &(s.age));//数组首元素就是地址 不需要取地址 ,此时也就是读取成功printf("%s %d\n", s.name, s.age);//表纯输出流打印文件fprintf(stdout, "%s %d\n", s.name, s.age);//指定输出流,打印文件fclose(pf);pf = NULL;return 0;
}
———————————————————————————————————————————
fprintf(可以打印在屏幕上面)
适用于所有的输出流,可以打印在屏幕上面
也就是你可以用fprintf写写入里面,用fscanf进行读取,再用fprintf进行打印
当然这里前面的参数是文件,我们指向的是文件,然后才能打印出来
stdout(补充说明)
stdout 是 C 标准库中的一个文件流,代表标准输出。标准输出通常指的是计算机屏幕,但它也可以被重定向到其他地方,比如一个文件。在 C 语言中,stdout 用于打印程序的输出信息,比如 printf 函数和 fprintf 函数输出的内容。
当你调用 printf 或者 fprintf 函数时,如果不指定文件指针参数,这些函数会默认使用 stdout 作为输出目标。例如:
printf("Hello, World!");
这行代码会将在 stdout 上打印 "Hello, World!"。默认情况下,stdout 指向控制台(屏幕),所以你会在屏幕上看到输出。
你还可以将 stdout 重定向到文件。例如,你可以使用系统命令行将输出重定向到文件:
./program > output.txt
这会使得 program 程序的标准输出被重定向到 output.txt 文件,而不会在屏幕上显示任何内容。
在 C 程序中,你也可以显式地将输出写入 stdout:
fprintf(stdout, "This will go to the screen or a file if redirected.\n");
因为这个不是标准输出流,是指定输出流,所以我们可以指定格式。
这里我们发现我们可以用fprintf函数打印出来
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct MyStruct
{char name[20];int age;
};
int main()
{struct MyStruct s = { "张三",23 };FILE* ps = fopen("fprintf.txt", "w");if (ps == NULL){perror("fopen:w:");return 1;}//这里是把内容写到文件里面fprintf(ps, "%s %d", s.name, s.age);//写入文件fclose(ps);ps = NULL;//只读,因为你剩下的操作是文件读取,所以这里不行w,但是可以是只读,读取文件FILE* pf = fopen("fprintf.txt", "r");if (pf == NULL){perror("fopen:r:");return 1;}//这里是读取内容,不读取是无法直接打印文件内容的fscanf(pf, "%s %d", s.name, &(s.age));//数组首元素就是地址 不需要取地址 printf("%s %d\n", s.name, s.age);//表纯输出流打印文件fprintf(stdout, "%s %d\n", s.name, s.age);//指定输出流,打印文件fclose(pf);pf = NULL;return 0;
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
sprintf(指定格式转化成字符串)+sscanf(字符串转化成指定格式)
sprintf(指定格式转化成字符串)
格式化的数据转化成字符串sprintf
sprintf
是一个在 C 语言中定义的函数,它的作用是将格式化的字符串和参数转换成字符串,并将结果存储在指定的字符数组中。因此,sprintf
可以用来将文件中的文档内容转化成字符串,也可以用来将刚编写的结构体代码转化为字符串。具体使用方式取决于程序的具体需求。
这里已经转化为字符串
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct MyStruct
{char name[20];int age;
};
int main()
{struct MyStruct s = { "张三",23 };FILE* ps = fopen("fprintf.txt", "w");if (ps == NULL){perror("fopen:w:");return 1;}//这里是把内容写到文件里面fprintf(ps, "%s %d", s.name, s.age);//写入文件fclose(ps);ps = NULL;//只读,因为你剩下的操作是文件读取,所以这里不行w,但是可以是只读,读取文件FILE* pf = fopen("fprintf.txt", "r");if (pf == NULL){perror("fopen:r:");return 1;}//这里是读取内容,不读取是无法直接打印文件内容的fscanf(pf, "%s %d", s.name, &(s.age));//数组首元素就是地址 不需要取地址 //转化为字符串的形式char buf[100] = { 0 };//因为是转化成字符串的形式,所以需要用一个数组进行接收sprintf(buf, "%s %d", s.name, s.age);printf("字符串打印: %s \n", buf);fclose(pf);pf = NULL;return 0;
}
———————————————————————————————————————————
sscanf(字符串转化成指定格式)
sscanf语法说明
这里是 从结构体读取数据
这里是从buf里面读取
所以sscanf也就是前面加上一个需要读取的名称
两次打印的对比,一样的,但是此时已经不是字符串的格式已经是指定的格式了
代码总结
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct MyStruct
{char name[20];int age;
};
int main()
{struct MyStruct s = { "张三",23 };FILE* ps = fopen("fprintf.txt", "w");if (ps == NULL){perror("fopen:w:");return 1;}//这里是把内容写到文件里面fprintf(ps, "%s %d", s.name, s.age);//写入文件fclose(ps);ps = NULL;//只读,因为你剩下的操作是文件读取,所以这里不行w,但是可以是只读,读取文件FILE* pf = fopen("fprintf.txt", "r");if (pf == NULL){perror("fopen:r:");return 1;}//这里是读取内容,不读取是无法直接打印文件内容的fscanf(pf, "%s %d", s.name, &(s.age));//数组首元素就是地址 不需要取地址 //转化为字符串的形式char buf[100] = { 0 };//因为是转化成字符串的形式,所以需要用一个数组进行接收sprintf(buf, "%s %d", s.name, s.age);printf("字符串打印: %s \n", buf);//字符串转化为带有格式的形式sscanf(buf, "%s %d", s.name, &(s.age));//我们这里还是这个格式, 把数组转化成格式给到结构体里面fprintf(stdout, "按照格式打印:%s %d\n", s.name, s.age);//指定输出流,打印文件fclose(pf);pf = NULL;return 0;
}
sscanf(buf, "%s %d", s.name, &(s.age));//我们这里还是这个格式, 把数组转化成格式给到结构体里面,buf是字符串,格式化的输入到结构体里面
———————————————————————————————————————————
下面这个是把bit格式化的读取到buf里面 ,简单的说也就是后面放置的是可以接收的一个空的空间、
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
printf(标准输出流)+scanf(标准输入流)+函数的总结
这里说明一下,printf和scanf经常使用,就不详细举例,直接进行说明。
在C语言中,printf、fprintf、sprintf、scanf、sscanf和fscanf是用于输入和输出数据的函数。下面是它们的区别和通常的使用场景:
- printf
-
- printf函数用于将格式化的数据输出到标准输出(通常是终端或控制台)。
- 它不会在输出字符串的末尾添加换行符,所以如果需要换行,需要在格式字符串中显式包含\n。
- 示例:printf("Hello, World!\n"
- fprintf
-
- fprintf函数用于将格式化的数据输出到任意指定的文件指针(FILE *)。
- 它可以将数据输出到文件、网络流等。
- 示例:FILE *fp = fopen("file.txt", "w"); fprintf(fp, "Hello, World!\n"); fclose(fp);
- sprintf
-
- sprintf函数用于将格式化的数据输出到一个字符数组或字符串。简单的说就是转化成字符串格式
- 它不会在输出字符串的末尾添加换行符。
- 示例:char buffer[100]; sprintf(buffer, "Hello, World!\n"); printf("%s", buffer);
- scanf
-
- scanf函数用于从标准输入(通常是键盘)读取格式化的数据。
- 它等待用户输入,并根据指定的格式解析输入的数据。
- 示例:int num; scanf("%d", &num); printf("You entered: %d\n", num);
- sscanf
-
- sscanf函数用于从字符串中读取格式化的数据。可以把字符串转化为任何你需要的格式
- 它将字符串中的数据按照指定的格式解析成变量。
- 示例:char str[] = "1234"; int num; sscanf(str, "%d", &num); printf("You entered: %d\n", num);
- 可以把字符串转化为任何你需要的格式
- fscanf
-
- fscanf函数用于从任意指定的文件指针读取格式化的数据。
- 它可以从文件、网络流等读取数据。
- 示例:FILE *fp = fopen("file.txt", "r"); int num; fscanf(fp, "%d", &num); fclose(fp); printf("You entered: %d\n", num);
格式化的数据就是带有格式的数据
比如整形 字符 浮点型
看到结构体不方便 需要转化为字符串 那就是 sprintf
需要转化回来 那就用sscanf, fscanf
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fwrite(二进制形式写进去,写wb)
语法格式
在 C 语言中,`fwrite()` 函数用于向文件写入数据。它的语法格式如下:
```c
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
```
参数说明
1. `ptr`:必需。指向要写入数据的指针。(内容)(arr)
2. `size`:必需。每个数据项的大小(以字节为单位)。(大小)(sizeof(arr[0]))
3. `count`:必需。要写入的数据项的数量。(写入的长度)(sz)
4. `stream`:必需。文件指针,指向目标文件。(写入的目标文件)(pf)
返回值:
- 成功时,返回写入的字节数。
- 出错时,返回 `EOF`。
示例代码:
```c
#include <stdio.h>
int main() {FILE *fp;char str[] = "Hello, World!";size_t len = strlen(str);fp = fopen("example.txt", "w"); // 打开文件用于写入if (fp == NULL) {perror("Error opening file");return 1;}size_t written = fwrite(str, sizeof(char), len, fp); // 写入字符串if (written != len) {perror("Error writing to file");}fclose(fp); // 关闭文件return 0;
}
```
在这个示例中,我们打开了一个名为 "example.txt" 的文件,然后尝试将字符串 "Hello, World!" 写入该文件。`fwrite()` 函数返回实际写入的字节数,我们可以将其与要写入的字符串长度进行比较,以检查是否写入成功。如果写入失败,将通过 `perror` 函数打印错误信息。最后,我们关闭文件并返回。
———————————————————————————————————————————
fwrite(地址,一个元素多大,几个元素,写到哪个流里面)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{FILE* pf = fopen("二进制文件的操作", "wb");if (pf == NULL){perror("二进制打开错误:wb:");return 1;}int arr[] = { 1,2,3,4,5,6,7,8,9,0,12,3,123,123,1,23,231,123,123,312,123,213 };int sz = sizeof(arr) / sizeof(arr[0]);fwrite(arr, sizeof(arr[0]), sz, pf);fclose(pf);pf == NULL;return 0;
}
这里我们可以看到我们把二进制的文件写到里面去了
这个函数只要记着
fwrite(地址,一个元素多大,几个元素,写到哪个文件里面)
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fread(读取二进制文件)
语法格式 
说明
`fread()` 函数是 C 语言标准库中的一个函数,用于从文件指针指向的文件中读取数据。它定义在 `<stdio.h>` 头文件中。`fread()` 函数用于读取二进制文件,因为它的读取操作不会转换字符,即读取的字节序列与存储在文件中的序列完全一致。
`fread()` 函数的语法格式如下:
```c
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
```
参数说明:
- `void *ptr`: 指向要读取数据的内存块的指针。函数将从文件读取的数据存储到这个指针指向的内存块中。
- `size_t size`: 每个数据项的大小(以字节为单位)。
- `size_t nmemb`: 要读取的数据项的数量。
- `FILE *stream`: 指向 `FILE` 对象的指针,该 `FILE` 对象标识了要读取的文件。
`fread()` 函数返回读取的字节总数,如果读取失败或到达文件末尾,它可能返回 EOF。
示例代码:
```c
#include <stdio.h>
int main() {FILE *fp;int data;int itemsRead;fp = fopen("data.bin", "rb"); // 打开文件用于二进制读取if (fp == NULL) {perror("Error opening file");return -1;}// 分配足够的内存来存储一个整数data = (int)malloc(sizeof(int));itemsRead = fread(data, sizeof(int), 1, fp); // 读取一个整数if (itemsRead == 1) {printf("Read data: %d\n", *data);} else {printf("Failed to read data\n");}fclose(fp);free(data);return 0;
}
在上面的代码中,`fread()` 函数被用来从名为 "data.bin" 的文件中读取一个整数。这段代码假设文件中只有一个整数,并且使用 `malloc()` 分配了足够的内存来存储这个整数。读取完成后,代码打印出读取的整数值。记得在读取文件后关闭文件流,使用 `fclose()` 函数可以做到这一点。同时,使用 `free()` 函数释放用 `malloc()` 分配的内存是很重要的,以避免内存泄漏。
———————————————————————————————————————————
代码图解
版本1
返回值参数是成功读取的元素
就是你让我读取100个 实际文件里面只有5个 那我只能读取5个 并且打印
循环读取 这个打印出来也是12345
版本2
这里是i++等于存到arr里面去了,也就是实际你打印出的是arr,也就是不存在最后指针指向的位置跑到后面,导致空间无法释放
while里面取地址取出的是首元素的地址,pf指向的文件放到了arr里面,所以才说,这里++,实际上,++的是arr数组里面的元素,因为arr已经接收了元素。剩下的就是打印
但是这里还是一个问题就是,不管你读取多少元素,最后都会把arr可以放下的所有的元素进行读取。
代码总结
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{FILE* pf = fopen("二进制文件的操作", "wb");//wb写入二进制文件if (pf == NULL){perror("二进制打开错误:wb:");return 1;}int arr[] = { 1,2,3,4,5,6,7,8,9,0,12,3,123,123,1,23,231,123,123,312,123,213 };int sz = sizeof(arr) / sizeof(arr[0]);fwrite(arr, sizeof(arr[0]), sz, pf);fclose(pf);pf == NULL;int str[1000] = { 0 };FILE* ps = fopen("二进制文件的操作", "rb");//rb读二进制文件if (ps == NULL){perror("二进制打开错误:wb:");return 1;}//也就是//存储的地方,单个大小,读取大小,文件流fread(str, sizeof(int), 400, ps);//以字节为单位 40个字节也就是10个整形for (int i = 0; i < 100; i++){printf("%d ", str[i]);}fclose(ps);ps == NULL;return 0;
}
超出读取范围,那么就会读取0字节,也就是后面的地址 ,但是我们并没有利用,所以才没有出问题,是不建议这样的,这里只是举例。
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
fseek(根据文件偏移位置读取文件)
语法说明
`fseek` 函数是 C 语言标准库中的一个函数,用于在文件指针指向的流中设置读/写位置。其语法格式如下:
```c
#include <stdio.h>
int fseek(FILE *stream, long offset, int origin);
```
参数说明如下:
`FILE *stream`:指向 `FILE` 对象的指针,该 `FILE` 对象标识了要进行操作的流。
- `long offset`:表示要移动的位数。如果 `offset` 是正数,则文件读/写位置向前移动 `offset` 字节;如果是负数,则向后移动。
- `int origin`:表示 `offset` 的起始点,可以是以下三个常量之一:
- `SEEK_SET`:从文件的开头开始计算 `offset`(默认值)。
- `SEEK_CUR`:从当前的文件读/写位置开始计算 `offset`。
- `SEEK_END`:从文件的末尾开始计算 `offset`。
该函数执行成功时返回 `0`,失败时返回 `-1`。如果发生错误,可以通过 `ferror` 函数检查流是否出错。
请注意,`fseek` 函数对二进制文件和文本文件都是有效的。但是在文本文件中,由于需要考虑字符编码和换行符等因素,`fseek` 可能不会按照预期工作,特别是在不同平台之间移植代码时。
———————————————————————————————————————————
首先我们得有一个概念,读取文件需要有一个接收值。
fseek文件的当前位置SEEK_SET
SEEK_END倒着往前偏移
这几个都是找到f
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("ofpen:r:");return 1;}int ret = 0;fseek(pf, 4, SEEK_SET);//起始位置ret = fgetc(pf);printf("%c ", ret);fseek(pf, 4, SEEK_CUR);//文件指针当前位置ret = fgetc(pf);printf("%c ", ret);fseek(pf, -9, SEEK_END);//文件末尾开始计算,所以这里是负数,从后往前计算ret = fgetc(pf);printf("%c ", ret);fclose(pf);pf == NULL;return 0;
}
这个函数的目的不是进行打印而是找到偏移量,那么此时就可以进行读取到你需要的数值
比如你可以读取从前往后第3个字节那一个字节,那么你就可以使用这个函数,并且使用读取一个字节的函数打印出来。
如果你需要的是,从前往后第三个字节之后的字节,那么你就可以使用这个函数,配套使用读取函数,进行循环读取打印即可。
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
rewind(回到起始位置)
语法格式
在 C 语言中,`rewind` 函数用于将文件指针定位到文件的开头。它的语法格式如下:
```c
#include <stdio.h>
rewind(FILE *stream);
```
参数
`stream` 是指向 `FILE` 对象的指针,该对象标识了要重置的文件流。调用 `rewind` 函数后,文件流的位置指针将被重置到文件的开头,就像在使用 `fseek(stream, 0, SEEK_SET)` 一样。
下面是一个使用 `rewind` 的例子:
```c
#include <stdio.h>
int main() {FILE *fp;char buffer[100];fp = fopen("example.txt", "r"); // 打开文件if (fp == NULL) {// 处理错误}fread(buffer, sizeof(char), 100, fp); // 读取文件内容rewind(fp); // 将文件指针重置到文件开头fread(buffer, sizeof(char), 100, fp); // 重新读取文件内容fclose(fp); // 关闭文件return 0;
}
```
在这个例子中,`rewind` 函数被用来在读取文件内容后,将文件指针倒回到文件的开头,以便可以再次读取文件的内容。
———————————————————————————————————————————
此时读取到f
我们可以用rewind回到起始位置
也就是直接输入文件流,就可以直接回到函数所在的起始位置
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("ofpen:r:");return 1;}int ret = 0;fseek(pf, 4, SEEK_SET);//起始位置ret = fgetc(pf);printf("%c ", ret);fseek(pf, 4, SEEK_CUR);//文件指针当前位置ret = fgetc(pf);printf("%c ", ret);fseek(pf, -9, SEEK_END);//文件末尾开始计算,所以这里是负数,从后往前计算ret = fgetc(pf);printf("%c \n", ret);rewind(pf);//配合使用,返回文件起始位置ret = fgetc(pf);printf("返回起始位置:%c ", ret);fclose(pf);pf == NULL;return 0;
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
ftell(获取当前位置)
语法格式
在 C 语言中,`ftell` 函数用于获取当前文件指针的位置,以字节为单位。它的语法格式如下:
```c
#include <stdio.h>
long ftell(FILE *stream);
```
参数
`stream` 是指向 `FILE` 对象的指针,该对象标识了要查询位置的文件流。函数返回当前文件指针的位置,如果出错,则返回 `-1`。
下面是一个使用 `ftell` 的例子:
```c
#include <stdio.h>
int main() {FILE *fp;long position;char buffer[100];fp = fopen("example.txt", "r"); // 打开文件if (fp == NULL) {// 处理错误}fread(buffer, sizeof(char), 100, fp); // 读取文件内容position = ftell(fp); // 获取当前文件指针的位置printf("当前文件指针的位置是:%ld\n", position);fclose(fp); // 关闭文件return 0;
}
```
在这个例子中,`ftell` 函数被用来获取在读取文件内容后,文件指针当前位置的信息。然后,这个位置被打印出来。请注意,`ftell` 的返回值是一个 `long` 类型的值,因此它可以表示非常大的数字,这取决于文件的大小。
———————————————————————————————————————————
ftell 函数是C语言标准库中的一个函数,用于获取当前文件位置指针的位置。这个位置是一个长整型数,表示从文件开始的字节偏移量。
换句话说,ftell 可以告诉你当前读/写文件的位置在哪里,这对于确定文件中某个特定位置的读/写操作非常有用。
函数原型定义如下:
long ftell(FILE *stream);
其中 stream 是指向 FILE 对象的指针,该 FILE 对象标识了要查询的流。
使用 ftell 函数时,可以进行以下操作:
- 确定当前的文件位置。
- 在读取或写入文件后,检查位置是否如预期。
- 在处理大文件时,可以利用 ftell 来判断是否已经到达文件末尾。
请注意,ftell 返回的值是在调用 fseek 之前或与之关联的文件操作之后的文件位置。如果在 ftell 之后对文件进行任何操作(如读取、写入或定位),则返回的值将不再准确。
在使用 ftell 时,还应当注意平台的差异,因为 ftell 的行为可能会受到操作系统和文件系统的影响。
从前到后用于获取当前文件位置指针的位置。这里是9,这里返回的是文件的偏移量
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("ofpen:r:");return 1;}int ret = 0;fseek(pf, 4, SEEK_SET);//起始位置ret = fgetc(pf);printf("%c ", ret);fseek(pf, 4, SEEK_CUR);//文件指针当前位置ret = fgetc(pf);printf("%c ", ret);fseek(pf, -9, SEEK_END);//文件末尾开始计算,所以这里是负数,从后往前计算ret = fgetc(pf);printf("%c \n", ret);rewind(pf);//配合使用,返回文件起始位置ret = fgetc(pf);printf("返回起始位置:%c \n", ret);int s = 0;//这里需要进行一个返回值进行接收s=ftell(pf);//这里我们已经知道返回了初始位置printf("当前位置:%d \n", s);//所以当前位置是1//此时神奇的来了,上面我们已经返回文件初始位置了,我们可以根据偏移量读取位置//因为是从前往后计算当前位置的,同时利用fseek函数把数值移动到最后一位,并且不进行偏移fseek(pf, 0, SEEK_END);//文件末尾开始计算,不进行偏移int a = 0;a = ftell(pf);printf("文件总长度:%d \n", a);fclose(pf);pf == NULL;return 0;
}
可以计算文件总的长度
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
feof(文件读取结束的判定)
语法格式
`feof` 函数用于在文件读取操作中判断是否到达文件末尾。如果到达文件末尾,则返回非零值;否则返回零。
语法格式如下:
```c
#include <stdio.h>
int feof(FILE *stream);
```
参数
`stream` 是指向 `FILE` 对象的指针,该 `FILE` 对象标识了要检查的流。通常,这个参数是通过 `fopen` 函数返回的。
函数返回值:
- 如果已到达流 `stream` 的文件末尾,则返回非零值。
- 如果 `stream` 未打开或不是一个有效文件流,则行为未定义。
- 如果没有到达文件末尾,则返回零。
在使用 `feof` 函数时,通常与读取操作配合使用,例如 `fread` 或 `fgets`,以检查是否在读取过程中到达文件末尾。
简单的说 是来根据返回值来进行判断的
fgetc 在读取到文件末尾时会返回 EOF,这可以通过比较 ch 和 EOF 来判断是否到达文件末尾。在大多数实现中,EOF 是一个非零值
———————————————————————————————————————————
feof文件读取结束的判定
这个不是判断文件是不是结束 是已经结束判断的原因是什么
是结束了 ?还是出错了?
如果是 正常读取结束那么就会进行判定,走if
如果不是正常读取结束,那么此时就会走else
从而打印出错误信息
不要用错了
也就是判断返回值是不是空指针
———————————————————————————————————————————
总结
文本文件
非零 就是正常的
———————————————————————————————————————————
错误的文件描述
也就是返回eof是非零值,也就是符合条件为真
否则为假,不满足条件,打印错误信息
———————————————————————————————————————————
做题
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
文件缓冲区
设置缓冲区的目的就是提高效率
举例子来说的话 就是问老师问题,全班70人 ,每个人都要问,一会一个一会一个,那老师说了,你这样存五个问题再来。大家都可以问问题了。
这个代码可以感受到缓冲区的存在
刷新的意义是把缓冲区的文件放到内存里面去
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
文件操作函数的综合使用 (例题)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{//创建打开文件 只读//写进去FILE* ss = fopen("data.txt", "w");if (ss == NULL){perror("fopen:w:"); return 1;}fputs("hellow JJS", ss);fclose(ss);ss = NULL;//创建打开文件 只读FILE* ps = fopen("data.txt", "r");if (ps == NULL){perror("fopen:w:");return 1;}//打开文件 创建文件 FILE* pf = fopen("data_copy.txt", "w");if (pf == NULL){perror("fopen:w:");return 1;}//拷贝文件//一边读一边写,char ch = 0;//这里赋值给,ch 。ch while ((ch = fgetc(ps)) != EOF){fputc(ch, pf);}fclose(ps);fclose(pf);ps = NULL;pf = NULL;return 0;
}
//data 原始被拷贝文件
// 写文件 w把文件创建 =ss 负责接收
//读取创创建的文件 ps读取文件
//
//拷贝文件
//data_copy 拷贝文件到这个文件里面
// pf 创建被拷贝的文件 首先创建 data_copy的文件 w的形式写进去
//
//
// 循环 把写入的data的字符 输入到data_copy里面
// 首先是读取 也就是 fgetc 读取到eof之前都可循环
// 然后就是输入字符 也就是fputc函数
// 循环输入
// 这里是把 循环输出的函数 遍历 赋值给ch
// 此时 也就是fputc(ch,pf)
// 也就是把ch里面的遍历字符 输入到data_copy 也就是pf
//完成作业