数据结构——实现通讯录(附源码)


乐观学习,乐观生活,才能不断前进啊!!!

我的主页:optimistic_chen
我的专栏:c语言
点击主页:optimistic_chen和专栏:c语言,
创作不易,大佬们点赞鼓励下吧~

前言

顺序表作为线性表的一种,他满足增删查改的基本操作,我们之前已经写过一篇 ,这篇博客我将基于顺序表的内容完成通讯录的实现,也是顺序表的一种应用方式之一。

文章目录

  • 前言
  • 实现准备
    • 实现通讯录的各种操作
  • 开始通讯录实现
    • 记录原始数据
    • 通讯录的初始化
    • 通讯录的销毁
    • 添加通讯录数据
    • 删除通讯录数据
    • 通讯录的查找
    • 通讯录的展示
    • 通讯录的修改
    • 通讯录页面
  • 完整代码
  • 完结

实现准备

· 经过之前的博客我们知道顺序表的底层就是数组,而通讯录就是顺序表通过封装过后的产物~
所以我们可以说通讯录的底层其实就是顺序表啦~

· 我们知道之前实现顺序表的时候,每个数组中存放的是内置类型int,但是通讯录内容数据类型可不只有int哦 ~* 而我们如果想要将各种联系人的数据存放并管理起来,那么我们就必须先自定义一个结构体类型来存放每个联系人的数据。然后将每个联系人的数据存放到数组中统计管理起来~

· 我们用宏定义来表示数组的大小方便以后的调整~

#pragma once
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100

//定义联系人的数据类型
typedef struct personInfo
{
	char name[NAME_MAX];//联系人姓名
	char gender[GENDER_MAX];//联系人性别
	int age;///联系人年龄
	char tel[TEL_MAX];//联系人电话
	char addr[ADDR_MAX];//联系人地址
}peoInfo;//对结构体的重命名

这样我们自定义了一个数据类型,实现了数组中每一个元素都是我们自定义的类型。

· 接下来就是基于顺序表来实现通讯录

顺序表的定义:

typedef struct SeqList
{
	SLDataType* arr;
	int size;
	int capacity;//空间大小
}SL;

//给顺序表改个名字,叫做通讯录
typedef struct SeqList Contact;

在这里插入图片描述

这里我只是给顺序表重新取了一个名字(contact)!
因为头文件之间不可以互相包含,所以我们不可以将SeqList.h中的SL进行重命名,只能通过前置声明。

实现通讯录的各种操作

通讯录和顺序表的基本操作相差不大,这里我把二者比较一下:

Contach.h

#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100
//自定义联系人的数据结构
typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}peoInfo;

//要用到顺序表相关的方法,对通讯录的操作实际就是对顺序表的操作

//给顺序表改个名字,叫做通讯录
typedef struct SeqList Contact;

//通讯录相关的方法
//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestTory(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

SeqList.h

#pragma once//避免头文件多次包含
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"//需要自定义的数据类型

typedef peoInfo SLDataType;//方便类型改动
//将本来peoInfo类型改为SLDataType类型

//动态顺序表
typedef struct SeqList
{
	SLDataType* arr;
	int size;
	int capacity;//空间大小
}SL;

//typedef struct SeqList SL;

//顺序表初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
  
void SLPrintf(SL s);
//头部插入 / 尾部插入
void SLPushBack(SL* ps, SLDataType x);
void SLPushPront(SL* ps, SLDataType x);

//头部删除 / 尾部删除
void SLPopBack(SL* ps);
void SLPopPront(SL* ps);

//在指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLFrase(SL* ps, int pos);

//查找数据
int SLFind(SL* ps, SLDataType x);

开始通讯录实现

记录原始数据

void DoadContact(Contact* con) 
{
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL) {
		perror("open fail\n");
		return;
	}
	peoInfo info= { 0 };
	while (fread(&info, sizeof(peoInfo), 1, pf))
	{
		SLPushBack(con, info);
	}
	printf("历史数据导入成功\n");
	fclose(pf);
	pf = NULL;
}

通讯录的初始化

void ContactInit(Contact* con)
{
	//实际上要进行的是顺序表的初始化
	//顺序表的初始化已经实现好了
	SLInit(con);
	DoadContact(con);
}

