首页 > 其他分享 >文件操作(1)(C语言版)

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

时间:2024-06-23 18:28:25浏览次数:21  
标签:文件 NULL return int C语言 pf 操作 fopen

前言:

        

        为什么要学习文件操作:

        1、如果大家写过一些代码,当运行结束的时候,这些运行结果将不复存在,除非,再次运行时这些结果才能展现在屏幕上面,就比如之前写过的通讯录。

        现实中的通讯录可以保存自己写进去的信息,下次方便查找,但是我们写的当程序推出结束后,里面的信息也随之销毁不会保存

      2、  是因为我们运行的结果都存在了内存当中,程序结束后内存中的数据将会自动清空,但是我们找到我们保存在C盘或者是其它盘中的文件数据就算电脑关机也不会被清除,原因是这些文件数据都保存在硬盘中,硬盘中的数据不会自动清空,所以一般我们删除一些文件都是手动删除。

        所以学会文件的相关操作以后,数据就可以直接保存在硬盘当中!!!

文件的分类:

        我们经常看到不同的文件,但是在程序设计的时候文件有以下两种:

1、程序文件:

常以 .c \ .obj \ .exe结尾的

        

        

       

2、数据文件:

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

例如:

文本文档.txt,

文件名:

        一个完整的文件,肯定是有完整的文件名,文件名有如下几部分组成:


        文件路径+文件名主干+文件后缀

        例如: c:\code\test1.txt

文件的打开与关闭:

        我们向文件中存储数据的步骤应该是:

        1、打开文件。

        2、输入要存入的数据。

        3、关闭文件。

1、打开文件:

        当我们打开文件前vs会提供给我们一个FILE类型的结构体:

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE;

        编译器会开辟一个文件信息区,这些文件的地址,名称,大小等等的一些信息会保存在这个地方,不同编译器提供的文件信息可能有所不同。

        我们通常会创建一个FILE*的指针维护文件信息,当打开文件的时候,会返回文件的相关信息的地址,文件的相关内容我们用FILE*去接收。

 fopen打开文件:

        要打开一个文件,我们通常用fopen函数打开,需要包括fopen相关的头文件

        #include<stdio.h>

        当然fopen打开文件有如下的打开方式:

具体打开代码如下:

        

#include<stdio.h>
int main()
{
	FILE* pf = fopen("cool.txt", "w");
    
	return 0;
}

对fopen传参的说明:

   

 第一个"  " 里面写你要打开的文件的文件名,有两种写法:
          第一种相对路径打开:如果文件名称前面什么都不加,那就表示在当前程序存放的路      径下打开
          如果加..\\表示在上一级路径下打开..\\..\\表示在上上级路径下打开
          第二种绝对路径打开:写入完整的名称,也就是完整的文件路径,从根目录到该文件      的路径
            例如:D:\cold\2024_6_16_\2024_6_16_

第二个"  "里面写的是你要用哪种方式打开文件
          如果要用写("w")的形式打开,如果相路径中没有对应的文件,就会自己创建一个

当然也有可能文件打开失败,所以要判断一下,fopen函数打开失败的时候会返回NULL

指针:

所以代码改造为:

