【C语言】通讯录《信息写到文件版本》

news2024/11/24 8:27:48

🚩write in front🚩   

🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
🏅2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家博主 & 星级博主~掘金⇿InfoQ~51CTO创作者[新人榜No.7]~周榜257﹣总榜931⇿全网访问量40w+🏅
🆔本文由 謓泽 原创 CSDN首发🙉如需转载还请通知⚠

📺创作时间 ↔ 2021年3月18日◬
📝个人主页-謓泽的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​
📣系列专栏-
YY_謓泽的博客-CSDN博客🎓
✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本📩

目录

🚩write in front🚩   

概述 

增添の功能

Save_Contact() → 保存通讯录信息

读文件操作 

模块化代码实现 

Ⅰ→  test.c

Ⅱ→address_book.h

Ⅲ→address_book.c

✨最后✨

概述 

这个是在之前的动态版本进行添加,如果你不清楚通讯录的静态或者是动态怎么实现。可以看看博主写的前面两篇通讯录的静态和动态的实现↓

🍖链接→🍖【C语言】通讯录《静态内存版本》_謓泽的博客-CSDN博客

🍗链接→🍗【C语言】通讯录《动态内存版本》_謓泽的博客-CSDN博客


增添の功能

相比之前的静态版本还是动态版本。这个信息写到文件版本,无疑是更加完善的。如果你不会文件操作的话,可以看看我前面写过的内存的一篇博客来看看⇣

链接→【C语言】内存函数_謓泽的博客-CSDN博客

增添の功能↓

(1)→当通讯录退出的时候,把信息写到文件里面。

(2)→当通讯录初始化的时候,加载文件的信息到通讯录当中去。

在上述的博客当中我们是↓

Destory_Contact(&con);//销毁通讯录

而在这篇博客我们实现的是首先要保存通讯录,也就是保存信息到文件去。那么我们创建一个函数实现保存信息到文件里。

Save_Contact(&con);//保存信息到文件

Save_Contact() → 保存通讯录信息

那么首先我们要实现这个保存通讯录信息到文件的这个函数。

Save_Contact() 代码示例如下↓

