C语言文件操作

目录

1.为什么使用文件

2.文件是什么

3.文件的打开和关闭

1.打开文件

2.关闭文件

(1)fputc

(2)fgetc

(3)fputs

(4)fgets

(5)fprintf

(6)fscanf

(7)fwrite

(8)fread

(9)sprintf

(10)sscanf

3.文件的随机读写 

(1)fssek

(2)ftell

(3)rewind

4.文件读取结束的判定


1.为什么使用文件

   我们知道在我们写一些具有记录性功能的一些程序时,我们添加或修改的成员只有在程序运行时才有,然而当我们退出程序时,这些内容就被内存回收了,因此为了使数据持久化,可以将数据放在磁盘文件或存放在数据库等方式。

2.文件是什么

   磁盘上的文件是文件,但在程序设计中我们通常说的文件有两种:程序文件、数据文件(从文件功能角度分析)

(1)程序文件

   包括源程序的文件(后缀为.c),目标文件(Windows环境后缀为.obj),可执行程序(Windows环境后缀为.exe)。

(2)数据文件

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

补充:

文件名包含三个部分:文件路径 + 文件名主干 + 文件后缀(后缀可以没有)

3.文件的打开和关闭

   首先在了解文件打开前我们需要了解文件指针。当我们打开一个文件时,都会有一个文件信息区来存放相关的信息(文件的名字,文件的状态等)这些信息呢就是保存到我们的一个结构体变量中,该结构体是有系统声明的,取名为FILE。不同编译器的FILE类型包含可能不相同,但大都是一样的,每次使用一个文件,我们可以通过一个文件指针变量就能找到与它关联的文件。

1.打开文件

原型:FILE * fopen ( const char * filename, const char * mode )

打开文件,首先我们以什么方式打开,我们通常有以读的方式,以写的方式,以二进制方式读,以二进制方式写如以下表格中:

