文件操作(2)(C语言版)

文件的随机读写:

fseek函数:

前面讲解了顺序读写的相关函数,这里介绍一些可以**"指哪写哪的函数"**

有三个参数:

1、文件的地址

2、相对于第三个参数origin偏移的位置

3、起始位置(有三种)

第一种:SEEK_SET(开头)

第二种:SEEK_CUR(当前位置)

第三种:SEEK_END(结尾)

cpp 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdef", pf);

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

可以通过fseek改变光标位置,而且是覆盖改写

什么意思呢?

如以下代码:

cpp 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdef", pf);
	fseek(pf, 2, SEEK_SET);//从头开始往后两个位置
	fputs("aa", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

还可以这样改:

cpp 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdef", pf);
	fseek(pf, 2, SEEK_SET);//从头开始往后两个位置开始
	fputs("aa", pf);
	fseek(pf, 3, SEEK_CUR);//从当前位置开始
	fputs("kikll", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

ftell函数:

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

cpp 复制代码
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdef", pf);
	fseek(pf, 2, SEEK_SET);//从头开始往后两个位置
	fputs("aa", pf);
	int ret = ftell(pf);
	printf("%d\n", ret);
	fclose(pf);
	pf = NULL;
	return 0;
}

rewind函数:

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

cpp 复制代码
#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[27];
	char a = 0;
	for (a = 'A'; a <= 'z'; a++)
	{
		fputc(a, pf);
	}
	rewind(pf);
	fread(arr, 1, 26, pf);
	fclose(pf);
	pf = NULL;
	arr[26] = '\0';
	printf("%s\n", arr);
	return 0;
}

**文件读取结束的判定

到此为止讨论了所有文件的相关函数及操作,但是有一点我们还是有点不清楚,一个函数读取文件什么时候停止呢?停止的标志是什么呢?

那如果读取文件中途读取失败又会怎么样,返回的值类型是什么?

接下来就详细探究探究以上函数什么时候读取结束?

feof函数:

feof函数可以检查并判断文件是否为正常结束。

当读取到文件末尾时结束读取,feof会返回一个非零的值,但是读的时候也会有异常结束的时候 ,这时候返回的值就是0。

用feof判断文件是否结束还是失败是不行的。

所以这里就需要用到每个函数读取是否结束的返回值进行判断!

  1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets ) 例如: fgetc 判断是否为 EOF . fgets 判断返回值是否为 NULL .

  2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。 例如: fread判断返回值是否小于实际要读的个数。

拷贝一份文件

cpp 复制代码
int main()
{
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int a = 0;
	for (a = 'A'; a <= 'Z'; a++)
	{
		fputc(a, pf);
		if (a % 5 == 0)
		{
			fputc('\n', pf);
		}
	}
	rewind(pf);//找到起始位置
	FILE* pf1 = fopen("cool.txt", "w");
	if (pf1 == NULL)
	{
		perror("fopen");
		fclose(pf);
		pf = NULL;
		return 1;
	}
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		fputc(ch,pf1);
	}
	fclose(pf1);
	pf1 = NULL;
	fclose(pf);
	pf = NULL;
	return 0;
}

改进通讯录(可以保存在文件中)

之前写的通讯录经过多次修改,现在可以动态化存储,单数唯一的缺点是,当运行结束后,所有的信息也会跟着销毁,不会被存储起来,现在有办法将其存储在文件中,为此要用的时候,可以打开,这样存储的信息就不会丢失了。

结束之前将信息存入文件

我们用fwrite写入文件,fread读取文件内容。

cpp 复制代码
void savecontact(con* pc)
{
	FILE* pf = fopen("contact.txt", "wb");//二进制打开文件输出
	if (pf == NULL)
	{
		perror("fopen");
		return ;
	}
	int i = 0;
	for (i = 0; i < pc->num; i++)
	{
		fwrite(pc->contact + i,sizeof(per),1,pf);
	}
	fclose(pf);
	pf = NULL;
}

因为fwrite返回的值为读取的值,一次性读取的值我们可以进行设置

参数num为每次读取的值,当读取的值比设置的小,则返回之际读取的个数。

所以选择用while循环一次一次读取!!

开始时写入文件中保存的内容

cpp 复制代码
void inputcontact(con* pc)
{
	FILE* pf = fopen("contact.txt","rb");
	if (pf == NULL)
	{
		perror("inputcontact");
		return;
	}
	//录入信息
	per tmp = { 0 };
	while (fread(&tmp, sizeof(per), 1, pf))
	{
		checkcapacity(pc);
		pc->contact[pc->num] = tmp;
		pc->num++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}
相关推荐
SelectDB3 分钟前
十亿 JSON 秒级响应:Apache Doris vs ClickHouse,Elasticsearch,PostgreSQL
算法
Dxxyyyy30 分钟前
零基础学JAVA--Day34(Map接口+HashTable+HashMap+TreeSet+TreeMap+开发中如何选择集合实现类?(重要))
java·开发语言
橘颂TA31 分钟前
【剑斩OFFER】算法的暴力美学——除自身以外数组的乘积
算法·leetcode·职场和发展·结构与算法
源码之家32 分钟前
机器学习:基于python租房推荐系统 预测算法 协同过滤推荐算法 房源信息 可视化 机器学习-线性回归预测模型 Flask框架(源码+文档)✅
大数据·python·算法·机器学习·数据分析·线性回归·推荐算法
rainFFrain1 小时前
qt显示类控件---QProgressBar
开发语言·qt
鑫—萍1 小时前
C/C++精品算法——双指针(1)
c语言·c++·算法
rainFFrain1 小时前
qt输入类控件---QComboBox/QSpinBox
开发语言·qt
铭哥的编程日记1 小时前
深入浅出蓝桥杯:算法基础概念与实战应用(三)搜索
算法·蓝桥杯·深度优先
2501_941111891 小时前
低延迟系统C++优化
开发语言·c++·算法
未来之窗软件服务1 小时前
自建开发工具IDE(二)文件托拽读取——东方仙盟炼气期
开发语言·前端·javascript·仙盟创梦ide·东方仙盟