在通讯录初始化时,应用顺序表的初始化,然后再导入原数据~

通讯录的销毁

保存数据

//将输入的数据保存到通讯录中
void SaveContact(Contact* con)
{
	FILE* pf = fopen("Contact.txt", "wb");
	if (pf == NULL)
	{
		perror("open fail\n");
		return;
	}
	peoInfo info = { 0 };
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr + i, sizeof(peoInfo), 1, pf);
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}

销毁数据

//通讯录的销毁
void ContactDestTory(Contact* con)
{
    SaveContact(con);
	SLDestroy(con);
}

添加通讯录数据

//通讯录添加数据(尾插)
void ContactAdd(Contact* con)
{
	//输入内容
	peoInfo info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s",info.name);

	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);

	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);

	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);

	printf("请输入要添加的联系人住址:\n");
	scanf("%s", info.addr);

	//往通讯录(顺序表)中添加数据
	SLPushBack(con, info);//顺序表中已有方法的复用
}

删除通讯录数据

这里我们通过名字来删除通讯录的数据!(读者可尝试其他方式删除)

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0==strcmp(con->arr[i].name, name))
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}
void ContactDel(Contact* con)
{
	//要删除的数据必须存在
	//查找
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人的数据不存在\n");
		return;
	}
	//要删除的数据存在   要知道数据对应下标
	SLFrase(con, find);
	printf("删除成功\n");
}

通讯录的查找

//通讯录查找
void ContactFind(Contact* con)
{
	//查找姓名
	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人数据不存在\n");
		return;
	}
	//表头:姓名 性别 年龄 电话 地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%3s %4s %5d %4s %4s\n",
		con->arr[find].name,
		con->arr[find].gender,
		con->arr[find].age,
		con->arr[find].tel,
		con->arr[find].addr);
	
}

通讯录的展示

void ContactShow(Contact* con)
{
	//表头:姓名 性别 年龄 电话 地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %4s %5d %4s %4s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr);
	}
}

通讯录的修改

//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的数据存在
	char name[NAME_MAX];
	printf("请输入要修改的用户姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人数据不存在\n");
		return;
	}
	//存在直接修改
	printf("请输入新的姓名:\n");
	scanf("%s", con->arr[find].name);

	printf("请输入新的性别:\n");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的年龄:\n");
	scanf("%d", &con->arr[find].age);

	printf("请输入新的电话:\n");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的地址:\n");
	scanf("%s", con->arr[find].addr);
}

通讯录页面

void menu()
{
	printf("*******************通讯录*******************\n");
	printf("******1.增加联系人        2.删除联系人******\n");
	printf("******3.修改联系人        4.查找联系人******\n");
	printf("******5.展示联系人        0.    退出  ******\n");
	printf("********************************************\n");
}
int main()
{
	int op = -1;
	Contact con;
	ContactInit(&con);


	do {
		menu();
		printf("请选择你的操作:\n");
		scanf("%d", &op);

		//要根据对应op执行不同操作
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("退出通讯录\n");
			break;
		default:
			break;
		}
	} while (op != 0);

	return 0;
}

完整代码

Contact.h

#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100
//自定义联系人的数据结构
typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}peoInfo;

//要用到顺序表相关的方法,对通讯录的操作实际就是对顺序表的操作

//给顺序表改个名字,叫做通讯录
typedef struct SeqList Contact;

//通讯录相关的方法
//通讯录的初始化

void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestTory(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
#include"SeqList.h"
#include<string.h>

void DoadContact(Contact* con) 
{
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL) {
		perror("open fail\n");
		return;
	}
	peoInfo info= { 0 };
	while (fread(&info, sizeof(peoInfo), 1, pf))
	{
		SLPushBack(con, info);
	}
	printf("历史数据导入成功\n");
	fclose(pf);
	pf = NULL;
}

//通讯录的初始化
void ContactInit(Contact* con)
{
	//实际上要进行的是顺序表的初始化
	//顺序表的初始化已经实现好了
	SLInit(con);
	DoadContact(con);
}

