C语言-常见文件操作函数详解(fgetc,fputc,fgets,fputs,fscanf,fprintf,fread,fwrite)

在这里插入图片描述

 🌏个人博客:尹蓝锐的博客

在这里插入图片描述

希望文章能够给到初学的你一些启发~ 如果觉得文章对你有帮助的话,点赞 + 关注+ 收藏支持一下笔者吧~

顺序读写数据常用函数

函数名调用形式功能返回值
fgetcfgetc(fp)从指针变量fp指向的文件中读入一个字符读成功,返回所读字符,失败返回EOF(即-1)
fputcfputc(fp)把字符ch写到文件指针变量fp所指向的文件中输出成功返回值就是输出的字符,输出失败返回EOF(即-1)
fgetsfgets(str,n,fp)

从fp指向的文件读入一个长度为(n-1)的字符串,存放到字符数组str中

tips:读n-1个是因为fgets函数要固定留一个字符 '\0' 作为字符串结束标志

读成功,返回地址str,失败则返回NULL
fputsfputs(str,fp)

把str所指向的字符串写到文件指针变量fp所指向的文件中

输出成功,返回0;否则返回非0值
fscanffscanf(fp,"%d",i)将int类型变量i的值按照%d的格式输出到fp指向的文件中成功后,将返回写入的字符总数。否则并返回负数。
fprintffprintf(fp,"%f",j)将float类型的变量j的值按照%f的格式输出到屏幕上成功后,将返回写入的字符总数。否则并返回负数。

fread

fread(buffer,size,count,fp)从fp中读取一个含有count个元素的数组,每个元素的大小为size个字节,并将其存储在buffer指定的内存块中。返回成功读取的元素总数
fwritefwrite(buffer,size,count,fp)从buffer指向的内存块向文件流中写入一个包含count个元素数组,每个元素的大小为size个字节。流的位置指示器按写入的总字节数前进。返回成功写入的元素总数。

1、fgetc

int fgetc ( FILE * stream );

  1. 从流中获取字符
  2. 返回指定流的内部文件位置指示符当前指向的字符。然后,内部文件位置指示器将前进到下一个字符。
  3. 如果调用时流位于文件末尾,则函数返回EOF并为流设置文件末尾指示符(feof)。
  4. 如果发生读取错误,该函数将返回EOF并为流设置错误指示符(ferror)。
  5. fgetc和getc是等效的,除了getc可以在某些库中实现为宏。

为了更加具体理解,我们创建一个文件并输入一些字符

 在保证文件有内容可读取后,我们以只读的方式打开文件,使用ch变量挨个读取文件中的字符

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.txt", "r");
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch = getc(fp);
	printf("%c", ch);
	ch = getc(fp);
	printf("%c", ch);
	fclose(fp);
	fp = NULL;
	return 0;
}

运行结果如下:

2、fputc

int fputc ( int character, FILE * stream );

  1. 向流写入字符将字符写入流并推进位置指示器。
  2. 字符被写在流的内部位置指示器指示的位置,然后自动前进一个。

使用fputc向文件中挨个写入字符

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.txt", "w");//只写方式打开
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch[10] = "excellent!";
	for (int i = 0; i < 10; i++)
	{
		fputc(ch[i], fp);
	}
	fclose(fp);
	fp = NULL;
	return 0;
}

运行结果如下,test被成功写入字符

这里需要注意的是:如果test.txt文件中本来有内容,原来的内容会被清空

3、fgets

char * fgets ( char * str, int num, FILE * stream );

  1. 从流中获取字符串
  2. 从流中读取字符,并将其作为字符串存储到str中,直到读取了(num-1)个字符,或者到达换行符或文件末尾,以先发生者为准。
  3. 换行符会使fgets停止读取,但函数会将其视为有效字符,并将其包含在复制到str的字符串中。
  4. 在复制到str的字符之后,会自动附加一个终止空字符。
  5. 请注意,fgets与gets有很大不同:fgets不仅接受流参数,还允许指定str的最大大小,并在字符串中包含任何换行符。

确保test.txt文件有内容的情况下,用只读方式打开文件

通过fgets函数获取文件中的字符串并将其保存至字符数组ch中,代码如下

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.txt", "r");//只读方式打开
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch[10];
	fgets(ch, sizeof(ch), fp);
	puts(ch);
	fclose(fp);
	fp = NULL;
	return 0;
}

运行结果如下

我们需要注意的是本代码调用fgets函数时,第二个参数使用sizeof(ch),计算字符数组ch所占字节数,计算结果值为10,而fgets函数第二个参数代表取10-1个,即9个字符,所以文件中只有9个字符被存入字符数组ch中,原本文件内容excellent后的  !没有被输出

4、fputs

int fputs ( const char * str, FILE * stream );

  1. 将字符串写入流
  2. 将str指向的字符串写入流。
  3. 函数从指定的地址(str)开始复制,直到到达终止的空字符(“\0”)。此终止空字符不会复制到流中。
  4. 请注意,fputs与put的不同之处不仅在于可以指定目标流,而且fputs不会写入额外的字符,而put会自动在末尾添加换行符。