//读写信息到文件
void Save_Contact(Contact* pc)
{
	FILE* pf = fopen("information.txt","w");
	//返回值判断
	if (pf == NULL)
	{
		perror("Save_Contact:");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		//数组名+i就是数组名下标元素的地址。
		fwrite(pc->date + i, sizeof(information), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

那么现在我们就可以试一下,那我们就把张三同学的通讯录信息写下。

张三:?????????????,算了为了张三同学的隐私我们就不这样了(o゚v゚)ノ

直接简单一点打印输入数字①来康康吧。

从上述的截屏当中可以知道我们是写入进去东西的。


读文件操作 

现在我们保存文件是没有任何的问题了,但是当我们再次运行通讯录的时候。通讯录依然会什么都会没有。所以,此时我们就需要进行读文件的一个操作。

我们在初始化的时候就可以进行读文件的一个操作了,因为在此之前已经有增删查改了。

那我们封装一个函数用read_file()来进行实现。 

void read_file(Contact* pc)
{
	FILE* pf = fopen("information.txt", "r");
	//返回值判断
	if (pf == NULL)
	{
		perror("read_file");
		return;
	}
	//读文件
	information tmp = {0};//问题:读文件停止(不知道你写入几个信息)?返回值的问题实际count
	while (fread(&tmp, sizeof(information), 1, pf))//读不到返回0
	{
		//是否增容
		Cap_inc(pc);
		//存放增容元素
		pc->date[pc->sz] = tmp;
		//加载信息
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

让我们来看看是否能进行一个读文件的操作。检测是非常简单的,我们先输入一个张三,再退出程序。然后,再输入一个李四。看看能不能读写上次张三的信息。

输入界面数字:6 即可(o゚v゚)ノ

第一次的输入! 

上述的读写操作是成功的。 

第二次的输入!

从这里我们可以知道它保存了我们上述的读写的值,也就是读文件的操作我们是成功的了。


模块化代码实现 

Ⅰ→  test.c

代码示例如下↓

/*
	@Note1:当通讯录退出的时候,把信息写道文件。
	@Note2:当通讯录初始化的时候,加载文件的信息。
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include"a.h"
#include<Windows.h>
#pragma warning(disable:6031)
//颜色函数
void color(short x)
{
	if (x >= 0 && x <= 15)
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
//创建菜单函数
void menu()
{
	color(0);//黑色
	system("cls");//清屏

	color(12);//白色
	printf("¤--------------------------------------------¤\n");
	printf("|■■■■■■■■→通讯录v1.0←■■■■■■■■|\n");
	printf("|———————————————————————|\n");
	printf("|★★★★★→1.increase ■ 2.deLete←★★★★★|\n");
	printf("|★★★★★→3.find     ■ 4.Revise←★★★★★|\n");
	printf("|★★★★★→5.Check    ■ 6.Print ←★★★★★|\n");
	printf("|★★★★★→0.Exit     ■         ←★★★★★|\n");
	printf("|———————————————————————|\n");
	printf("|■■■■■■■■→通讯录v1.0←■■■■■■■■|\n");
	printf("¤--------------------------------------------¤\n");
}
enum Number
{
	Exit,
	Increase,
	DeLete,
	Find,
	Revise,
	Check,
	Print,
};
int main(void)
{
	menu();
	int input = 0;
	//当然初始化全0:Contact con = {0};也是可以的,当然我们这里的初始化不是这样的原因是可以应对比较复杂的问题。
	Contact con;//初始化通讯录
	//给date申请一块连续的内存空间存放在堆区上。
	InitContact(&con);
	do
	{
		color(5);
		printf("¤----------------¤\n");
		printf("|请输入界面上的数字|:");
		scanf("%d", &input);
		printf("¤----------------¤\n");
		color(1);
		switch (input)
		{
		case Exit:
			//销毁之前先保存。
			Save_Contact(&con);
			//把通讯录里面的内存空间date给释放掉。
			Destory_Contact(&con);//销毁通讯录。
			printf("══════════════@\n");
			printf("退出通讯录v1.0@\n");
			printf("══════════════@\n");
			break;
		case Increase:
			//增加人的信息,放在通讯录当中去。
			Add_Contact(&con);
			break;
		case DeLete:
			//删除通讯人的信息
			DeLete_Contact(&con);
			break;
		case Find:
			//查找指定通讯录人的信息
			Find_Contact(&con);
			break;
		case Revise:
			//修改指定通讯录人的信息
			Revise_Contact(&con);
			break;
		case Check:
			//排查通讯录当中人员的信息
			Check_Contact(&con);
			break;
		case Print:
			//打印通讯录当中人员的信息。
			Print_Contact(&con);
			break;
		default:printf("你输入的数字找不到,请重新输入~\n");
		}
	} while (input);
	return 0;
}

Ⅱ→address_book.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h> 
#include<stdlib.h>
#include<Windows.h>
#include<string.h>

#define Max_name 5
#define Max_age 100
#define Max_genger 3
#define Max_address 20
#define Max_telephone 20

//#define num 1000 //静态的存放
#define Defsz 3 //一开始的值
#define Inc 2  //每次的增量

//类型的定义
typedef struct information
{
	//名字、年龄、性别、电话、地址。
	char name[Max_name];
	char age[Max_age];
	char genger[Max_genger];
	char telephone[Max_telephone];
	char address[Max_address];
}information;

//通讯录 - 动态版本
typedef struct Contact
{
	//这里用了个结构体嵌套
	information* date;//指向动态内存的申请空间,用于存放联系人的信息。
	int sz;//记录当前通讯录有效信息的个数。
	int capacity;//表示当前通讯录的最大"容量"大小。
}Contact;

//初始化通讯录
void InitContact(Contact* pc);
//增加通讯录信息
void Add_Contact(Contact* pc);
//打印通讯录的信息
void Print_Contact(const Contact* pc);
//删除通讯人的信息
void DeLete_Contact(Contact* pc);
//查找指定通讯录人的信息
void Find_Contact(Contact* pc);
//修改指定通讯录人的信息
void Revise_Contact(Contact* pc);
//排查通讯录当中人员的信息
void Check_Contact(Contact* pc);
//销毁通讯录
void Destory_Contact(Contact* pc);

//保存通讯录信息到文件
void Save_Contact(Contact* pc);

//读文件-加载文件
void read_file(Contact* pc);

//检测增容
void Cap_inc(Contact* pc);

Ⅲ→address_book.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"address_book.h"

//读文件-加载文件
void read_file(Contact* pc)
{
	FILE* pf = fopen("information.txt", "r");
	//返回值判断
	if (pf == NULL)
	{
		perror("read_file");
		return;
	}
	//读文件
	information tmp = {0};//问题:读文件停止(不知道你写入几个信息)?返回值的问题实际count
	while (fread(&tmp, sizeof(information), 1, pf))//读不到返回0
	{
		//是否增容
		Cap_inc(pc);
		//存放增容元素
		pc->date[pc->sz] = tmp;
		//加载信息
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

//动态版本进行初始化
void InitContact(Contact* pc)
{
	pc->date = (information*)malloc(Defsz * sizeof(information));
	if (pc->date == NULL)
	{
		perror("InitContact");
		return;
	}
	//如果返回的为空指针的情况
	pc->sz = 0;//sz初始化
	pc->capacity = Defsz;//当前最大"容量"

	//读文件-加载文件
	read_file(pc);
}

//增容函数
void Cap_inc(Contact* pc)
{
	//当记录当前通讯录有效信息的个数 等于 表示当前通讯录的最大"容量"大小。
	if (pc->sz == pc->capacity)
	{
		//给堆区增加"容量",因为空间不够。
		information* pa = (information*)realloc(pc->date, (pc->capacity + Inc)*(sizeof(information)));
		if (pa != NULL)
		{
			pc->date = pa;//把这块空间移交到date进行维护
			pc->capacity = pc->capacity + Inc;//由于这里我们进行了增容也需要把容量改变成+Inc的值

			printf("增加联系人已成功(@^0^)\n");
		}
		//增容失败
		else
		{
			perror("Add_Contact:");
			printf("增加联系人失败!(ToT)/~~~\n");
			return;
		}
	}
}

//动态版本增加
void Add_Contact(Contact* pc)
{
	//检测容量
	Cap_inc(pc);
	//增加一个人的信息
	printf("\n");
	printf("请输入增加人的名字->:");
	scanf("%s", pc->date[pc->sz].name);//注意→数组名是首元素地址,所以不用进行取地址.

	printf("请输入增加人的年龄->:");
	scanf("%s", pc->date[pc->sz].age);

	printf("请输入增加人的性别->:");
	scanf("%s", pc->date[pc->sz].genger);

	printf("请输入增加人的电话->:");
	scanf("%s", pc->date[pc->sz].telephone);

	printf("请输入增加人的地址->:");
	scanf("%s", pc->date[pc->sz].address);
	//成功~
	pc->sz++;
	printf("★恭喜你~添加信息成功★\n");
	printf("\n");
}

//读写信息到文件
void Save_Contact(Contact* pc)
{
	FILE* pf = fopen("information.txt","w");
	//返回值判断
	if (pf == NULL)
	{
		perror("Save_Contact:");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		//数组名+i就是数组名下标元素的地址。
		fwrite(pc->date + i, sizeof(information), 1, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

void Print_Contact(const Contact* pc)
{
	int i = 0;
	//打印标题栏的信息
	printf("|-------------------------------------------------------|\n");
	printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");

	for (i = 0; i < pc->sz; i++)
	{
		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].genger,
			pc->date[i].telephone,
			pc->date[i].address);
	}
}

static int FindByname(Contact* pc, char name[])
{
	int i = 0;
	//用for循环进行遍历
	for (i = 0; i < pc->sz; i++)
	{
		//strcmp()比较字符串
		if (strcmp(pc->date[i].name, name) == 0)
		{
			return i;//返回下标
		}
	}
	return -1;
}

void DeLete_Contact(Contact* pc)
{
	char name[Max_name] = { 0 };
	//通讯录为空的时候
	if (pc->sz == 0)
	{
		printf("通讯录当中没有任何信息\n");
		return;
	}
	printf("请输入你要删除的名字->:");
	scanf("%s", name);
	//查找要删除的人:有/没有
	int ret = FindByname(pc, name);
	if (ret == -1)
	{
		printf("没有查找到当前人的信息\n");
		return;
	}
	//删除
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->date[i] = pc->date[i + 1];
	}
	pc->sz--;//因为我们删除成功下标要减1
	printf("★恭喜你~删除信息成功★\n");
	printf("\n");
}

void Find_Contact(Contact* pc)
{
	char name[Max_name] = { 0 };
	printf("请输入你要查找的名字->:");
	scanf("%s", name);
	int ret = FindByname(pc, name);
	if (ret == -1)
	{
		printf("没有查找到当前人的名字\n");
		return;
	}
	else
	{
		printf("|-------------------------------------------------------|\n");
		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");

		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", 
			pc->date[ret].name,
			pc->date[ret].age,
			pc->date[ret].genger,
			pc->date[ret].telephone,
			pc->date[ret].address);
		printf("查找%sの信息成功~\n", pc->date[ret].name);
	}
}

void Revise_Contact(Contact* pc)
{
	char name[Max_name] = { 0 };
	printf("请输入你要修改通讯录人的名字->:");
	scanf("%s", name);
	int ret = FindByname(pc, name);
	if (ret == -1)
	{
		printf("当前修改人的信息不存在\n");
		return;
	}
	else
	{
		printf("请输入修改人的名字->:");
		scanf("%s", pc->date[ret].name);//注意→数组名是首元素地址,所以不用进行取地址.

		printf("请输入修改人的年龄->:");
		scanf("%s", pc->date[ret].age);

		printf("请输入修改人的性别->:");
		scanf("%s", pc->date[ret].genger);

		printf("请输入修改人的电话->:");
		scanf("%s", pc->date[ret].telephone);

		printf("请输入修改人的地址->:");
		scanf("%s", pc->date[ret].address);
		printf("恭喜你,修改成功~\n");
	}
}

int sort_name_max(const void* e1, const void* e2)
{
	return (strcmp(((struct Contact*)e1)->date->name, ((struct Contact*)e2)->date->name));
}

void Check_Contact(Contact* pc)
{
	//qosrt()函数首字母进行排序
	qsort(pc->date, pc->sz, sizeof(pc->date[0]), sort_name_max);
	printf("|-------------------------------------------------------|\n");
	printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", "名字", "年龄", "性别", "电话", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("|%-3s\t%-3s\t%-3s\t%-11s\t%-10s\t|\n", pc->date[i].name,
			pc->date[i].age,
			pc->date[i].genger,
			pc->date[i].telephone,
			pc->date[i].address);
	}
}

void Destory_Contact(Contact* pc)
{
	//销毁通讯录实际上就是把date给释放掉,free()函数进行回收即可。
	free(pc -> date);
	pc->date = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	//记得清0☆⌒(*^-゜)v THX!!
}

✨最后✨

那么这个就已经实现了通讯录的最终版本了,这个项目适合已经把C语言学完的人做。巩固自己以往的能力,做个这个提升自己逻辑思维和代码能力的一个小的项目。

记得三连^o^y

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

非零基础自学Golang 第9章 结构体 9.5 结构体方法

非零基础自学Golang 文章目录非零基础自学Golang第9章 结构体9.5 结构体方法9.5.1 指针类型接收者9.5.2 值类型接收者第9章 结构体 9.5 结构体方法 Go语言中&#xff0c;一个方法就是一个包含了接收者的函数。 对于结构体方法&#xff0c;接收者可以是结构体类型的值或是指针…

【图像融合】对比度增强结合多尺度边缘保持分解红外与可见光图像融合【含Matlab源码 1886期】

⛄一、对比度增强结合多尺度边缘保持分解红外与可见光图像融合简介 1 引言 夜视成像技术在军事与执法领域&#xff0c;如监控&#xff0c;侦查&#xff0c;情报搜集和安保等方面有着重要应用。不同类型的夜视成像传感器在记录同一场景时&#xff0c;在其提供的信息中有部分是冗…

目标检测论文解读复现【NO.21】基于改进YOLOv7的小目标检测

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0…

Java项目:基于SSM的高校运动会管理系统的设计与实现

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 该高校运动会信息管理系统是以B/S架构为设计基础并基于SSM框架开发的系统。系统采用了Java语言和MySQL数据库来实现。 系统按预定的算法完成了创…

数据结构---删去k个数字后的最小值

删去k个数字后的最小值思路贪心算法JAVA实现1JAVA实现2给出一个整数&#xff0c;从该整数中去掉k个数字&#xff0c;要求剩下的数字形成的新整数尽可能小。应该如何选取被去掉的数字&#xff1f; 其中整数的长度大于或等于k&#xff0c;给出的整数的大小可以超过long类型的数字…

计算机毕业设计 基于HTML+CSS+JavaScript 大气的甜品奶茶美食餐饮文化网页设计与实现23页面

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

Java+SSM房屋租赁系统房屋出租房产(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用的技术实现如下 后台框架&#xff1a;Spring、SpringMVC、MyBatis UI界面&#xff1a;jQuery 、JSP 数据库&#xff1a;MySQL 系统功能 系统分为前台用户界面和后台系统管理&#xff1a; 1.前台用户界面 用户注册、用户登录、用户中心、浏览房源、房源…

代码随想录训练营第54天|休息日 小结

打家劫舍系列 198. 打家劫舍对于当前的房间&#xff0c;无非就两种选择&#xff1a;偷与不偷。如果当前房间偷&#xff0c;那么前一个房间就不偷&#xff0c;即dp[i] dp[i-2] nums[i]&#xff1b;如果当前房间不偷&#xff0c;那么dp[i] dp[i-1]&#xff0c;因此递推公式为…

ch3_1_多进程的概念

1. CPU 的管理 CPU的工作原理&#xff1a; 从内存中取出程序的指令&#xff0c; 执行程序中的指令&#xff1b; 1.1 多道程序 假设A 程序运行时&#xff0c; 遇到 IO 处理时&#xff0c; 为了能够执行A 程序的后续指令&#xff0c; 正常情况下 cpu 需要等待着IO 处理完成&am…

后端快速学习VUE(一):VUE入门

个人博客地址 http://xiaohe-blog.top/ 文章目录1. 简介2. 基本使用2.1 引入Vue2.2 基本使用2.3 总结 &#xff1a;3. v-text、v-html指令的使用4. v-on : 事件绑定4.1 事件的三要素&#xff1a;4.2 v-on的基本使用4.3 v-on获取vue实例this4.4 事件绑定简化写法5. 常用指令5.1 …

useRef 源码解读

文章目录useRef 源码解读mountRefupdateRefref 的生命周期&#xff08;工作流程&#xff09;总结&#xff1a;render 阶段commit 阶段总述具体阐述safelyDetachRefcommitAttachRefuseRef 源码解读 由于 string 类型的 ref 已不推荐使用&#xff0c;所以只针对 function &#…

论文复现-1:bertscore

Bertscore是计算相似度的一种方法。 遗留问题&#xff1a;使用model layer 中的单一层 还是多个层&#xff0c;会对结果造成很大的影响吗&#xff1f; sent_encode函数是使用tokenizer将句子做encode。 tokenizer.encode( sent, add_special_tokensTrue, add_prefix_spaceTrue,…

HTML与CSS基础

2022.12.12 程序员在前端写完代码之后通过浏览器的渲染和解析成为用户看到的网页 浏览器出品的公司不同&#xff0c;内部的渲染引擎也不同。导致解析相同代码时的速度、性能、效果也不同 相同的前端网页在不同浏览器中运行的的结果也可能不同 WEB的三大标准 HTML包含页面内…

Java+MySQL基于SSM的智能办公管理系统

随着时代的发展,人们越来越来希望通过简单方便快捷的方式来进行办公,通过自能办公系统可以实现在线办公,这种办公模式脱离了传统纸质办公很多困扰,在实现现代化的同时提高了办公的效率。 本智能办公管理系统采用JAVA语言来进行开发,用小巧灵活的MySQL数据库做完后台存储解释。本…

痞子衡职场经验与感悟分享 - 索引

大家好&#xff0c;我是痞子衡&#xff0c;是正经搞技术的痞子。本系列痞子衡给大家分享的是职场经验与见闻感悟。 痞子衡在嵌入式行业也摸打滚爬了不少年&#xff0c;有一些个人经验可以给大家参考。所谓他山之石可以攻玉&#xff0c;希望痞子衡的经验对大家的职场之路有所帮…

jsp+ssm计算机毕业设计电影影评网【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

java基础的综合运用

文章目录前言一.类的设计书籍类书架类用户类二.行为的规范2.1 增加书籍2.2展示所有书籍2.3查找书籍2.4 删除书籍2.5 归还书籍2.6 借阅书籍2.7 退出系统三.测试类的方法四.项目的目录前言 在我们学习完面向对象的知识之后&#xff0c;我们就要运用相关知识去实现一个图书管理系…

十六进制转Ascii脚本(包含\x处理)

目录 1.前言 2.十六进制转换脚本(包含处理\x) 1.前言 在以前玩CTF的时候,会遇到十六进制编码,特别是带\x的那种,网上虽然也有在线解密网站,但是对于\x解码不是特别友好。 2.十六进制转换脚本(包含处理\x&#

【Flink实时数仓】数据仓库项目实战 《四》日志数据分流 【DWD】

文章目录【Flink实时数仓】数据仓库项目实战 《四》日志数据分流-流量域 【DWD】1.流量域未经加工的事务事实表1.1主要任务1.1.1数据清洗&#xff08;ETL&#xff09;1.1.2新老访客状态标记修复1.1.3新老访客状态标记修复1.2图解1.3代码1.4数据测试1.4.1 测试脏数据1.4.2 测试e…

论文写作神器,SCI 写作必备

一、论文写作建议与英文句型积累/引用 1. Academic Phrasebank 网址&#xff1a; https://www.phrasebank.manchester.ac.uk/ Academic Phrasebank&#xff1a;从引言工作到结论提出了论文写作的详细建议&#xff0c;并在每个小点给出了海量的英语表达以供参考。是 SCI 新手…