void SaveContact(Contact* con)
{
	FILE* pf = fopen("Contact.txt", "wb");
	if (pf == NULL)
	{
		perror("open fail\n");
		return;
	}
	peoInfo info = { 0 };
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr + i, sizeof(peoInfo), 1, pf);
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}
//通讯录的销毁
void ContactDestTory(Contact* con)
{
	SaveContact(con);
	SLDestroy(con);
}

//通讯录添加数据(尾插)
void ContactAdd(Contact* con)
{
	//输入内容
	peoInfo info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s",info.name);

	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);

	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);

	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);

	printf("请输入要添加的联系人住址:\n");
	scanf("%s", info.addr);

	//往通讯录(顺序表)中添加数据
	SLPushBack(con, info);//顺序表中已有方法的复用
}

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0==strcmp(con->arr[i].name, name))
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}
//通讯录删除数据
void ContactDel(Contact* con)
{
	//要删除的数据必须存在
	//查找
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人的数据不存在\n");
		return;
	}
	//要删除的数据存在   要知道数据对应下标
	SLFrase(con, find);
	printf("删除成功\n");
}

//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头:姓名 性别 年龄 电话 地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %4s %5d %4s %4s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr);
	}
}

//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的数据存在
	char name[NAME_MAX];
	printf("请输入要修改的用户姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人数据不存在\n");
		return;
	}
	//存在直接修改
	printf("请输入新的姓名:\n");
	scanf("%s", con->arr[find].name);

	printf("请输入新的性别:\n");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的年龄:\n");
	scanf("%d", &con->arr[find].age);

	printf("请输入新的电话:\n");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的地址:\n");
	scanf("%s", con->arr[find].addr);
}

//通讯录查找
void ContactFind(Contact* con)
{
	//查找姓名
	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人数据不存在\n");
		return;
	}
	//表头:姓名 性别 年龄 电话 地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%3s %4s %5d %4s %4s\n",
		con->arr[find].name,
		con->arr[find].gender,
		con->arr[find].age,
		con->arr[find].tel,
		con->arr[find].addr);
	
}

SeqList.h

#pragma once//避免头文件多次包含
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"//需要自定义的数据类型

typedef peoInfo SLDataType;//方便类型改动
//将本来peoInfo类型改为SLDataType类型

//动态顺序表
typedef struct SeqList
{
	SLDataType* arr;
	int size;
	int capacity;//空间大小
}SL;

//typedef struct SeqList SL;

//顺序表初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
  
void SLPrintf(SL s);
//头部插入 / 尾部插入
void SLPushBack(SL* ps, SLDataType x);
void SLPushPront(SL* ps, SLDataType x);

//头部删除 / 尾部删除
void SLPopBack(SL* ps);
void SLPopPront(SL* ps);

//在指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLFrase(SL* ps, int pos);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void SLInit(SL* ps)//初始化
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

void SLDestroy(SL* ps)//销毁
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

void SLPushBack(SL* ps, SLDataType x)//顺序表的尾插
{
	assert(ps);
	//插入数据之前先判断空间够不够
	if (ps->capacity == ps->size)
	{
		//申请空间(多大?一般2倍增容)
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType*tmp = (SLDataType*)realloc(ps->arr,newCapacity * 2 * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		//申请空间成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	//ps->arr[ps->size] = x;
	//++ps->size;
	ps->arr[ps->size++] = x;
}

void SLCheckCapacity(SL* ps)//申请空间单独成一个函数
{
	if (ps->capacity == ps->size)
	{
		//申请空间(多大?一般2倍增容)
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * 2 * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		//申请空间成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}

void SLPushPront(SL* ps, SLDataType x)//头插
{
	assert(ps);
	void SLCheckCapacity(SL * ps);
	//先让顺序表的数据统一往后移动
	for (int i = ps->size; i > 0 ; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[1]=arr[0]
	}
	ps->arr[0] = x;
	ps->size++;
}

void SLPrintf(SL s)//打印
{
	for (int i = 0; i < s.size; i++)
	{
		printf("%d ", s.arr[i]);
	}
	printf("\n");
}

void SLPopBack(SL* ps)//尾删
{
	assert(ps);
	assert(ps -> size);//顺序表不为空
	//ps->arr[ps->size - 1] = -1;
	--ps->size;//直接减去空间
}

void SLPopPront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	
	//数据整体往前一位
	for (int i = 0; i < ps->size-1;i++)
	{
		ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1]
	}
	ps->size--;
}

//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x) 
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	//插入数据:空间够不够
	void SLCeckCapacityCapacity(ps);
	//让pos之后的数据整体往后移动一位
	for (int i = ps->size; i>pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[pos+1]=arr[pos]
	}
	ps->arr[pos] = x;
	ps->size++;
}

//在指定位置之前删除数据
void SLFrase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size );
	for (int i = pos; i < ps->size-1; i++)
	{
		ps->arr[i] = ps -> arr[i + 1];
	}
	ps->size--;
}

