基于顺序表实现通讯管理系统!(有完整源码!)

​​​​​​​

                                                                                个人主页:秋风起,再归来~

                                                                                文章专栏:C语言实战项目                              

                                                                        个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!​​​​​​​

目录

1、实现思路

​编辑

2、各种接口的实现

2.1 初始化通讯录

2.2 添加通讯录数据

2.3 删除通讯录数据

2.4 展示通讯录数据

2.5 查找通讯录数据

2.6 修改通讯录数据

2.7 销毁通讯录数据

2.8 制作一个简易的菜单 

3、完整源码

SeqList.h

Contact.h

SeqList.c

Contact.c

test.c

4、 完结散花


1、实现思路

前言:在我之前的文章当中已经写过一篇关于如何实现顺序表的文章(点击这里),而这篇文章主要是讲解如何基于顺序表实现通讯管理系统,所以要看明白这篇文章的宝子们一定要先看完写的顺序表的文章哦~

1.1 首先我们知道顺序表的底层就是数组,而通讯录就是顺序表通过封装过后的产物~

所以我们可以说通讯录的底层其实就是顺序表啦~

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

我们用宏定义来表示数组的大小方便以后的调整~(这些代码都是写在contact.h头文件当中)

#define NAME_MAX 20
#define GENDER_MAX 20
#define TELE_MAX 20
#define ADDR_MAX 200
//定义一个自定义类型来存放我们所要的联系人信息
typedef struct PersonInformation
{
	char name[NAME_MAX];//名字
	char gender[GENDER_MAX];//性别
	int age;//年龄
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//住址
}PeoInfo;

 ​​

1.3 我们知道顺序表是这样定义的~

//定义一个动态顺序表的结构体变量
typedef struct SeqList
{
	SLDataType* arr;
	size_t num;//记录有效数据的个数
	size_t capacity;//该顺序表的容量大小
}SL;//将该结构体类型重命名为SL

我们在顺序表的头文件当中引入Contact.h头文件(因为我们要将顺序表中的每个元素改成我们自定义是类型)

​​

1.4 接下来我们就让顺序表摇身一变成为通讯录!

//前置申明
typedef struct SeqList contact;

 这里我只是给顺序表重新取了一个名字(contact)!

因为头文件之间不可以互相包含,所以我们不可以将SeqList.h中的SL进行重命名,只能通过前置声明。

到这里我们就可以对通讯录进行各种接口的实现了!

Contact.h

#define _CRT_SECURE_NO_WARNINGS

#pragma once
#define NAME_MAX 20
#define GENDER_MAX 20
#define TELE_MAX 20
#define ADDR_MAX 200

//定义一个自定义类型来存放我们所要的联系人信息
typedef struct PersonInformation
{
	char name[NAME_MAX];//名字
	char gender[GENDER_MAX];//性别
	int age;//年龄
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//住址
}PeoInfo;

//前置申明
typedef struct SeqList contact;

//初始化通讯录
void InitContact(contact* con);

//添加通讯录数据
void AddContact(contact* con);

//删除通讯录数据
void DelContact(contact* con);

//展示通讯录数据
void ShowContact(contact* con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact* con);

//销毁通讯录数据
void DestroyContact(contact* con);

SeqList.h

#define _CRT_SECURE_NO_WARNINGS

#pragma once//避免头文件的多次包含
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"//需要自定义的类型,所以引入contact头文件
typedef PeoInfo SLDataType;//便于类型的改动

//定义一个动态顺序表的结构体变量
typedef struct SeqList
{
	SLDataType* arr;
	size_t num;//记录有效数据的个数
	size_t capacity;//该顺序表的容量大小
}SL;//将该结构体类型重命名为SL

//加入增删查改接口

//1. 顺序表初始化
void SeqListInit(SL* p);

//2. 检查顺序表容量是否已满
void CheckSeqList(SL* p);

//3. 顺序表的尾插
void SeqListPushBack(SL* p, SLDataType x);

