【C C++】万字图文详解C语言文件操作 完美装饰课设大作业_以只读方式打开文本文件怎么操作c语言

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

接下来对代码的每一步进行解释:

打开文件时有两种方式:相对路径和绝对路径

相对路径:在当前源程序(.c)文件所在的路径下的某个文件。

绝对路径:任意路径下的文件。

fopen并非每次都能成功地打开文件。打开成功则返回指向该文件的文件信息区的指针;打开失败则返回NULL。 所以使用pf前必须加以判断。

free的原理相同,fclose关闭文件后,pf指向的地址不再有效,为了避免不小心再次使用,需将其置为NULL。以上代码中的**“w”,指一种文件的打开方式,含义为“只写”的方式打开。除了"w"**之外,还有许许多多的打开方式,如下:

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

接下来我们就简单认识一下前三个打开方式。

1.以"r"(只读)的方式打开文件
FILE* pf = fopen("test.txt", "r");

以只读的方式打开文件,只能从文件里读取数据,而不能写如数据或者修改数据。

如果找到该文件,则返回指向该文件的文件信息区的FILE类型的指针;

如果未找到,则返回NULL。

2.以"w"(只写)的方式打开文件
FILE* pf = fopen("test.txt", "w");

以只写的方式打开文件,只能写入数据到文件中,而不能读取文件数据。

如果未找到该文件,则在该路径下创建该文件并返回指向该文件的文件信息区的指针;

如果找到该文件,则丢弃该文件中的内容,视其为新的空文件,并返回指向该文件的文件信

息区的指针。

3.以"a"(追加)的方式打开文件
FILE* pf = fopen("test.txt", "a");

以追加的方式打开文件,含义为在该文件的末尾打开文件进行写入。

如果未找到该文件,则在该路径下创建该文件并返回指向该文件的文件信息区的指针;

如果找到该文件返回指向该文件的文件信息区的指针。

学会了如何打开和关闭文件之后,我们来看看如何进行文件的读与写。

文件的顺序读写


文件顺序读写所涉及的函数有:

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

输入流与输出流的概念

C语言中,把不同类型的输入输出源称为流,根据其作用分为输入流和输出流。

例如我们的终端设备键盘与屏幕就是两种流;键盘称之为标准输入流,屏幕为标准输出流

与之类似,文件也是一种流。文件保存在磁盘中,因此我们也可以把文件看作一种外部设

备。所有输入/输出流指的是标准输入/输出流和其他输入/输出流。

输入输出是指:

从输入流中把数据读取到内存中,称为输入。(例如,scanf从键盘中读取数据到内存中)

把内存中的数据写入到输入流中,称为输出。(例如,printf把内存中的数据打印到屏幕上)

fputc & fgetc

fputc的作用是,将一个整型数据写入流中。整型数据将会被写入到文件指针所指向的位置。

文件指针默认指向文件起始位置偏移量为0的位置。并且每成功写入一个数据,该指针自动向

前移动一位。

返回值:

如果成功则返回该整型数据;

如果失败则返回EOF。

示例:

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "w");
	//判空
	if (pf == NULL)
	{
		perror("fopen");
		exit(-1);
	}

	fputc('a', pf);
	
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}


fgetc的作用是,返回指定流中文件位置指针指向的字符,然后该指针后移一位。

返回值:

如果读取成功则返回读取字符的ASCII码值

如果读取失败则返回EOF;

如果文件位置指针指向文件末尾则返回EOF;

如果发生其他错误返回EOF;

示例:

读取文件中写好的26个英文字母。

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	//判空
	if (pf == NULL)
	{
		perror("fopen");
		exit(-1);
	}
	int ch = 0;
	while ((ch=fgetc(pf)) != EOF)
	{
		printf("%c ", ch);
	}
	
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

fputs & fgets

fputs的作用是,将字符串str写入流中。从str的起始位置开始写入,直至遇到’\0’结束,并

且’\0’不会写入到流中。

