当前位置: 首页 > article >正文

C语言文件操作复习回顾(1)

关于流,内存数据读写铺垫的复习

  1. 打开一个文件 -> 内存里面就会创建一个对应关联的文件信息区 -> 文件信息区其实就是一个FILE类型的结构体 -> 各个结构体成员记录了该文件的种种信息 -> 结构体(文件信息区)由FILE* 结构体指针来维护 -> 有了指针,一切都好说了
  2. 输入输出/读写都是站在内存/程序的角度
  3. 任何一个C语言程序运行的时候,默认会打开三个流:stdin(标准输入), stdout(标准输出), stderr(标准错误)。stdin, stdout, stderr就是三个管理标准输入流,标准输出流,标注错误流的FILE*指针
    在这里插入图片描述
  4. 这个流的类型就是FILE这样一个结构体。这个流其实就是由我们的FILEstream指针来管理的。流相当于是一个FILE类型的结构体,然后FILE相当于是维护流的一个指针
  5. 如果说内存数据要输出到文件里面,你要去看看针对文件的流有没有被打开, 如果说内存数据要输出到网络里面,你要去看看针对网络的流有没有被打开, 如果说内存数据要输出到软盘里面,你要去看看针对软盘的流有没有被打开…
  6. 因为我写程序他的数据不可能永远都是在内存当中,我有可能需要把这个数据放到文件当中,比如说需要放到我的终端设备当中,比如说要放到网络上面,当把数据放到这些外部输出设备的时候。对于程序员而言,他不一定懂各种细节,所以说在c语言当中就抽象出了流这么一个概念。就是说不管三七二十一,直接把数据放到流上面,然后具体这些数据是怎么传到各种各样的外部输出设备是自己会分装好的。除了在c语言当中,程序它默认会打开三个流之外,如果说根据特定的需求,需要把数据传到其他各种各样的外部输出设备的话,就需要打开针对各种各样外部输出设备的一个流,然后实际上就是通过FILE*指针(结构体指针)来操作流(FILE结构体)。
  7. 我们在操作文件的时候,首先要打开文件拥有这个流。打开文件就好比打开了(没有被C语言默认打开的)针对文件的流,fopen()返回的FILE*指针与维护流的指针是一个道理
    在这里插入图片描述

利用输入输出流进行数据顺序读写(尤以文件为例)

文件里面没有整型等等,全部要么是字符,要么就是字符串,要么就是二进制,要么就是二进制信息解析成字符后的乱码

在这里插入图片描述
提醒一下:如果没有人为干预,文件指针都是自己自动动的

fputc() 一个字符输出

在这里插入图片描述
在这里插入图片描述

  1. 演示代码:
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen failed");
		return;
	}
	fputc('U', pf);
	fputc('S', pf);
	fputc('B', pf);

	fputc('U', stdout);
	fputc('S', stdout);
	fputc('A', stdout);
	fclose(pf);
	return 0;
}

fgetc() 一个字符输入

在这里插入图片描述
在这里插入图片描述

  1. 文件里面有多个字符的时候,我们用fgetc一个个去读取,此时定位文件位置的指针在fgetc每次读取完一次之后,就会后移一个字节往后走了一步指到下一个字符去了,因此fgetc一个个读取的话不需要顾虑太多,每次读取的时候只需要传参同一个FILE*结构体指针(事实上你其他的也传不了)
  2. 演示代码:
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen failed");
		return;
	}
	
	printf("%c\n", fgetc(pf));
	printf("%c\n", fgetc(pf));
	printf("%c\n", fgetc(pf));
	printf("%d\n", fgetc(pf));  //EOF  即-1

	fclose(pf);
	return 0;
}

fputs() 一行字符串输出 + 一个\n的问题注意一下

在这里插入图片描述

  1. 由于fputs针对的是一行字符串的输出,如果说多次调用fputs的话,比如说把字符串给他写到文件里面去,那么这多个字符串之间并不会默认换行,如果说想要达到换行的这个效果,那么就必须在输出每行字符串的时候,在字符串的末尾加上转义字符换行符\n
  2. 演示代码:
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen failed");
		return;
	}

	fputs("the United States Of American\n", pf);
	fputs("the United States Of American\n", pf);
	
	fclose(pf);
	return 0;
}

在这里插入图片描述

fgets() 一行字符串输入 + \n三特性

在这里插入图片描述

  1. 中间这个参数就是指从外部输出设备的字符串输入到内存当中的字符的个数,因为是把字符串从外部输出设备输入到内存,然后它这个字符串结束符\0是默认会强制占掉一个空间,所以说比如说你想要往内存当中输进来六个字符的字符串,你那个第二个参数应该要设置成7。
  2. 然后这个函数它只能处理一行,比如说这一行只有三个字符,下一行有300个字符,然后你采用这个函数fgets,那个参数设置成50,那么这个函数执行完成之后,你读进来的也只有这一行的那三个字符+换行符 共4个字符的字符串而已。
  3. 在文件当中,每一行的字符串末尾都默认带有一个换行符。需要注意几点:1. 这个换行符是一个实体的存在,什么意思呢?主要影响就在于fgets的第二个参数,如果在统计的时候在一行当中延伸到了换行符\n,那么这个换行符也是算做一个字符,也需要参与计数。2. 拷贝文件一行字符串的时候换行符也是可能会被拷贝到内存字符串当中的,这时候打印的时候就会产生效果与影响。3. 当文件指针碰到文件字符串一行当中的换行符时,文件指针自己也会去换行。但无论如何要记住:fgets永远处理的都是一行字符串,文件指针换行后不会又继续去拷贝下一行内容。
  4. 演示代码:
    在这里插入图片描述
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen failed");
		return;
	}

	char arr1[20] = { 0 };
	char arr2[20] = { 0 };

	fgets(arr1, 16, pf);
	fgets(arr2, 6, pf);

	printf("arr1 : %s", arr1);
	printf("arr2 : %s", arr2);
	fclose(pf);
	return 0;
}