//4. 顺序表的尾删
void SeqListPopBack(SL* p);

//5. 顺序表的头插
void SeqListPushFront(SL* p, SLDataType x);

//6. 顺序表的头删
void SeqListPopFront(SL* p);

//7. 顺序表在pos位置插入
void SeqListInsert(SL* p, size_t pos, SLDataType x);

//8. 顺序表在pos位置删除
void SeqListErase(SL* p, size_t pos);

//9. 顺序表的查找
int SeqListFind(SL* p, SLDataType x);//如果该数字存在则返回该数字的下标,否则返回-1

//10 顺序表的销毁
void SeqListDestory(SL* p);

//11. 顺序表的打印
void SeqListPrint(SL* p);

2、各种接口的实现

2.1 初始化通讯录

因为我们希望在初始化通讯录时可以将我们之前保存的数据加载到通讯中,所以我们可以通过文件操作将数据加载到通讯录当中~

//导入原文件中的数据
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))
	{
		SeqListPushBack(con, info);
	}
	printf("历史数据导入成功!\n");
	fclose(pf);
	pf = NULL;
}

在初始化时,我们就可以调用顺序表中的初始化接口来实现通讯录的初始化 ,然后再导入原数据~

//初始化通讯录
void InitContact(contact* con)
{
	SeqListInit(con);
	DoadContact(con);
}

2.2 添加通讯录数据

添加数据,我们就是在尾插的基础上对顺序表进行封装(头插也可以)!

//添加通讯录数据
void AddContact(contact* con)
{
	PeoInfo p;
	printf("请输入您要添加的联系人的姓名!\n");
	scanf("%s", p.name);
	printf("请输入您要添加的联系人的性别!\n");
	scanf("%s", p.gender); 
	printf("请输入您要添加的联系人的年龄!\n");
	scanf("%d", &(p.age));
	printf("请输入您要添加的联系人的电话!\n");
	scanf("%s", p.tele);
	printf("请输入您要添加的联系人的住址!\n");
	scanf("%s", p.addr);
	SeqListPushBack(con, p);
	printf("插入成功\n");
}

2.3 删除通讯录数据

这里我们通过名字来删除通讯录的数据!(当然我们也可以通过其他方式来删除数据)

//通过名字来查找通讯录中是否存在该联系人数据
int  FindByName(contact* con,char* name)
{
	for (int i = 0; i < con->num; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			return i;//如果找到就返回他的下标
		}
	}
	return -1;//如果没找到返回一个无效的下标
}
//删除通讯录数据
void DelContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入您要删除的联系人的名字!\n");
	scanf("%s", name);
	int pos=FindByName(con, name);
	if (pos < 0)
	{
		printf("您要删除的联系人不存在!\n");
		return;
	}
	//调用顺序表中的在指定位置删除数据的函数
	SeqListErase(con, pos);
	printf("删除成功!\n");
}

2.4 展示通讯录数据

//展示通讯录数据
void ShowContact(contact* con)
{
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t\t住址\n");
	for (int i = 0; i < con->num; i++)
	{
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tele,
			con->arr[i].addr
		);
	}
}

2.5 查找通讯录数据

//查找通讯录数据
void FindContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入您要查找的联系人的名字!\n");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("您要查找的联系人不存在!\n");
		return;
	}
	printf("名字\t性别\t年龄\t电话\t住址\n");
	printf("%s\t%s\t%d\t%s\t%s\t\n",
		con->arr[pos].name,
		con->arr[pos].gender,
		con->arr[pos].age,
		con->arr[pos].tele,
		con->arr[pos].addr
	);
}

2.6 修改通讯录数据