返回值:

写入成功则返回非负值;

写入失败则返回EOF。

示例:

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "w");
	//判空
	if (pf == NULL)
	{
		perror("fopen");
		exit(-1);
	}

	fputs("hello world", pf);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}


fgets的作用是,从流中读取字符串并保存到str中,直到读取 (num-1)个字符或者遇

到’\n’,或者到达文件末尾。读取完成之后,会自动在str末尾添加’\0’

注意:'\n’会被认为是有效字符读取到str中

返回值:

读取成功则返回str;

读取失败则返回NULL;

读取到文件末尾而停止则返回EOF;

示例:

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	//判空
	if (pf == NULL)
	{
		perror("fopen");
		exit(-1);
	}
	
	char str[15];
	fgets(str, 15, pf);
	printf(str);
	
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}


fscanf & fprintf

这次我们不用解读帮助文档,仅仅通过对比scanf和printf的函数构造就可以掌握fscanf和fprintf。

通过对比,二者相较于我们经常使用的scanf、printf仅仅多了一个流。其实它们不仅长相相似用法也几乎完全相同。

示例:

将结构体类型的数据写到文件中:

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { "zhangsan", 20, 95.5f };
	//打开文件
	FILE*pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		exit(-1);
	}
	//写文件
	fprintf(pf, "%s %d %.1f", s.name, s.age, s.score);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

再将保存的数据读取出来:

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct S s = { "zhangsan", 20, 95.5f };
	//打开文件
	FILE*pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		exit(-1);
	}
	
	//读文件
	fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
	printf("%s %d %f\n", s.name, s.age, s.score);
	
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

这里再补充说明一点 :

前面我们提到,键盘和屏幕是标准输入输出流,它俩的FILE指针分别写作:

stdin(标准输入流)    stdout(标准输出流)

那运用我们的奇思妙想,思考一下以下这两组的含义是否相同?

scanf(...)
fscanf(stdin,...)

printf(...)
fprintf(stdout, ...)

答案是肯定的。这两组是等价的。

那我们平时使用键盘和屏幕时,为什么不像文件那样先打开它们所对应的流呢?

原因在于,对任何一个C程序,只要运行起来就默认打开3个流

stdin------标准输入流------键盘

stdout------标准输出流------屏幕

stderr------标准错误流------屏幕

三者的类型都为FILE*

文件的随机读写


所谓随机读写,就是可以按照需求在文件的任意位置进行读写,而完成这个操作所需的两个重要参数就是偏移量和起始位置。

fseek

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

int fseek ( FILE * stream, long int offset, int origin );

返回值:

如果成功则返回0;

失败返回一个非负值。

示例:

#include<stdio.h>
int main()
{
	//打开文件
	FILE*pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		exit(-1);
	}
	//写文件
	fputs("This is an apple", pf);
	fseek(pf, 9, SEEK_SET);
	fputs(" sum",pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

ftell

返回当前位置相较于文件起始位置的偏移量。

long int ftell ( FILE * stream );

示例:

#include<stdio.h>
int main()
{
	//打开文件
	FILE*pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		exit(-1);
	}
	//打印偏移量
	fseek(pf, 9, SEEK_SET);
	printf("%d\n", ftell(pf));
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

//打开文件

FILE*pf = fopen(“test.txt”, “w”);
if (NULL == pf)
{
perror(“fopen”);
exit(-1);
}
//写文件
fputs(“This is an apple”, pf);
fseek(pf, 9, SEEK_SET);
fputs(" sum",pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}



ftell

返回当前位置相较于文件起始位置的偏移量。

long int ftell ( FILE * stream );

示例:

#include<stdio.h>
int main()
{
	//打开文件
	FILE*pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		exit(-1);
	}
	//打印偏移量
	fseek(pf, 9, SEEK_SET);
	printf("%d\n", ftell(pf));
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)
[外链图片转存中…(img-aQpAHfKW-1713337801585)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值