✨个人主页: 熬夜学编程的小林
💗系列专栏: 【C语言详解】 【数据结构详解】
文件操作
1、文件的顺序读写
1.1、顺序读写函数介绍
1.1.1、fgetc 与 fputc
1.1.2、fgets 与 fputs
1.1.3、fscanf 与 fprintf
1.1.4、fread 与 fwrite
1.2、对比一组函数
总结
1、文件的顺序读写
1.1、顺序读写函数介绍
函数名 | 功能 | 适用于 |
fgetc | 字符输入函数 | 所有输入流 |
fputc | 字符输出函数 | 所有输出流 |
fgets | 文本行输入函数 | 所有输入流 |
fputs | 文本行输出函数 | 所有输出流 |
fscanf | 格式化输入函数 | 所有输入流 |
fprintf | 格式化输出函数 | 所有输出流 |
fread | 二进制输入 | 文件 |
fwrite | 二进制输出 | 文件 |
上面说的适用于所有输入流⼀般指适用于标准输入流和其他输入流(如文件输入流);所有输出流⼀般指适用于标准输出流和其他输出流(如文件输出流)
1.1.1、fgetc 与 fputc
int fputc ( int character, FILE * stream );
将字符写入流。
将字符写入流并推进位置指示器。字符被写在流的内部位置指示器指示的位置,然后自动前进一个。
举个例子:
#include <stdio.h>
int main()
{//打开文件FILE* pf = fopen("test.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;
}
VS执行此代码之后不会输出内容,需要去找到对应文件验证。
int fgetc ( FILE * stream );
从流中获取字符。
返回指定流的内部文件位置指示器当前指向的字符。然后,内部文件位置指示器将前进到下一个字符。如果流在调用时位于文件末尾,则该函数将返回 EOF 并设置流的文件末尾指示符 (feof)。
如果发生读取错误,该函数将返回 EOF 并设置流的错误指示器 (ferror)。
fgetc 和 getc 是等效的,只是 getc 在某些库中可以作为宏实现。
举个例子:
#include <stdio.h>
int main()
{//打开文件FILE* pf = fopen("test.txt", "r");//文件操作if (pf == NULL){perror("fopen");return 1;}//从pf流中读取数据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);//关闭文件fclose(pf);pf = NULL;return 0;
}
输出结果与对应文件内容比较如下图:
1.1.2、fgets 与 fputs
int fputs ( const char * str, FILE * stream );
将字符串写入流。
将 str 指向的 C 字符串写入流。该函数从指定的地址 (str) 开始复制,直到到达终止 null 字符 ('0')。此终止 null 字符不会复制到流中。
请注意,fputs 与 puts 的不同之处不仅在于可以指定目标流,而且 fputs 不会写入其他字符,而 puts 会自动在末尾附加换行符。
举个例子:
#include <stdio.h>
int main()
{//打开文件FILE* pf = fopen("test1.txt", "w");//文件操作if (pf == NULL){perror("fopen");return 1;}//将字符串写入文件fputs("abcdef", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
执行该代码之后的文件结果如下图:
char * fgets ( char * str, int num, FILE * stream );
//str为接受数据的地址
从流中获取字符串。
从流中读取字符,并将它们作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件末尾,以先到者为准。换行符使 fgets 停止读取,但它被函数视为有效字符,并包含在复制到 str 的字符串中。
终止 null 字符会自动追加到复制到 str 的字符之后。
请注意,fgets 与 gets 有很大不同:fgets 不仅接受 stream 参数,还允许指定 str 的最大大小,并在字符串中包含任何结束换行符。
#include <stdio.h>
int main()
{//打开文件FILE* pf = fopen("test1.txt", "r");//文件操作if (pf == NULL){perror("fopen");return 1;}char arr[100] = { 0 };//将文件中读取字符串fgets(arr, 5, pf);printf("%s\n", arr);//关闭文件fclose(pf);pf = NULL;return 0;
}
测试结果如下图:
1.1.3、fscanf 与 fprintf
int fprintf ( FILE * stream, const char * format, ... );
将格式化的数据写入流。
将按格式指向的 C 字符串写入流。如果 format 包含格式说明符(以 % 开头的子序列),则格式后面的附加参数将被格式化并插入到生成的字符串中,以替换它们各自的说明符。在 format 参数之后,该函数至少需要与 format 指定的其他参数一样多的附加参数。
举个例子:
#include <stdio.h>
struct S
{float f;char c;int n;
};
int main()
{struct S s = { 5.2f,'c',52 };//结构体初始化//打开文件FILE* pf = fopen("test1.txt", "w");//文件操作if (pf == NULL){perror("fopen");return 1;}//写文件fprintf(pf, "%f-%c-%d", s.f, s.c, s.n);//关闭文件fclose(pf);pf = NULL;return 0;
}
代码测试:
int fscanf ( FILE * stream, const char * format, ... );
从流中读取格式化的数据。
从流中读取数据,并根据参数格式将数据存储到其他参数所指向的位置。附加参数应指向已分配的对象,该对象由格式字符串中的相应格式说明符指定。
举个例子:
#include <stdio.h>
struct S
{float f;char c;int n;
};
int main()
{struct S s = { 0 };//打开文件FILE* pf = fopen("test1.txt", "r");//文件操作if (pf == NULL){perror("fopen");return 1;}//读文件fscanf(pf, "%f-%c-%d", &(s.f), &(s.c), &(s.n));printf("%f-%c-%d\n", s.f, s.c, s.n);//关闭文件fclose(pf);pf = NULL;return 0;
}
测试代码:
1.1.4、fread 与 fwrite
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
将数据块写入流中。
从 ptr 指向的内存块写入一个 count 元素数组,每个元素的大小为 Bytes 字节。流的位置指示器按写入的总字节数前进。
在内部,该函数将 ptr 指向的块解释为无符号字符类型的 (size*count) 元素数组,并按顺序将它们写入流式处理,就好像为每个字节调用了 fputc 一样。
举个例子:
#include <stdio.h>
int main()
{int arr[] = { 0,1,2,3,4,5,6,7,8,9 };//打开文件FILE* pf = fopen("data.txt", "wb");//文件操作if (pf == NULL){perror("fopen");return 1;}//二进制写文件fwrite(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
测试代码:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
从流中读取数据块。
从流中读取 count 元素的数组,每个元素的大小为 bytes,并将它们存储在 ptr 指定的内存块中。流的位置指示器按读取的总字节数前进。
如果成功,读取的总字节数为 (size*count)。
举个例子:
#include <stdio.h>
int main()
{int arr[10] = { 0 };//打开文件FILE* pf = fopen("data.txt", "rb");//文件操作if (pf == NULL){perror("fopen");return 1;}//二进制写文件fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}//关闭文件fclose(pf);pf = NULL;return 0;
}
测试代码:
1.2、对比一组函数
scanf / fscanf / sscanf
int scanf ( const char * format, ... );
//使用键盘输入信息
int fscanf ( FILE * stream, const char * format, ... );
//将stream中的信息写入后面格式化函数中
int sscanf ( const char* s, const char * format, ... );
//将字符串信息转化为格式化信息
printf / fprintf / sprintf
int printf ( const char * format, ... );
//打印信息到屏幕
int fprintf ( FILE * stream, const char * format, ... );
//将后面格式化信息写到stream中
int sprintf ( char * str, const char * format, ... );
//将格式化数据转化为字符串数据
总结
本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!