//修改通讯录数据
void ModifyContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入您要修改的联系人的名字!\n");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("您要修改的联系人不存在!\n");
		return;
	}
	printf("请输入新的名字\n");
	scanf("%s", con->arr[pos].name);
	printf("请输入新的性别\n");
	scanf("%s", con->arr[pos].gender);
	printf("请输入新的年龄\n");
	scanf("%d", &con->arr[pos].age);
	printf("请输入新的电话\n");
	scanf("%s", con->arr[pos].tele);
	printf("请输入新的住址\n");
	scanf("%s", con->arr[pos].addr);
	printf("修改成功!\n");
}

2.7 销毁通讯录数据

在退出通讯录时我们希望将我们对通讯录进行的操作保存下来!

//将输入的数据保存到通讯录中
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->num; i++)
	{
		fwrite(con->arr + i, sizeof(PeoInfo), 1, pf);
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}
//先保存数据到文件中再销毁通讯录数据
void DestroyContact(contact* con)
{
	SaveContact(con);
	//调用顺序表的销毁函数即可
	SeqListDestory(con);
}

2.8 制作一个简易的菜单 

#define _CRT_SECURE_NO_WARNINGS

#include"SeqList.h"
#include"contact.h"

void menu()
{
	printf("**********************************\n");
	printf("*****1、增加用户 2、删除用户  ****\n");
	printf("*****3、查找用户 4、修改用户  ****\n");
	printf("*****5、展示用户 0、退出通讯录****\n");
	printf("**********************************\n");
}