在这里插入图片描述

fprintf() 格式化字符串输出 + 参照printf就可以了

在这里插入图片描述

  1. 如果用fprintf的话非常简单,就先正常按照printf去写,然后在括号最前面再加上一个参数(流指针),如:指向要写入文件的文件信息区的文件指针。这就是把格式化的信息写到文件里面去。
  2. 演示代码:
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen failed");
		return;
	}

	fprintf(pf, "%c %d %s\n", 'Y', 2, "我真是醉了");
	fprintf(pf, "%.3f %.1lf %s%c\n", 11.99954, 22.833, "无语了", 'Q');

	fclose(pf);
	return 0;
}

在这里插入图片描述

fscanf() 格式化字符串输入 + 文件指针换行问题不用考虑

在这里插入图片描述

  1. fscanf就是从文件里面把里面的信息拿到内存里面去。这个函数又与scanf十分相似,参数比scanf多了一个FILE*指针。
  2. 因此你先用scanf一如既往像以前那样正常写好,注意:scanf/fscanf的末尾几个参数都必须是地址形式,因为我是要把数据真真切切地读入到内存里面去,必须给我传地址!当然,数组名是首元素地址就不用&了。再在最前面加上参数:文件指针就OK了。
  3. 代码演示:
    在这里插入图片描述
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen failed");
		return;
	}

	char ch1 = 0;
	char ch2 = 0;
	int num = 0;
	char arr1[20] = { 0 };
	char arr2[20] = { 0 };
	float f1 = 0;
	double f2 = 0;


	fscanf(pf, "%c %d %s\n", &ch1, &num, arr1);

	fscanf(pf, "%f %lf %s %c\n", &f1, &f2, arr2, &ch2);

	printf("ch1: %c\n",ch1);
	printf("num: %d\n", num);
	printf("arr1: %s\n", arr1);

	printf("f1: %.2f\n", f1);
	printf("f2: %.1lf\n", f2);
	printf("arr2: %s\n", arr2);
	printf("ch2: %c\n", ch2);

	fclose(pf);
	return 0;
}

在这里插入图片描述

fread() 与 fwrite() 二进制输入输出只能针对文件流

sprintf() 随意粘连任何已有东西+自己也可以添油加醋+组成一个新的字符串(类型很自由)

int main()
{
	int num = 10;
	char ch = 'A';
	char* p1 = "我裂开了";
	float f = 12.5345;
	char* p2 = "哈哈哈哈哈";
	char arr[100] = { 0 };
	sprintf(arr, "%d%c%s   %s %f 666666我的新字符串", num, ch, p1, p2, f);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述

sscanf() 随意从已有字符串抠来一些东西 + 放到新的变量当中(类型很自由)

int main()
{
	char arr[50] = "我哈哈哈哈哈        666    114514Q";
	char arr1[50] = { 0 };
	int num1 = 0;
	int num2 = 0;
	char ch = 0;
	sscanf(arr, "%s %d %d %c", arr1, &num1, &num2, &ch);
	printf("%s\n", arr1);
	printf("%d\n", num1);
	printf("%d\n", num2);
	printf("%c\n", ch);
	return 0;
}

在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/10120.html

相关文章:

  • Matlab实现鹈鹕优化算法(POA)求解路径规划问题
  • Mysql前言
  • 【在Linux世界中追寻伟大的One Piece】多路转接epoll
  • 全球碳循环数据集(2000-2023)包括总初级生产力、生态系统净碳交换和生态系统呼吸变量
  • [CKS] Create/Read/Mount a Secret in K8S
  • .netCore WebAPI中字符串加密与解密
  • 基于STM32的倒车雷达系统设计
  • JAVA解析XML时的内存消耗问题
  • IronOCR for .NET crack,IronOCR的独特功能
  • CMake入门教程【核心篇】8.0构建目标
  • 2023-03-18青少年软件编程(C语言)等级考试试卷(一级)解析
  • 是时候告别这些 Python 库了
  • 你真的会用background属性?
  • 【51单片机Task】:led十六进制控制led灯详解、按键控制流水灯、跑马灯等任务
  • x210官方uboot配置编译
  • DNS服务器配置
  • 机器学习和深度学习在气象中的应用(台风预报只能订正、风速预报订正、LSTM 方法预测 ENSO)
  • 基于Spring boot和Vue3的博客平台:系统通知、评论回复通知、专栏更新通知、用户角色与权限管理模块
  • 数据技术嘉年华星光璀璨,云和恩墨全栈数据技术能力闪耀会场
  • Vue实现自动化平台(五)--用例编辑页面
  • ​InnoDB引擎之flush脏页​
  • 大数据4 - 分布式计算
  • 电话机器人开发
  • c++学习之c++对c的扩展2
  • Zebec Protocol 出席香港 Web3 峰会,带来了哪些信息?
  • ROS开发之如何制作launch启动文件?