完结

好了,这期的分享到这里就结束了~
如果这篇博客对你有帮助的话,可以点一个免费的赞并收藏起来哟~
可以点点关注,避免找不到我~
我们下期不见不散~~

​​

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python中cv2 (OpenCV, opencv-python)库的安装、使用方法demo最新详细教程

&#x1f42f; Python中cv2 (OpenCV, opencv-python)库的安装、使用方法demo最新详细教程 &#x1f4f8; 文章目录 &#x1f42f; Python中cv2 (OpenCV, opencv-python)库的安装、使用方法demo最新详细教程 &#x1f4f8;摘要引言正文&#x1f4d8; OpenCV库概述&#x1f680; …

手动下载huggingface数据集到本地加载

需要使用huggingface上的数据集时一般如下加载&#xff1a; import datasets dataset datasets.load_dataset("dataset_name")但是经常会报连接错误等问题&#xff0c;所以我们可以去huggingface官网下载好数据集&#xff0c;然后直接用数据集路径替换dataset_name…

Springboot+Vue项目-基于Java+MySQL的流浪动物管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

快速话术本(常用文本快速复制工具)EXE成品+软件源码

功能介绍 经常性需要重复性的输入几个不同的文本&#xff0c;来回复制很麻烦&#xff0c;这个小工具可以帮你解决&#xff0c;把要经常输入的文本添加进去&#xff0c;点击即可复制~ 链接&#xff1a;https://pan.baidu.com/s/14-U_9uzkvpCrpzBkQaDZeA?pwdu7ot 提取码&#…

IT项目管理 选择/判断 【太原理工大学】

第一章、IT项目管理 判断题 1、搬家属于项目。&#xff08; 对 &#xff09; 2、项目是为了创造一个唯一的产品或提供一个唯一的服务而进行的永久性的努力。&#xff08; 错 &#xff09; 3、项目具有临时性的特征。&#xff08; 对 &#xff09; 4、项目开发过程…

用户下单操作

一&#xff1a;用户下单需求分析和设计&#xff1a; 用户下单业务说明&#xff1a; 在电商系统中&#xff0c;用户是通过下单的方式通知商家&#xff0c;用户已经购买了商品&#xff0c;需要商家进行备货和发货。 用户下单后会产生订单相关数据&#xff0c;订单数据需要能够体…

情感分类学习笔记(1)

文本情感分类&#xff08;二&#xff09;&#xff1a;深度学习模型 - 科学空间|Scientific Spaces 一、代码理解 cw lambda x: list(jieba.cut(x)) #定义分词函数 您给出的代码定义了一个使用 jieba 分词库的分词函数。jieba 是一个用于中文分词的 Python 库。该函数 cw 是…

docker部署小试

一 1.1 需求&#xff1a;根据docker部署nginx并且实现https 1.2 前期准备 准备一台装备好的docker-ce虚拟机&#xff0c;容量至少满足4G/2C&#xff0c;同时做好关闭防火墙的操作 systemctl stop firewalld setenforce 0 1.3 实验部署 1.3.1 创建并进入文件夹 1.3.2 编辑run脚本…

如何设计一个自动化测试平台

之前写过很多自动化测试相关的文章&#xff0c;后台有同学留言&#xff1a;希望写一篇自动化测试平台的文章。他的原话是这样&#xff1a;目前市场上开源或者商业的自动化测试平台很多&#xff0c;但试用下来总感觉有些地方不太融洽&#xff0c;想自己落地一个适合自己团队和项…