int main()
{
	contact con = { 0 };
	InitContact(&con);
	int input = 0;
	do
	{
		menu();
		printf("请输入您的选择!\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			FindContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 0:
			printf("退出通讯录成功!\n");
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while(input);
	DestroyContact(&con);
	return 0;
}

3、完整源码

SeqList.h

#define _CRT_SECURE_NO_WARNINGS

#pragma once//避免头文件的多次包含
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"//需要自定义的类型,所以引入contact头文件
typedef PeoInfo SLDataType;//便于类型的改动

//定义一个动态顺序表的结构体变量
typedef struct SeqList
{
	SLDataType* arr;
	size_t num;//记录有效数据的个数
	size_t capacity;//该顺序表的容量大小
}SL;//将该结构体类型重命名为SL

//加入增删查改接口

//1. 顺序表初始化
void SeqListInit(SL* p);

//2. 检查顺序表容量是否已满
void CheckSeqList(SL* p);

//3. 顺序表的尾插
void SeqListPushBack(SL* p, SLDataType x);

//4. 顺序表的尾删
void SeqListPopBack(SL* p);

//5. 顺序表的头插
void SeqListPushFront(SL* p, SLDataType x);

//6. 顺序表的头删
void SeqListPopFront(SL* p);

//7. 顺序表在pos位置插入
void SeqListInsert(SL* p, size_t pos, SLDataType x);

//8. 顺序表在pos位置删除
void SeqListErase(SL* p, size_t pos);

//9. 顺序表的查找
int SeqListFind(SL* p, SLDataType x);//如果该数字存在则返回该数字的下标,否则返回-1

//10 顺序表的销毁
void SeqListDestory(SL* p);

//11. 顺序表的打印
void SeqListPrint(SL* p);

Contact.h

#define _CRT_SECURE_NO_WARNINGS

#pragma once
#define NAME_MAX 20
#define GENDER_MAX 20
#define TELE_MAX 20
#define ADDR_MAX 200

//定义一个自定义类型来存放我们所要的联系人信息
typedef struct PersonInformation
{
	char name[NAME_MAX];//名字
	char gender[GENDER_MAX];//性别
	int age;//年龄
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//住址
}PeoInfo;

//前置申明
typedef struct SeqList contact;

//初始化通讯录
void InitContact(contact* con);

//添加通讯录数据
void AddContact(contact* con);

//删除通讯录数据
void DelContact(contact* con);

//展示通讯录数据
void ShowContact(contact* con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact* con);

//销毁通讯录数据
void DestroyContact(contact* con);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
//1. 顺序表初始化
void SeqListInit(SL* p)
{
	assert(p);//判断指针的有效性
	p->arr = NULL;
	p->capacity = 0;
	p->num = 0;
}

//2. 检查顺序表容量是否已满
void CheckSeqList(SL* p)
{
	assert(p);//判断指针的有效性
	if (p->num == p->capacity)
	{
		size_t newcapacity = p->capacity == 0 ? p->capacity = 4 : p->capacity * 2;
		//如果原来没有空间,就给上4,有的话就扩大为原来的两倍
		SLDataType* ptr = (SLDataType*)realloc(p->arr, newcapacity * sizeof(SLDataType));//动态扩容
		if (ptr == NULL)
		{
			perror("realloc fail;");
			return;
		}
		//也可以用assert断言一下
		p->arr = ptr;//开辟成功将地址传给arr
		p->capacity = newcapacity;//更新容量
	}
}

//3. 顺序表的尾插
void SeqListPushBack(SL* p, SLDataType x)
{
	assert(p);//判断指针的有效性
	CheckSeqList(p);//尾插前先判断有没有容量或容量够不够
	p->arr[p->num] = x;//尾部插入数据
	p->num++;//有效数加一
}

//4. 顺序表的尾删
void SeqListPopBack(SL* p)
{
	assert(p);//判断指针的有效性
	assert(p->num > 0);//断言存在有效数据
	p->num--;//尾删一个数据
}

//5. 顺序表的头插
void SeqListPushFront(SL* p, SLDataType x)
{
	assert(p);//判断指针的有效性
	CheckSeqList(p);//先判断容量是否满了
	size_t end = p->num;
	while (end)
	{
		p->arr[end] = p->arr[end - 1];//整体向后移动
		end--;
	}
	p->arr[0] = x;//头插
	p->num++;//有效数据加一
}

//6. 顺序表的头删
void SeqListPopFront(SL* p)
{
	assert(p);//判断指针的有效性
	assert(p->num > 0);//有数据才删除
	size_t begin = 1;
	while (begin < p->num)
	{
		p->arr[begin - 1] = p->arr[begin];//整体向前移动
		begin++;
	}
	p->num--;// 有效数据减一

}

//7. 顺序表在pos位置插入
void SeqListInsert(SL* p, size_t pos, SLDataType x)
{
	assert(p);//判断指针的有效性
	assert(pos >= 0 && pos < p->num);//pos必须小于num并且大于等于0
	CheckSeqList(p);//判断容量是否满了
	for (int i = p->num; i > pos - 1; i--)
	{
		p->arr[i] = p->arr[i - 1];//将pos后面的元素往后挪
	}
	p->arr[pos - 1] = x;//在pos位置加入数据
	p->num++;//有效个数加一
}

//8. 顺序表在pos位置删除
void SeqListErase(SL* p, size_t pos)
{
	assert(p);//判断指针的有效性
	assert(pos >= 0 && pos < p->num);//pos必须小于num并且大于等于0
	assert(p->num > 0);//有数据才能删除
	for (int i = pos; i < p->num-1; i++)
	{
		p->arr[i] = p->arr[i+1];//将pos后面的元素往后挪
	}
	p->num--;//有效个数减一
}

//9. 顺序表的查找
int SeqListFind(SL* p, SLDataType x)//如果该数字存在则返回该数字的下标,否则返回-1
{
	assert(p);//断言
	for (int i = 0; i < p->num; i++)
	{
		if (p->arr[i] == x)
		{
			return i;//查到返回下标
		}
	}
	return -1;//没有查到
}


//10 顺序表的销毁
void SeqListDestory(SL* p)
{
	assert(p);//判断指针的有效性
	free(p->arr);//释放动态内存开辟的空间
	p->arr = NULL;
	p->capacity = 0;//容量置为0
	p->num = 0;//有效个数置为0
}

//11. 顺序表的打印
void SeqListPrint(SL* p)
{
	assert(p);//判断指针的有效性
	if (p->num == 0)
	{
		printf("顺序表为空!\n");
		return;
	}
	for (int i = 0; i < p->num; i++)
	{
		printf("%d ", p->arr[i]);//打印数据
	}
	printf("\n");
}

Contact.c

#define _CRT_SECURE_NO_WARNINGS

#include"SeqList.h"
#include"Contact.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))
	{
		SeqListPushBack(con, info);
	}
	printf("历史数据导入成功!\n");
	fclose(pf);
	pf = NULL;
}


//初始化通讯录
void InitContact(contact* con)
{
	SeqListInit(con);
	DoadContact(con);
}

//添加通讯录数据
void AddContact(contact* con)
{
	PeoInfo p;
	printf("请输入您要添加的联系人的姓名!\n");
	scanf("%s", p.name);
	printf("请输入您要添加的联系人的性别!\n");
	scanf("%s", p.gender); 
	printf("请输入您要添加的联系人的年龄!\n");
	scanf("%d", &(p.age));
	printf("请输入您要添加的联系人的电话!\n");
	scanf("%s", p.tele);
	printf("请输入您要添加的联系人的住址!\n");
	scanf("%s", p.addr);
	SeqListPushBack(con, p);
	printf("插入成功\n");
}

//通过名字来查找通讯录中是否存在该联系人数据
int  FindByName(contact* con,char* name)
{
	for (int i = 0; i < con->num; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			return i;//如果找到就返回他的下标
		}
	}
	return -1;//如果没找到返回一个无效的下标
}