通过fputs函数向文件中写入字符串

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.txt", "w");//只写方式打开
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch[11]="wonderful!";
	fputs(ch,fp);

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

运行结果如下:

5、fscanf

int fscanf ( FILE * stream, const char * format, ... );
  1. 从流中读取格式化数据
  2. 从流中读取数据,并根据参数格式将其存储到附加参数指向的位置。
  3. 附加参数应指向格式字符串中由其相应格式说明符指定的类型的已分配对象。

首先保证test.txt文件中有内容

使用scanf用格式化的方式读取文件中的内容,代码如下

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.txt", "r");//只写方式打开
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	int n;
	fscanf(fp, "%d", &n);
	printf("%d", n);
	fclose(fp);
	fp = NULL;
	return 0;
}

运行结果如下

6、fprintf

int fprintf ( FILE * stream, const char * format, ... );
  1. 将格式化数据写入流
  2. 将按格式指向的字符串写入流。如果format包含格式说明符(以%开头的子序列),则格式化format之后的其他参数并将其插入到结果字符串中,替换其各自的说明符。
  3. 在format参数之后,函数需要至少与format指定的额外参数一样多的参数。

使用fprintf函数向文件中格式化输出内容

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.txt", "w");//只写方式打开
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	int n = 123456;
	fprintf(fp, "%d", n);
	
	fclose(fp);
	fp = NULL;
	return 0;
}

运行结果如下:

7、fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
  1. 从流中读取数据块
  2. 从流中读取一个count个元素组成的数组,每个元素的大小为size个字节,并将其存储在ptr指定的内存块中。
  3. 流的位置指示器按读取的总字节数前进。
  4. 如果成功,读取的字节总数为(size(大小)*count(计数))。

该函数一共有4个参数:

  1. ptr指向大小至少为(大小*计数)字节的内存块的指针,转换为void*。
  2. size要读取的每个元素的大小(以字节为单位)。
  3. size_t是一个无符号整数类型。
  4. count元素的数量,每个元素的大小为字节。
  5. size_t是一个无符号整数类型。
  6. stream指向指定输入流的FILE对象的指针。

首先保证test.dat该二进制文件中有数据,我这里给的是123456,可将test.txt中输入数据后修改文件名成.dat

使用fread函数从二进制文件中读入数据存入字符数组arr中,并输出

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.dat", "rb");//只读方式打开,且读的是二进制文件
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[7] = { 0 };
	fread(arr, sizeof(arr[0]), sizeof(arr), fp);
	printf("%s", arr);
	// arr : 将文件读取到内存的位置
	// sizeof(arr[0]) : 读取的元素字节大小
	// sizeof(arr) : 读取元素的个数,
	// 读取字节个数是 sizeof(arr) * sizeof(arr[0])
	// fp : 文件指针
	fclose(fp);
	fp = NULL;
	return 0;
}

运行结果如下:

8、fwirte

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
  1. 将数据块写入流
  2. 从ptr指向的内存块向流中的当前位置写入含有count个元素的数组,每个元素的大小为size字节
  3. 流的位置指示器按写入的总字节数前进。
  4. 在内部,该函数将ptr指向的块解释为一个无符号char类型的(大小*计数)元素数组,并将它们顺序写入流,就像每个字节都调用了fputc一样。

本函数由4个参数(与fread类似)

  1. ptr指向要写入的元素数组的指针,转换为const void*。
  2. size要写入的每个元素的大小(以字节为单位)。
  3. size_t是一个无符号整数类型。
  4. count元素的数量,每个元素的大小为字节。
  5. size_t是一个无符号整数类型。
  6. stream指向指定输出流的FILE对象的指针。

我们使用fwirte函数向二进制文件test.dat写入字符串hello,操作如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	FILE *fp = fopen("test.dat", "wb");//只写方式打开,且写的是二进制文件
	if (fp == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[7] = { "hello" };
	fwrite(arr, sizeof(arr[0]), sizeof(arr), fp);
	// arr : 将文件读取到内存的位置
	// sizeof(arr[0]) : 读取的元素字节大小
	// sizeof(arr) : 读取元素的个数,
	// 读取字节个数是 sizeof(arr) * sizeof(arr[0])
	// fp : 文件指针
	fclose(fp);
	fp = NULL;
	return 0;
}

检验:将test.dat后缀改成txt文件,打开发现更改成功

  如果我的博客能给您带来启发,请不吝点赞、评论和收藏,也欢迎您关注我的博客。

  如果你喜欢这篇文章,别忘了留下你的感想和建议,让我知道你的想法。同时,也请继续关注我的博客,我们不见不散!

  最后,愿每一位读到这里的你,都能拥有一个充实而美好的每一天。不管世界怎样变化,保持学习,保持热爱,保持对生活的好奇心,我们的故事,还在继续……

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹蓝锐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值