文章目录
前言
据我所知,大部分C语言的初学者在使用C语言的场景都是在刷网站上的算法题,而网站上的算法题基本上是不会使用文件相关的操作的,所以初学者往往会忽略掉对于C语言对于文件的操作指令。本节将对C语言的文件操作指令做一个汇总。
一、文件加工厂
1.fopen()
函数原型:FILE *fopen(char const *name,char const *mode);//参数分别为:文件名和打开文件的方式
打开文件的方式如下:
fopen()的返回值是一个文件类型指针FILE *。如果文件打开失败,则返回NULL。
2.fclose()
函数原型:int fclose(FILE *fp);
参数为文件指针。有一个整数返回值,可以用一个整型变量接收,也可以不接收,当文件关闭成功时返回值为0,否则返回EOF。
3.fgetc()
函数原型:int fgetc(FILE *fp);
从指定文件中读取一个字符,返回值为从文件中读取出的字符的ASCII码值,若读到文件结束符则函数返回文件结束标志EOF。
4.fputc()
函数原型:int fputc(int c,FILE *fp);
将字符c传入到文件fp当中,虽然函数原型中形参为int类型,但是可以传入字符char类型的变量。返回值为字符c的ASCII码值,写入失败返回EOF。
5.fgets()
函数原型:char *fgets(char *s,int n,FILE *fp);
从指定的文件中读取字符串。函数有3个参数,第一个参数s为暂存读出字符串的缓冲区,第二个参数n为一次读取的最大字符个数,fp为文件指针。
fgets()从fp中读取字符,当读到换行回车符、文件末尾、满n-1个字符时在字符串末尾加上一个’\0’,把它们存放到字符数组s中,并返回结果为s的首地址。若在任何字符读取前就达到了文件末尾,fgets()返回NULL指针用于检查是否读到文件尾。
6.fputs()
函数原型:int *fputs(const char *s,FILE *fp);
向文件中写入字符串s,字符串应以’\0’结尾。写入成功返回0,写入失败返回EOF,返回值可接收也可不接收。
7.fread()
函数原型:unsigned fread(void *s,unsigned size,unsigned count,FILE *fp)
这个函数一般用于对二进制文件进行操作,此外用于二进制文件操作的函数还有fwrite()、fseek()。
fread()的功能是从文件中读取出一组数据。函数有4个参数,第一个参数为从文件读取出的数据应存入的地址,第二个参数size为读出的每个数据块的字节数大小,第三个参数count为允许读出多少个大小为size的数据块的个数,第四个参数为文件指针。返回值为实际读出的数据块个数。
8.fwrite()
函数原型:unsigned fwrite(const void *s,unsigned size,unsigned count,FILE *fp);
向文件中写入一组数据。它的参数形式与fread()相同,所以不再赘述,参考fread()的参数格式即可。返回值为实际写入的数据块个数。
9.fprintf()
函数原型:int fprintf(FILE *fp,const char *format,…);
fprintf()的使用和printf()十分相似。不同点在于printf()的输出对象是终端,而fprintf()的输出对象是文件,并且fprintf()要传入的参数有文件指针,其它格式与printf()相同。
10.fscanf()
函数原型:int fscanf(FILE *fp,const char *format,…);
fscanf()与scanf()相似,在用法上可以参考fprintf()。
但由于fprintf()和fscanf()对文件进行读写时,输入要将ASCII码转换成二进制数,输出要将二进制数转换成字符,所以时间开销比较大,所以一般不建议使用fprintf()和fscanf()。
11.fseek()
函数原型:int fseek(FILE *fp,long offset,int from);
用于对文件指针进行重定位。
之前的文件操作函数都是从头开始对文件进行顺序读写的,这是由于文件指针开始时都是指向文件头,然后不断移动到下一个字符。而fseek()可以将文件指针定位到用户指定的位置开始对文件进行读写操作,从而实现对文件的随机读写。
fseek()有三个参数,第一个参数为要读写的文件,第二个参数offset为位移量,它是以起始点from为基点,向前移动的字节数,第三个参数from为定位起始点。
from的取值有如下几种:
一定要注意,fseek()只能用于二进制文件,对文本文件的定位会产生混乱!!
12.rewind()
函数原型:void rewind(FILE *fp);
使文件指针返回到文件开头。
13.ftell()
函数原型:long ftell(FILE *fp);
得到文件指针当前位置,用相对于文件头的位移量来表示。出错时返回-1。
这个函数一般搭配fseek()来使用,将ftell()的返回值作为fseek()的offset参数,此时fseek()的from应为SEEK_SET。
14.feof()
函数原型:int feof(FILE *fp);
判断当前文件指针是否读到文件尾,若是则返回值为真,否则返回值为0。
二、学以致用
接下来通过一些练习来巩固一下以上提到的文件操作函数。
例一
题目:从键盘输入3个关于图书的数据,存入文件,再从文件中取出输出显示到屏幕上。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 3
/*图书数据结构体,并定义全局数组BOOK_ARRAY*/
struct book_info {
char name[20];//书本名字
char author[20];//书本作者
char publisher[20];//书本出版商
}BOOK_ARRAY[MAXSIZE];
int WriteFile(const char *WFile);
int ReadFile(const char *RFile);
int main() {
const char* File = "MyBookFile.txt";
for (int i = 0; i < MAXSIZE; i++) {
printf("Please input the information of number%d book:\n", i + 1);
scanf("%s %s %s", &BOOK_ARRAY[i].name, &BOOK_ARRAY[i].author, &BOOK_ARRAY[i].publisher);
}
if (WriteFile(File)) {
ReadFile(File);
}
return 0;
}
//将BOOK_ARRAY中的数据写入到WFile当中,若写入成功返回1,不成功返回0
int WriteFile(const char* WFile) {
FILE* fwt;
//以写入方式打开WFile,文件指针fwt指向WFile的文件头
if ((fwt = fopen(WFile, "w")) == NULL) {
printf("open File error\n");
return 0;
}
for (int i = 0; i < MAXSIZE; i++) {
//将BOOK_ARRAY写入fwt,每个数据块大小为一个结构体的sizeof,若写入的数据块个数不为1,则报错
if (fwrite(&BOOK_ARRAY[i], sizeof(book_info), 1, fwt) != 1) {
printf("write File error\n");
return 0;
}
}
fclose(fwt);
return 1;
}
int ReadFile(const char* RFile) {
FILE* frt;
//以读取方式打开RFile,文件指针fwt指向WFile的文件头
if ((frt = fopen(RFile, "r")) == NULL) {
printf("open File error\n");
return 0;
}
for (int i = 0; i < MAXSIZE; i++) {
fread(&BOOK_ARRAY[i], sizeof(book_info), 1, frt);
printf("number:%d\tname:%s\tauthor:%s\tpublisher:%s\n", i + 1, BOOK_ARRAY[i].name, BOOK_ARRAY[i].author, BOOK_ARRAY[i].publisher);
}
fclose(frt);
return 1;
}
例二
题目:合并两个已按递增排序的整数文件成为一个按递增排序的文件
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]){
//读取的第一个文件为fp1,读取的第二个文件为fp2,写入文件为fp3
FILE *fp1,*fp2,*fp3;
if(argc!=4){
printf("The number of arguments error\n");
return -1;
}
if((fp1 = fopen(argv[1],"r"))==NULL){
printf("open File1 error\n");
return -1;
}
if((fp2 = fopen(argv[2],"r"))==NULL){
printf("open File2 error\n");
return -1;
}
if((fp3 = fopen(argv[3],"w+"))==NULL){
printf("open File3 error\n");
return -1;
}
//fp1中读出的数字为a1,fp2中读出的数字为a2
int a1,a2;
fread(&a1,sizeof(int),1,fp1);
fread(&a2,sizeof(int),1,fp2);
while(!feof(fp1)&&!feof(fp2)){
if(a1<a2){
fwrite(&a1,sizeof(int),1,fp3);
fread(&a1,sizeof(int),1,fp1);
}else{
fwrite(&a2,sizeof(int),1,fp3);
fread(&a2,sizeof(int),1,fp2);
}
}
while(!feof(fp1)){
fwrite(&a1,sizeof(int),1,fp3);
fread(&a1,sizeof(int),1,fp1);
}
while(!feof(fp2)){
fwrite(&a2,sizeof(int),1,fp3);
fread(&a2,sizeof(int),1,fp2);
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
在命令行当中输入四个参数,分别为执行程序、读取数据的文件名1、读取数据的文件名2、写入数据的文件名。