//删除通讯录数据
void DelContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入您要删除的联系人的名字!\n");
	scanf("%s", name);
	int pos=FindByName(con, name);
	if (pos < 0)
	{
		printf("您要删除的联系人不存在!\n");
		return;
	}
	//调用顺序表中的在指定位置删除数据的函数
	SeqListErase(con, pos);
	printf("删除成功!\n");
}

//展示通讯录数据
void ShowContact(contact* con)
{
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t\t住址\n");
	for (int i = 0; i < con->num; i++)
	{
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tele,
			con->arr[i].addr
		);
	}
}


//查找通讯录数据
void FindContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入您要查找的联系人的名字!\n");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("您要查找的联系人不存在!\n");
		return;
	}
	printf("名字\t性别\t年龄\t电话\t住址\n");
	printf("%s\t%s\t%d\t%s\t%s\t\n",
		con->arr[pos].name,
		con->arr[pos].gender,
		con->arr[pos].age,
		con->arr[pos].tele,
		con->arr[pos].addr
	);
}

//修改通讯录数据
void ModifyContact(contact* con)
{
	char name[NAME_MAX];
	printf("请输入您要修改的联系人的名字!\n");
	scanf("%s", name);
	int pos = FindByName(con, name);
	if (pos < 0)
	{
		printf("您要修改的联系人不存在!\n");
		return;
	}
	printf("请输入新的名字\n");
	scanf("%s", con->arr[pos].name);
	printf("请输入新的性别\n");
	scanf("%s", con->arr[pos].gender);
	printf("请输入新的年龄\n");
	scanf("%d", &con->arr[pos].age);
	printf("请输入新的电话\n");
	scanf("%s", con->arr[pos].tele);
	printf("请输入新的住址\n");
	scanf("%s", con->arr[pos].addr);
	printf("修改成功!\n");
}

//将输入的数据保存到通讯录中
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->num; i++)
	{
		fwrite(con->arr + i, sizeof(PeoInfo), 1, pf);
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}

//先保存数据到文件中再销毁通讯录数据
void DestroyContact(contact* con)
{
	SaveContact(con);
	//调用顺序表的销毁函数即可
	SeqListDestory(con);
}

test.c

#define _CRT_SECURE_NO_WARNINGS

#include"SeqList.h"
#include"contact.h"

void menu()
{
	printf("**********************************\n");
	printf("*****1、增加用户 2、删除用户  ****\n");
	printf("*****3、查找用户 4、修改用户  ****\n");
	printf("*****5、展示用户 0、退出通讯录****\n");
	printf("**********************************\n");
}