文件的使用方式含义如果指定文件不存在
“r” (只读)为了输入数据,打开一个已经存在的文本文件出错
“w” (只写)为了输出数据,打开一个文本文件建立一个新的文件
“a” (追击)向文本文件尾部添加数据建立一个新的文件
“rb” (只读)为了输入数据,打开一个二进制文件出错
“wb” (只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab” (追击)向二进制文件尾部添加数据出错
"r+" (读写)为了读和写,打开一个文本文件出错
"w+" (读写)为了读和写,建立一个文本文件建立一个新的文件
"a+" (读写)打开一个文件,在文件尾部进行读写建立一个新的文件
"rb+" (读写)为了读和写,打开一个二进制文件出错
"wb+" (读写)为了读和写,新建一个新的二进制文件建立一个新的文件
"ab+" (读写)打开一个二进制文件,在文件尾读和写建立一个新的文件


2.关闭文件

原型:int fclose ( FILE * stream )

//代码样例
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (!pf)
	{
		perror("fopen:");
		return 0;
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

有了以上函数,就可以对文件的写和读 

(1)fputc

原型:int fputc ( int character, FILE * stream )

   fputc是一个字符一个字符的读取到文件中,读取失败返回EOF用例如下

//写文件字符
int main()
{
	//struct S s = { 0 };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char i = 0;
	for (i = 'a'; i <= 'z'; i++)
	{
		fputc(i, pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

(2)fgetc

原型:int fgetc ( FILE * stream )

   fgetc是文件一个一个字符的从文件中读取出来,读取失败返回EOF用例如下

//读文件字符
int main()
{
	//struct S s = { 0 };
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//char ch = fgetc(pf);
	//printf("%c", ch);
	char ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		printf("%c ", ch);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

(3)fputs

原型:int fputs ( const char * str, FILE * stream )

   fputs是用来一行一行的读取到文件中,读取失败返回EOF,用例如下

//写一行数据
int main()
{
	//struct S s = { 0 };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("hello bit\n", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

(4)fgets

原型:char * fgets ( char * str, int num, FILE * stream )

   fgets是用来一行一行的读取文件,读取失败返回EOF,用例如下

//读一行数据
int main()
{
	//struct S s = { 0 };
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[20] = { 0 };
	fgets(arr, 5, pf);  //读的5个数据中,其中第五个是 '\0' 
	printf("%s\n", arr);//所以相当于读了字符串中的 5-1 个字符
	fclose(pf);
	pf = NULL;
	return 0;
}

(5)fprintf

原型:int fprintf ( FILE * stream, const char * format, ... )

   fprintf是用来格式化输出文件

//读一行数据
struct S
{
	char name[20];
	int age;
	float high;
};
int main()
{
	struct S s = { "zhangsan", 20, 1.87f};
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[20] = { 0 };
	fprintf(pf, "%s %d %f", s.name, s.age, s.high);
	fclose(pf);
	pf = NULL;
	return 0;
}

(6)fscanf

原型:int fscanf ( FILE * stream, const char * format, ... )

   是用来格式化输入文件

//读一行数据
struct S
{
	char name[20];
	int age;
	float high;
};
int main()
{
	struct S s = { 0 };
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	
	fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.high));

	printf("%s %d %f\n", s.name, s.age, s.high);

	fclose(pf);
	pf = NULL;
	return 0;
}

(7)fwrite

原型:size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream )

   二进制形式输出

//二进制方式读一行数据
struct S
{
	char name[20];
	int age;
	float high;
};
int main()
{
	struct S s = { "zhangsan", 20, 1.87f };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fwrite(&s, sizeof(struct S), 1, pf);

	fclose(pf);
	pf = NULL;
	return 0;
}

(8)fread

原型:size_t fread ( void * ptr, size_t size, size_t count, FILE * stream )

   二进制形式输入

//二进制方式写一行数据
struct S
{
	char name[20];
	int age;
	float high;
};
int main()
{
	struct S s = { 0 };
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s %d %f\n", s.name, s.age, s.high);

	fclose(pf);
	pf = NULL;
	return 0;
}

(9)sprintf

struct S
{
	char name[20];
	int age;
	float high;
};
int main()
{
	struct S s = { "zhangsan", 20, 1.87f };
	char buf[100] = { 0 };
	sprintf(buf, "%s %d %.2f\n", s.name, s.age, s.high);
	//sprintf函数的功能是将格式化的数据转化为字符串
	printf("%s", buf);
	return 0;
}

(10)sscanf

int main()
{
	struct S s = { "zhangsan", 20, 1.87f };
	struct S tmp = { 0 };
	char buf[100] = { "zhangsan 20 1.87" };
	//char buf[100] = { 0 };
	//sprintf(buf, "%s %d %.2f\n", s.name, s.age, s.high);
	sscanf(buf, "%s %d %f", tmp.name, &(tmp.age), &(tmp.high));
	//将字符串转化为格式化的数据
	printf("%s %d %.2f", tmp.name, tmp.age, tmp.high);
	return 0;
}

总结:

 scanf 是针对标准输入的格式化输入语句

 printf 是针对标准输出的格式化输出语句

 fscanf 是针对所有输入流的格式化输入语句

 fprintf 是针对所有输出流的格式化输入语句

 sscanf 是将字符串转化为格式化数据

 sprintf 是将格式化数据转换为字符串

3.文件的随机读写 

(1)fssek

原型:int fseek ( FILE * stream, long int offset, int origin )
   fssek是根据文件指针的位置和偏移量来定位文件指针,它可以指定位置的读取文件,前提是要知道文件内容。

(2)ftell

原型:long int ftell ( FILE * stream )

   ftell是和上面的fssek函数内容相互照应,它能知道当前位置相对于起始位置的偏移量是多少。

(3)rewind

原型:void rewind ( FILE * stream )

   rewind是用来回到起始位置,当我们已经不知道文件指针的位置时,就可以用这个函数来回到起始的位置。

4.文件读取结束的判定

文件结束有两个原因:1.就是文件读取到末尾。 2.就是文件读取错误,失败了从而结束。

   feof函数会告诉我们文件读取结束的原因,而不能用feof函数的返回值直接用来判断文件的是否结束。

   ferror函数会告诉我们文件读取失败时的原因。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值