C语言【文件操作 2】

文章目录

前言

在前面的文章我们讲解了文件操作的基础:点击此处浏览前文下面正式讲解文件的操作函数
注意:因为本章讲解的文件操作,所以大多数函数使用环境默认是文件!!!

顺序读写函数的介绍

函数名 功能 适用于
fgetc 字符输⼊函数 所有输入流
fputc 字符输出函数 所有输出流
fgets 文本行输入函数 所有输入流
fputs 文本行输出函数 所有输出流
fscanf 格式化输⼊函数 所有输入流
fprintf 格式化输出函数 所有输出流
fread ⼆进制输⼊ 文件
fwrite 二进制输出 文件

上面说的适用与所有输入流一般指的是适用于标准输入流与其他输入流(例如文件输入流);所有输出流指的是适用于标准输出流与其他输出流(例如文件输出流)。

fputc && fgetc

fputc

将一个字符输出到文件

c 复制代码
int fputc(int c, FILE* stream);

参数为什么是int类型呢?

因为传递的是ASCII码值

为什么会返回int类型的值呢?返回的是什么呢?

cpp网站是这样写的:

On success, the character written is returned.

If a writing error occurs, EOF is returned and the error indicator (ferror) is set.

大致意思就是:

如果写入成功,返回被写入的字符的ASCII码值

如果写入失败,返回EOF并设置错误提示符

例子:

c 复制代码
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "w");//只写
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}
	for (char c = 'A'; c <= 'Z'; c++)
	{
		fputc(c, pf);//将字符输入到文件中
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

fgetc

从文件中读取一个字符

c 复制代码
int fgetc(FILE* stream)

返回的是ASCII码值

关于fgetc的返回值cpp网站是这样写的

On success, the character read is returned (promoted to an int value).

The return type is int to accommodate for the special value EOF, which indicates failure:

If the position indicator was at the end-of-file, the function returns EOF and sets the eof indicator (feof) of stream.

If some other reading error happens, the function also returns EOF, but sets its error indicator (ferror) instead.

大致意思是:

如果读取成功,返回被读取字符的ASCII码值;

若读取失败或文件光标已经到了文件末尾(就是没字符可以读了),则会返回EOF

例子:

c 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("text.txt", "r");//只读
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}
	int c;
	while ((c = fgetc(pf)) != EOF)
	{
		printf("%c ", c);
	}

	fclose(pf);
	pf = NULL;

	return 0;
}

fputs && fgets

fputs

将字符串输出到文件

c 复制代码
int fputs ( const char * str, FILE * stream );

关于返回值

cpp网站是这样写的:

On success, a non-negative value is returned.

On error, the function returns EOF and sets the error indicator (ferror).

大致意思:

输出成功,返回一个非负数;

输出失败,返回EOF

例子:

c 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("text.txt", "w");//只写
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}
	char str[100] = "Hello World";
	fputs(str, pf);//数组名是数组首元素地址
	fclose(pf);
	pf = NULL;
	return 0;
}

fgets

读取指定位置范围内的字符串

c 复制代码
char * fgets ( char * str, int num, FILE * stream );

str:用于接收字符串

num:一次读num-1个字符(fgets会默认在第num处存放'\0')

关于返回值

cpp网站是这样写的:

On success, the function returns str.

If the end-of-file is encountered while attempting to read a character, the eof indicator is set (feof). If this happens before any characters could be read, the pointer returned is a null pointer (and the contents of str remain unchanged).

If a read error occurs, the error indicator (ferror) is set and a null pointer is also returned (but the contents pointed by str may have changed).

大致意思就是:

读取成功,返回str的地址;

读取失败或文件已到末尾,返回NULL;

例子:

c 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("text.txt", "r");//只读
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
		return;
	}
	char buf1[100] = { 0 };
	char* str1;
	str1 = fgets(buf1, 12, pf);//这是我明确知道文件有多少个元素
	printf("明确知道:");
	printf("%s", str1);

	printf("\n");
	rewind(pf);//将光标返回文件初始位置

	//假设我们不知道文件内有多少个元素
	char buf2[100] = { 0 };
	char* str2;

	printf("并不明确:");
	while ((str2 = fgets(buf2, 2, pf)) != NULL)
	{
		printf("%s", str2);
	}

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

fprintf && fscanf

fprintf

将数据以格式化的形式输出到文件

c 复制代码
int fprintf ( FILE * stream, const char * format, ... );

fprintfprintf很像,只是printf是输出到标准输出流(屏幕);而·printf是可以输出到指定输出流中

例子:

c 复制代码
#include<stdio.h>
typedef struct st
{
	char _Name[20];
	int _Score;
	char _SId[17];
}Stu;

int main()
{
	Stu student = { "zhangsan" , 99, "202300002024" };
	FILE* pf = fopen("text.txt", "w");//只写
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}

	fprintf(pf, "%s %d %s", student._Name, student._Score, student._SId);

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

fscanf

从文件输出格式化的数据

c 复制代码
int fscanf ( FILE * stream, const char * format, ... );

同理,fscanfscanf也是很相似的;只不过scanf是从标准输入流(键盘)得到数据,fscanf是从指定的输入流中得到数据

例子:

c 复制代码
#include<stdio.h>
typedef struct st
{
	char _Name[20];
	int _Score;
	char _SId[17];
}Stu;

int main()
{
	FILE* pf = fopen("text.txt", "r");//只读
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}
	Stu x = { 0 };
	fscanf(pf, "%s %d %s", x._Name, &(x._Score), x._SId);
	printf("%s %d %s", x._Name, x._Score, x._SId);

	fclose(pf);
	pf = NULL;

	return 0;
}