int main()
{
	contact con = { 0 };
	InitContact(&con);
	int input = 0;
	do
	{
		menu();
		printf("请输入您的选择!\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			FindContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 0:
			printf("退出通讯录成功!\n");
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while(input);
	DestroyContact(&con);
	return 0;
}

4、 完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

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

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

相关文章

C语言中strlen函数的实现

C语言中strlen函数的实现 为了便于和strlen函数区别&#xff0c;以下命令为_strlen。 描述&#xff1a;实现strlen&#xff0c;获取字符串的长度&#xff0c;函数原型如下&#xff1a; size_t strlen(const char *str);_strlen实现&#xff1a; size_t _strlen(const char*…

彩虹聚合DNS管理系统,附带系统搭建教程

聚合DNS管理系统&#xff0c;可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。 本系统支持多用户&#xff0c;每个用户可分配不同的域名解析权限&#xff1b;支持API接口&#xff0…

武汉星起航:跨境电商领域的领航者,助力全球贸易新篇章

自2017年以来&#xff0c;武汉星起航一直专注于亚马逊自营店铺&#xff0c;积累了宝贵的经验。2020年正式成立后&#xff0c;公司以跨境电商为核心&#xff0c;致力于为合作伙伴提供深入的合作模式。武汉星起航凭借其卓越的服务和实战经验&#xff0c;已成功助力众多创业者实现…

基于SpringBoot的“智慧外贸平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“智慧外贸平台”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 平台首页界面图 商品信息界面图 …

Java8 进阶

Java8 进阶 文章目录 Java8 进阶什么是函数式接口&#xff1f;public interface Supplierpublic interface Consumerpublic interface Predicatepublic interface FunctionJava8 特性总结&#xff1a;一、Function<T, R>二、Consumer<T>三、Supplier<T>四、P…

位运算-191. 位1的个数- 136. 只出现一次的数字

位1的个数 已解答 简单 相关标签 相关企业 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中 设置位 的个数&#xff08;也被称为汉明重量&#xff09;。 示例 1&#xff1a; 输入&#xff1a;n 11 输…

Linux第4课 Linux的基本操作

文章目录 Linux第4课 Linux的基本操作一、图形界面介绍二、终端界面介绍 Linux第4课 Linux的基本操作 一、图形界面介绍 本节以Ubuntu系统的GUI为例进行说明&#xff0c;Linux其他版本可自行网搜。 图形系统进入后&#xff0c;左侧黄框内为菜单栏&#xff0c;右侧为桌面&…

c# 指数搜索(Exponential Search)

该搜索算法的名称可能会产生误导&#xff0c;因为它的工作时间为 O(Log n)。该名称来自于它搜索元素的方式。 给定一个已排序的数组和要 搜索的元素 x&#xff0c;找到 x 在数组中的位置。 输入&#xff1a;arr[] {10, 20, 40, 45, 55} x 45 输出&#xff1a;在索…

检验平台最基本的技术要求有哪几条

检验平台最基本的技术要求通常有以下几条&#xff1a; 系统稳定性&#xff1a;检验平台应具备良好的稳定性&#xff0c;能够长时间运行而不出现系统崩溃或异常情况。 数据安全性&#xff1a;检验平台应具备对数据进行安全存储和传输的能力&#xff0c;确保数据不被非法获取、篡…

吴恩达机器学习笔记:第 6 周-11机器学习系统的设计(Machine Learning System Design)11.1-11.5

目录 第 6 周 11、 机器学习系统的设计(Machine Learning System Design)11.1 首先要做什么11.2 误差分析11.3 类偏斜的误差度量11.4 查准率和查全率之间的权衡11.5 机器学习的数据 第 6 周 11、 机器学习系统的设计(Machine Learning System Design) 11.1 首先要做什么 在接…

基于Python的豆瓣电影评分可视化,豆瓣电影评分预测系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

2024年阿里云4月服务器有哪些优惠活动?

2024年阿里云服务器4月优惠活动有哪些&#xff1f;4月份最新优惠活动有99计划云服务器99元一年、学生服务器、游戏服务器优惠、云服务器精选特惠、高校计划优惠券300元、阿里云服务器免费试用等活动。4月云服务器最新优惠价格2核2G3M带宽99元一年、2核4G5M带宽199元一年&#x…

AcWing 312. 乌龟棋(每日一题)

原题链接&#xff1a;312. 乌龟棋 - AcWing题库 小明过生日的时候&#xff0c;爸爸送给他一副乌龟棋当作礼物。 乌龟棋的棋盘只有一行&#xff0c;该行有 N 个格子&#xff0c;每个格子上一个分数&#xff08;非负整数&#xff09;。 棋盘第 1 格是唯一的起点&#xff0c;第…

vue + koa + Sequelize + 阿里云部署 + 宝塔:宝塔数据库连接

之前文章已经介绍了宝塔上传前后端代码并部署&#xff0c;不清楚的请看这篇文章&#xff1a; vue koa 阿里云部署 宝塔&#xff1a;宝塔前后端部署 下面是宝塔创建数据库&#xff1a; 我用的 koa Sequelize 连接的数据库&#xff0c;Sequelize 非常适合前端使用&#xf…

Map源码解析

基本介绍 其实HashMap底层是个什么东西我们之前也讲过, 就是一个哈希桶(差不多可以看成一个数组), 然后每一个节点又连接着链表/红黑树之类的, 下面让我们看一看具体在源码上是怎样实现的: 常量及其它 -> static final int DEFAULT_INITIAL_CAPACITY 1 << 4; //这个…

springboot 在fegin调用中sdk集成主工程,A component required a bean of type.....

一 前景描述 1.1 总结 1.主工程启动类&#xff08;这里是FeginApp8081&#xff09;所在的路径&#xff0c;和调用sdk的类&#xff0c;这里是FeginJiekou接口类型&#xff0c;其所在目录和主工程目录启动一致。则不需要在启动加制定扫描注解。 主工程启动类路径&#xff1a;…

《C++程序设计》阅读笔记【4-指针(2)】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;《C程序设计》阅读笔记 本文对应的PDF源文件请关注微信公众号程序员刘同学&#xff0c;回复C程序设计获取下载链接。 1 指针1.1 字符指针1.1.1 字符串的表示1.1.2 字符串的属性1.1.3 字符…

单片机之蜂鸣器

目录 蜂鸣器介绍 蜂鸣器的分类 发声原理分类 按有源无源分类 三极管驱动 蜂鸣器原理 音符与频率对照表 蜂鸣器播放130.8Hz的声音 仿真案例 蜂鸣器发声 电路图 keil文件 蜂鸣器播放音乐 歌曲数据获得 使用的频率 keil文件 蜂鸣器介绍 前言&#xff1a;蜂鸣器是…

【洛谷 P8655】[蓝桥杯 2017 国 B] 发现环 题解(邻接表+并查集+路径压缩)

[蓝桥杯 2017 国 B] 发现环 题目描述 小明的实验室有 N N N 台电脑&#xff0c;编号 1 ∼ N 1 \sim N 1∼N。原本这 N N N 台电脑之间有 N − 1 N-1 N−1 条数据链接相连&#xff0c;恰好构成一个树形网络。在树形网络上&#xff0c;任意两台电脑之间有唯一的路径相连。 …

深入理解Java异常处理机制(day20)

异常处理 异常处理是程序运行过程产生的异常情况进行恰当的处理技术 在计算机编程里面&#xff0c;异常的情况比所我们所想的异常情况还要多。 Java里面有两种异常处理方式&#xff1b; 1.利用trycatchfinaly语句处理异常&#xff0c;优点是分开了处理异常代码和程序正常代码…