int main()
{
	FILE*pf = fopen("cool.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	return 0;
}

2、关闭文件

        关闭文件我们用fclose关闭。

        传参只需要传需要关闭文件的的地址。

        代码如下:

	fclose(pf);

        但是关闭完之后,pf变量中存的文件地址是不是还存在呢?

        答案是存在的,这是pf中存的地址不再是我们开辟的了,导致FILE*pf变成了野指针,所以最后要将pf == NULL。

        代码改造如下:

	fclose(pf);
	pf = NULL;

完整文件打开与关闭代码:

int main()
{
	FILE*pf = fopen("cool.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

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

运行结果:

        

文件的读写操作:

        介绍完文件如何打开与关闭后,需要我们知道如何将我们想要将内容写入文件中

我们需要知道几个函数和相应的功能

流的概念:

数据和外部设备进行相互交互的时候,都是通过流(数据流)进行交互。

并不是直接进行信息交换的!

        传输不同的数据的时候,我们需要把数据传输到不同的流当中,当然在c语言运行的时候,编译器会自动打开三个标准流,使得我们可以直接传输:

1、标准输入流:stdin

2、标准输出流:stdout

3、标准错误流:stderr

在我们使用printf在屏幕上打印一些数据的时候就要用到标准输出流

在我们使用scanf从键盘上获取数据到内存中的时候就要用到标准输入流

这里的流也可以理解为FILE*的指针!

有上述一些输入输出函数和流的基本概念,接下来我们一个一个探讨和举例。

fgetc和fputc函数

fputc字符输出函数

使用如下:

int main()
{
	FILE* pf = fopen("cool.txt", "w");//写入文件要用"w"
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputc('a',pf);//输出字符
	fclose(pf);
	pf = NULL;
	return 0;
}

两个参数:

第一个参数:传入想写的字符。

第二个参数:是写你要通过哪个流传入,也就是文件的地址。

效果如下:

那如果我想要穿多个字符进去,该怎么传进去?

在使用fgetc的时候每传进去一个字符,它的光标自动就会往右移一个位置,等待下一个数据传入。

int main()
{
	FILE* pf = fopen("cool.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputc('a',pf);
	fputc('b', pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

cool.txt文件中就不会打印出ab呢?

最终会打印ab,也就证实了每当用fgetc输出一个字符,对应的字符指针(光标)会自动往后移一个

可以用循环打印字母表:

int main()
{
	FILE* pf = fopen("cool.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char pc = 0;
	for (pc = 'a'; pc <= 'z'; pc++)
	{
		fputc(pc, pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

当然此时我不想让它输出到文件中,我想让它输出到屏幕上,我们可以用标准输出流:

代码如下:

int main()
{
	FILE* pf = fopen("cool.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char pc = 0;
	for (pc = 'a'; pc <= 'z'; pc++)
	{
		fputc(pc, stdout);//文件的地址换成标准输出流
	}
	fclose(pf);
	pf = NULL;
	return 0;
}


输出结果:

fgetc字符输入函数:

前提:

在用这个函数的时候打开文件的时候我们需要将打开方式变为只读的形式,一定要相互匹配。

此时我在txt文件中输入abcd。

可以用fgtec读取并存入变量中,代码如下:

int main()
{
	FILE* pf = fopen("cool.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int arr = fgetc(pf);
	printf("%c\n", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

fgets和fputs函数

fputs字符串输出函数:

        该函数可以将字符串输出到文件中,代码如下:

int main()
{
	FILE* pf = fopen("cool.txt", "w");//必须是写的形式打开文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcde", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

其函数和字符函数fputc比较相似,只不过传入的字符变成字符串。

fgets字符串输入函数:

        将字符串输入到内存中,保存在字符数组中并打印。

不一样的是,fgets参数有三个:

第一个参数是:你要讲字符串输入到什么地方,

第二个参数是:输入的字符的个数包括\0也就是你想输入3个字符,这里num必须是4,因为这4个里面有一个是\0。

第三个参数是:文件的地址。

例如:

我在文本文件中输入abcde,然后在屏幕上打印abc,我应该传入哪些参数?

代码如下:

int main()
{
	FILE* pf = fopen("cool.txt", "r");//这里一定要用读的形式打开
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[20];
	fgets(arr, 4, pf);
	printf("%s\n", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

fscanf和fprintf函数

fprintf格式化输出函数:

那么它和printf的区别在哪?

fprintf有两个参数,相较于printf多了第一个参数——文件地址。

fprintf函数的使用:

int main()
{
	FILE* pf = fopen("cool.txt", "w");//以写的方式打开
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[] = { "i love world" };
	fprintf(pf, "%s\n%d\n", arr,3);
	fclose(pf);
	pf = NULL;
	return 0;
}

这个格式化输出函数传入数据就十分方便了。

想穿什么类型的数据都可以,只要格式正确。

fscanf格式化输入函数:

这里的fscanf和scanf的区别是什么呢?

注意fscanf还是需要多一个参数,文件的地址,而且,fscanf当遇到第一个非空格字符开始输入,当再次遇到空格字符就会停止输入!!!

就比如:

fscanf字符光标一直往后找,找到第一个非空格字符读取,每读一个光标往后移一个,直到再次遇到空格字符停止读取。

int main()
{
	FILE* pf = fopen("cool.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[20];
	/*int n = 8;*/
	fscanf(pf, "%s", arr);
	/*fscanf(pf, "%d", &n);*/
	printf("%s\n", arr);
	fclose(pf);
	pf = NULL;
	return 0;
} 

此时运行结果:

当写成这样:

运行结果:

当然要想读取不同类型的数据,我们可以将不同类型的数据用空格字符隔开,然后多次利用fscanf读取!

例如:

int main()
{
	FILE* pf = fopen("cool.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char arr[20];
	int n = 8;
	float a = 0;
	fscanf(pf, "%s", arr);
	fscanf(pf, "%d", &n);
	fscanf(pf, "%f", &a);
	printf("%s %d %f\n", arr,n,a);
	fclose(pf);
	pf = NULL;
	return 0;
} 

fread和fwrite函数

fwrite二进制输出函数:

注:此时文档是二进制文档,文档中存的是数据的二进制

 

有四个参数:

第一个参数:需要传入输出的变量的地址

第二个参数:需要传入每一个变量的大小。

第三个参数:数据的个数

第四个参数:文件的地址

int main()
{
	FILE* pf = fopen("cool.txt","wb");
	if (pf == NULL)
	{
		perror("fopen");
	}
	char arr[] = {"abcde"};
	int arr1[] = {1,2,3,4,5,6};
	fwrite(arr1,sizeof(int),6,pf);
	fwrite(arr, sizeof(char), 5, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

fread二进制输入函数:

它需要的参数和fwrite是一样的,但是我们需要注意

fread的返回值类型是size_t类型,返回读取到的数据的个数!!

这里应该做一个判断。

int main()
{
	FILE* pf = fopen("cool.txt","rb");//二进制读文件
	if (pf == NULL)
	{
		perror("fopen");
	}
	int i = 0;
	char arr[] = {"abcde"};
	int arr1[] = {1,2,3,4,5,6};
	fread(arr1,sizeof(int),6,pf);
	fread(arr, sizeof(char), 5, pf);
	for (i = 0; i < 6; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("%s", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

sprintf和sscanf函数

sprintf函数:

是将格式化的数据转化成字符串。

例如:

struct S
{
	int n;
	float a;
	char b;
};
int main()
{
	struct S s = { 10,(float)3.14,'a' };
	char arr[100];
	sprintf(arr,"%d %lf %c",s.n,s.a,s.b);
	printf("%s\n", arr);
	return 0;
}

sscanf函数:

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

struct S
{
	int n;
	float a;
	char b;
};
//int main()
//{
//	struct S s = { 10,(float)3.14,'a' };
//	char arr[100];
//	sprintf(arr,"%d %lf %c",s.n,s.a,s.b);
//	printf("%s\n", arr);
//	return 0;
//}

int main()
{
	struct S s = { 10,(float)3.14,'a' };
	char arr[100];
	sprintf(arr,"%d %f %c",s.n,s.a,s.b);
	sscanf(arr, "%d %f %c", &(s.n), &(s.a), &(s.b));
	printf("%d\n", s.n);
	printf("%f\n", s.a);
	printf("%c\n", s.b);
	return 0;
}

标签:文件,NULL,return,int,C语言,pf,操作,fopen
From: https://blog.csdn.net/m0_75235246/article/details/139735258

相关文章

  • 在Windows环境中,如果你希望禁用通过Win+R快捷键运行命令提示符(cmd),可以采取以下方法。
    在Windows环境中,如果你希望禁用通过Win+R快捷键运行命令提示符(cmd),可以采取以下方法。这些方法包括组策略编辑器和注册表编辑器,但请注意,修改系统设置可能会影响系统的其他功能,应谨慎操作。方法1:使用组策略编辑器打开组策略编辑器:按 Win+R,输入 gpedit.msc,然后按回车。......
  • 了解如何使用DIR命令来查看和管理文件系统中的文件和目录;更加灵活地利用 DIR 命令来筛
    应用大纲:初级使用方法1.基本用法使用 DIR 命令来列出当前目录中的所有文件和子目录。2.切换到不同目录使用 DIR[驱动器:][路径] 来列出指定目录中的文件和子目录。例如,DIRC:\Users。3.常用选项/P:分页显示结果,每页一屏。/W:宽列表格式显示,减少详细信息。/A:按......
  • 初阶《操作符详解》 3. 移位操作符
    3.移位操作符<< 左移操作符>> 右移操作符注:移动的是二进制位,移位操作符的操作数只能是整数。一个存储的二进制码分原码、反码、补码1.十进制数据的二进制表现形式就是原码,原码最左边的一个数字就是符号位,0为正,1为负。2.正的整数的原码、反码、补码相同3.负的......
  • 如何学习C语言
    学习三阶段:初识——>初阶——>进阶注:蓝色字体皆可跳转一阶:初识1.基本了解C语言的基础知识,对C语言有一个大概的认识2.简单认识每个知识点,后期在初阶和进阶进行详细描述学习内容1.什么是C语言2.第一个C语言程序3.数据类型4.变量、常量5.字符串、转义字符、注释......
  • 子比主题最新7.8版本改hosts绕过授权方法 附主题文件
    简介子比主题是可玩性很高的一款主题,也是本站同款主题。子比主题7.8授权验证算法与7.7一样,使用7.7授权文件的朋友可直接更新。使用方法搭建一个站点,绑定api.zibll.com域名,并开启SSL(随便找个域名的证书就行)上传以上源码,并配置好伪静态最后在/etc/hosts里面加一行127.0......
  • VScode配置C语言开发环境
    可以总结为两步1.本地安装和配置编译器2.VScode上安装C/C++扩展最后直接运行即可安装和配置编译器Windows系统可以使用mingw64,发布网址在这里https://sourceforge.net/projects/mingw-w64/files/这是压缩包格式,可以自由选择目录解压,比如我把mingw64放在D盘根目录在命......
  • juicefs cubefs 等元数据分离文件系统分析
    在近期我看到过国外一个大牛开发的hpfshttps://mp.csdn.net/mp_blog/creation/editor/139739977(请看我前面发的片文章)我瞬间就想到国内同类似产品juicefscubefs这两个东西,当时这种产品出现我就有一个疑问,为什么要把元数据单独弄个数据库去存呢?你还要开发数据冗余机制去保......
  • 操作系统的发展史、多道技术、进程理论、进程的三状态、同步异步/阻塞与非阻塞、开启
    【操作系统发展史】1为什么要使用操作系统呢?2程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,3这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱了出来,4只需要考虑自己的应用软件的编写就可以了,应用软件......
  • C语言之常用标准库介绍
    目录1标准库1.1诊断assert.h1.2字符类别测试ctype.h1.3错误处理errno.h1.4整型常量limits.h1.5地域环境locale.h1.6数学函数math.h1.7非局部跳转setjmp.h1.8可变参数表stdarg.h1.9公共定义stddef.h1.10输入输出stdio.h1.11实用函数stdlib.h1.12日期与时间函数time.h1......
  • C语言之IO流函数
    目录1IO函数1.1错误函数1.1.1检测流上的错误函数ferror1.1.2复位错误标志函数clearerr1.2结束函数1.2.1检测文件结束符函数feof1.2.2清除文件缓冲区函数fflush1.3处理文件函数1.3.1文件的打开与关闭函数fopen,fclose1.3.2替换文件中数据流函数freopen1.3.3文件指针定......