紧跟生成式AI暴雨发布新时代推理服务器

近日&#xff0c;暴雨发布最新训推一体AI服务器&#xff0c;以大容量内存和灵活的高速互连选项满足各种AI应用场景&#xff0c;最大可能支持扩展插槽&#xff0c;从而大幅提升智能算力性能&#xff0c;以最优的性能和成本为企业的模型训练推理落地应用提供更好的通用算力。 AIG…

物联网实战--平台篇之(三)账户后台数据库

目录 一、账户后台设计 二、账户数据库 三、数据库操作——增 四、数据库操作——改 五、数据库操作——查 本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240…

Netty的第一个简单Demo实现

说明 Netty 的一个练习&#xff0c;使用 Netty 连通 服务端 和 客户端&#xff0c;进行基本的通信。 需求 Client 连接服务端后&#xff0c;给服务端发送消息HelloServer Server 客户端连接成功后&#xff0c;打印连接成功读取到客户端的消息后&#xff0c;打印到控制台&…

企业是保留传统的MES还是换新的MES?

在选择上MES系统的时候&#xff0c;企业可以根据自身所处行业不同、当前阶段不同&#xff0c;以及业务需求的差异&#xff0c;对症下药&#xff0c;选择适合自己的解决方案。对于有些企业本来就有MES系统&#xff0c;但是已经过时过旧&#xff0c;就要考虑换新的MES系统了. 保留…

高精度数学计算的瑞士军刀,mpmath库详解与应用示例

写在前言 hello&#xff0c;大家好&#xff0c;我是一点&#xff0c;专注于Python编程&#xff0c;如果你也对感Python感兴趣&#xff0c;欢迎关注交流。 做为一个一只脚已经踏进35岁大关的程序员&#xff0c;对于职场&#xff0c;几乎向上无望&#xff0c;已经没有太多的期待…

DJANGO_PART 1

DJANGO_PART 1 文章目录 DJANGO_PART 11. 安装DJANGO2. 创建项目3. APP概念4. 快速上手5. templates6. 引入其它静态文件7. 模板语法8. 请求与响应 1. 安装DJANGO 安装语句&#xff1a;pip install django 2. 创建项目 django中项目会有一些默认的文件和默认的文件夹 终端创建…

渗透之sql注入实战2(二次注入)

目录 平台地址&#xff1a; 开始&#xff1a; 方法1&#xff1a; 方法二 找提示 这里存在一个文件包含&#xff08;file&#xff09;。 爆源码 index.php源码 confirm.php源码&#xff1a; search.php源码&#xff1a; change.php源码&#xff1a; delete.php源码&…

Linux---HTTP协议

HTTP HTTP协议&#xff08;Hypertext Transfer Protocol&#xff0c;超文本传输协议&#xff09;是一种应用层协议&#xff0c;主要用于在Web浏览器和Web服务器之间传输数据。 一、认识URL 平时我们俗称的 " 网址 " 其实就是说的 URL http请求样例 看起来是一行一…

英语学习笔记7——Are you a teacher?

Are you a teacher? 你是教师吗&#xff1f; 词汇 Vocabulary name /neɪm/ n. 名字&#xff0c;名声 英文名字构成&#xff1a; 名 字 姓      given name family name  也叫做&#xff1a;first name last name      例&#xff1a;Yanyan Gao 例句&#xff1…

Baidu Comate智能编码助手-程序员的神助攻

&#x1f389;Baidu Comate:程序员编程最牛的辅助利器&#xff0c;没有之一 &#x1f388;AI编程助力开发者提质增效 智能代码补全&#xff1a;AI编程助手可以根据上下文和用户的编码习惯&#xff0c;智能地提供代码补全和建议&#xff0c;帮助程序员更快速地编写代码&#xf…

Service 和 Ingress

文章目录 Service 和 IngressServiceEndpointservice 的定义代理集群外部服务反向代理外部域名Service 常用类型 IngressIngress-nginx安装使用 Service 和 Ingress service 和 ingress 是kubernetes 中用来转发网络请求的两个服务&#xff0c;两个服务用处不同&#xff0c;se…
最新文章