注意:上面的函数可以使用到任意的指定流中;
当然也要遵守语法:该是输出流给输出流,该是输入流给输入流

就拿fprintf举例

c 复制代码
#include<stdio.h>
typedef struct st
{
	char _Name[20];
	int _Score;
	char _SId[17];
}Stu;
int main()
{
	Stu student = { "zhangsan" , 99, "202300002024" };
	FILE* pf = fopen("text.txt", "w");//只写
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}

	fprintf(stdout, "%s %d %s", student._Name, student._Score, student._SId);
	//stdout是标准输出流

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

fwrite && fread

这两个函数只能用文件流(也就是只能输入输出到文件)

fwrite

以二进制的形式输出数据到文件(只能输入到文件)

c 复制代码
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

ptr->要输入的数据

size->数据的大小

count->数据的个数

例子:

c 复制代码
#include<stdio/h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	FILE* pf = fopen("text.txt", "wb");//只写(以二进制形式)
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}

	fwrite(arr, sizeof(arr[0]), 10, pf);

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

fread

以二进制的形式从文件中读取数据

c 复制代码
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

ptr->用于接收数据

size->数据的大小

count->数据的个数

关于返回值

cpp网站是这样写的

The total number of elements successfully read is returned.

If this number differs from the count parameter, either a reading error occurred or the end-of-file was reached while reading. In both cases, the proper indicator is set, which can be checked with ferror and feof, respectively.

If either size or count is zero, the function returns zero and both the stream state and the content pointed by ptr remain unchanged.

size_t is an unsigned integral type.

大致意思为:

如果读取成功,返回成功读取的元素个数。

如果这个数字与 count 参数不同,要么是发生了读取错误,要么是在读取过程中到达了文件终点。

如果 size 或 count 均为零,函数返回零,流状态和 ptr 指向的内容均保持不变。

例子:

c 复制代码
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "rb");//只读(以二进制形式)
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}
	int arr[10] = { 0 };
	fread(arr, sizeof(arr[0]), 10, pf);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

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

文件的随机读写

fseek函数

根据文件指针的位置和偏移量来定位文件指针。

c 复制代码
int fseek ( FILE * stream, long int offset, int origin );

偏移量

文件指针所指向的位置距离文件起始位置有多少个数据

文件起始位置有三种(下列表格在cpp网站的fseek函数中)

Constant Reference position
SEEK_SET Beginning of file
SEEK_CUR Current position of the file pointer
SEEK_END End of file *

SEEK_SET:文件的开始位置
SEEK_CUR:文件指针当前的位置
SEEK_END:文件的末尾

如果fseek给的起始位置是SEEK_END,那么访问前面的元素,偏移量就要给负数

例子:

c 复制代码
#include<stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("text.txt", "w");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	fputs(" sam", pFile);
	fclose(pFile);
	return 0;
}


这是为什么呢?

我们来看图吧。

ftell函数

返回文件指针相对于起始位置的偏移量

c 复制代码
long int ftell ( FILE * stream );

例子:

c 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("text.txt", "r");//只读
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
	}

	for (int i = 0; i < 5; i++)
	{
		fgetc(pf);
	}
	printf("偏移量为%d ",ftell(pf));
	fclose(pf);
	pf = NULL;

	return 0;
}

rewind函数

让文件指针返回到文件的起始位置

c 复制代码
void rewind ( FILE * stream );

前面的例子也使用过:

c 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("text.txt", "r");//只读
	if (pf == NULL)
	{
		perror("fopen");//如果错误会在屏幕上打印错误原因
		return;
	}
	char buf1[100] = { 0 };
	char* str1;
	str1 = fgets(buf1, 18, pf);//这是我明确知道文件有多少个元素
	printf("明确知道:");
	printf("%s", str1);

	printf("\n");
	rewind(pf);//将光标返回文件初始位置

	//假设我们不知道文件内有多少个元素
	char buf2[100] = { 0 };
	char* str2;

	printf("并不明确:");
	while ((str2 = fgets(buf2, 2, pf)) != NULL)
	{
		printf("%s", str2);
	}

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

文件的结束判断

被错误使用的feof

牢记:在文件读取的过程中,不能用feof函数的返回值来直接判断文件是否结束。

feof的作用是:当文件已经读取结束时,判断结束的原因是否为"遇到文件尾部结束"。

文本文件读取是否结束。判断返回值是否为EOF (fgetc),或NULL(fgets)。

二进制文件读取是否结束,判断返回值是否小于实际要读的数。

cpp的网站->https://cplusplus.com/

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!!!

相关推荐
不穿格子衬衫2 小时前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序
aqua35357423582 小时前
蓝桥杯-财务管理
java·c语言·数据结构·算法
唐·柯里昂7982 小时前
[3D打印]拓竹切片软件Bambu Studio使用
经验分享·笔记·3d
sml_54212 小时前
【笔记】连续、可导、可微的概念解析
笔记·线性代数
新手unity自用笔记2 小时前
项目-坦克大战学习-子弹的移动与销毁
笔记·学习·c#
Word码3 小时前
数据结构:栈和队列
c语言·开发语言·数据结构·经验分享·笔记·算法
五花肉村长3 小时前
数据结构-队列
c语言·开发语言·数据结构·算法·visualstudio·编辑器
qinzechen3 小时前
分享几个做题网站------学习网------工具网;
java·c语言·c++·python·c#
我命由我123453 小时前
SSL 协议(HTTPS 协议的关键)
网络·经验分享·笔记·学习·https·ssl·学习方法
丶Darling.4 小时前
代码随想录 | Day26 | 二叉树:二叉搜索树中的插入操作&&删除二叉搜索树中的节点&&修剪二叉搜索树
开发语言·数据结构·c++·笔记·学习·算法