《通讯录》思路及代码实现详解

news2024/11/19 22:38:35

目录

一、通讯录功能实现的详细描述

二、通讯录的代码及思路实现

2、1 定义联系人结构体

2、2 初始化就结构体与释放动态开辟空间的实现

2、3 菜单打印

2、4 添加联系人信息

2、5 删除联系人信息

2、6 查询联系人信息

2、7 修改联系人信息

2、8 打印所有联系人信息

2、9 排序整理联系人信息

2、10 删除所有联系人信息

三、通讯录代码的整合

contact.h

contact.c

test.c

 四、总结


标题:通讯录思路及代码实现详解 

作者:@Ggggggtm

寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景

  我们前面详细讲述了动态内存管理详解(malloc、calloc、realloc)和结构体的声明使用及存储方式,那么这篇文章我们来一个综合用到结构体和动态内存开辟练习。实现一个通讯录,该通讯录的功能有增删查改、排序、查看操作。

一、通讯录功能实现的详细描述

  在日常生活中,通讯录是我们每个人都非常熟悉的了。最常见的就是手机中的电话薄。我们就根据手机中的电话薄的功能来模拟实现一个通讯录。我们先看实现的通讯录都有哪些具体细节:

  1. 打印一个菜单,提供用户选择功能;
  2. 添加联系人信息;
  3. 删除联系人信息;
  4. 查询联系人信息;
  5. 修改联系人信息;
  6. 显示所有联系人信息;
  7. 对所有联系人信息进行排序整理;
  8. 删除所有联系人信息;
  9. 操作完毕可选择退出。

  以上就是实现的通讯录的整体细节与模板,具体每个功能的具体实现思路及细节我们接着往下看,我会给大家一一实现与讲解。

二、通讯录的代码及思路实现

2、1 定义联系人结构体

  在整体实现之前,我们需要先把联系人结构体实现出来。我们这个结构体需要包含联系人的所有信息。同时,我们为了动态实现通讯录,我们需要再定义一个结构体,包含一个联系人结构体指针、记录存储的多少个联系人的一个变量和一个记录联系人结构体的容量。我们具体看代码实现。

 

#define MAX_NAME 20
#define MAX_ADDR 20
#define MAX_TELE 12
#define MAX_SEX 5
#define INIT_SZ 50
#define INCREASE_SZ 20

typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char addr[MAX_ADDR];
	char tele[MAX_TELE];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;
	int size;
	int capacity;
}Contact;

2、2 初始化就结构体与释放动态开辟空间的实现

  在这里我们把初始化就结构体与释放动态开辟空间的实现放到一块实现,因为他们本身就可以看做一对。在初始化结构体时,我们需要初始给出通讯录可存储多少个联系人,还要给出增长空间的大小。我们来看代码:

void InitContact(Contact* ps)
{
	PeoInfo* str = (PeoInfo*)calloc(INIT_SZ, sizeof(PeoInfo));
	if (str == NULL)
	{
		perror("InitContact::calloc");
		return;
	}
	ps->data = str;
	ps->size = 0;
	ps->capacity = INIT_SZ;
}

void DestoryContact(Contact* ps)
{
	free(ps->data);
	ps->capacity = 0;
	ps->size = 0;
	ps->data = NULL;
	ps = NULL;
}

2、3 菜单打印

  菜单的打印是我们必须第一个实现的,也是我们实现整个通讯录的参照。 菜单的打印需要简单明了即可。且实现比较简单。注意要单独放在一个自定义函数中,让主函数中的代码尽量减少,方便观察。 

void menu()
{
	printf("********************************\n");
	printf("****   1.Add      2.Del     ****\n");
	printf("****   3.Reserch  4.Modify  ****\n");
	printf("****   5.Show     6.Sort    ****\n");
	printf("****   7.DelAll   0.Exit    ****\n");
	printf("********************************\n");
}

2、4 添加联系人信息

  再添加联系人之前,我们要先判断通讯录是否为满。如果满了的话我们需要进行扩容,再进行添加联系人。注意,为了输出格式简介,我们这里在添加联系人时就进行了格式化添加。具体我们结合这代码一起理解一下。

void check_capacity(Contact* ps)
{
	if (ps->capacity == ps->size)
	{
		PeoInfo* str = (PeoInfo*)realloc(ps->data, sizeof(PeoInfo) * (ps->capacity + INCREASE_SZ));
		if (str == NULL)
		{
			perror("check_capacity::realloc");
			return;
		}
		ps->data = str;
		ps->capacity += INCREASE_SZ;
		printf("增容成功\n");
	}
}

void AddContact(Contact* ps)
{
	check_capacity(ps);
	printf("请输入要添加的姓名:");
	scanf("%s", ps->data[ps->size].name);
	printf("请输入要添加的年龄:");
	scanf("%d", &ps->data[ps->size].age);
	printf("请输入要添加的性别:");
	scanf("%s", ps->data[ps->size].sex);
	printf("请输入要添加的地址:");
	scanf("%s", ps->data[ps->size].addr);
	printf("请输入要添加的电话:");
	scanf("%s", ps->data[ps->size].tele);
	ps->size++;
}

2、5 删除联系人信息

  我们这里是根据用户所输入的联系人姓名进行删除的,所以我们先要判断用户所输入的联系人是否存在。当然,如果通讯录为空的话,我们就直接可以知道删除失败的。由于后面多个功能都需要查找联系人,所以我们这里把查找联系人独立分装成一个函数,以便我们后续的使用。

int find(Contact* ps, char* name)
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void DelContact(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空,删除失败\n");
		return;
	}
	char name[MAX_NAME];
	printf("请输入要删除人的姓名:");
	scanf("%s", name);
	int ret = find(ps, name);
	if (ret == -1)
	{
		printf("索要删除的人不存在哦\n");
		return;
	}

	int i = 0;
	for (i = ret; i < ps->size - 1; i++)
	{
		ps->data[i] = ps->data[i + 1];
	}
	ps->size--;
	printf("删除成功\n");
}

2、6 查询联系人信息

  我们这里的查询寻联系人与find()函数并不相同,但是又有联系。我们需要查找出联系人,如果该联系人存在,我们就输出该联系人的信息,注意输出格式简洁。如果不存在,我们就提示用户该联系人不存在。代码的实现也相对简单,我们直接看代码的实现: 

void ReserchContact(Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要查询人的姓名:");
	scanf("%s", name);
	int ret = find(ps, name);
	if (ret == -1)
	{
		printf("通讯录中没有%s的信息哦\n", name);
		return;
	}
	printf("%-20s%-20s%-15s%-20s%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	printf("%-20s%-20d%-15s%-20s%-12s\n", ps->data[ret].name, ps->data[ret].age, ps->data[ret].sex, ps->data[ret].addr, ps->data[ret].tele);
}

2、7 修改联系人信息

  修改联系人信息与查询联系人信息思路大同小异,代码实现也是相似。修改联系人信息我们先要找到联系人,然后再提示用户输入修改联系人的信息。我们直接看代码: 

void ModifyContact(Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = find(ps, name);
	if (ret == -1)
	{
		printf("通讯录中没有%s的信息哦\n", name);
		return;
	}
	printf("请输入姓名:");
	scanf("%s", ps->data[ret].name);
	printf("请输入年龄:");
	scanf("%d", &ps->data[ret].age);
	printf("请输入性别:");
	scanf("%s", ps->data[ret].sex);
	printf("请输入地址:");
	scanf("%s", ps->data[ret].addr);
	printf("请输入电话:");
	scanf("%s", ps->data[ret].tele);
	printf("修改成功\n");
}

2、8 打印所有联系人信息

  我们只需判断通讯录是否为空,如果为空就提示用户。不为空我们就直接遍历打印即可。实现相对较为简单,我们直接看代码:

void ShowContact(Contact* ps)
{
	printf("%-20s%-20s%-15s%-20s%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%-20s%-20d%-15s%-20s%-12s\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].addr, ps->data[i].tele);
	}
}

2、9 排序整理联系人信息

  我们先首先要给出一个排序菜单,提供给客户选择根据联系人的哪项信息来进行排序,我们这里利用qsort函数实现按排序。整体还是简单的。我们看代码实现:

void SortMenu()
{
	printf("\n");
	printf("********************************\n");
	printf("****   1.name     2.age     ****\n");
	printf("****   3.addr     4.tele    ****\n");
	printf("****   5.sex                ****\n");
	printf("********************************\n");
	printf("\n");
}
int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).name, (*((PeoInfo*)e2)).name);
}
int cmp_by_age(const void* e1, const void* e2)
{
	return (*((PeoInfo*)e1)).age - (*((PeoInfo*)e2)).age;
}
int cmp_by_addr(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).addr, (*((PeoInfo*)e2)).addr);
}
int cmp_by_tele(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).tele, (*((PeoInfo*)e2)).tele);
}
int cmp_by_sex(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).sex, (*((PeoInfo*)e2)).sex);
}
void SortContact(Contact* ps)
{
	int input = 0;
	if (ps->size == 0)
	{
		printf("通讯录为空,不用排序哦\n");
	}
	do
	{
		SortMenu();
		printf("请选择要根据什么排序:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_name);
			break;
		case 2:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_age);
			break;
		case 3:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_addr);
			break;
		case 4:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_tele);
			break;
		case 5:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_sex);
			break;
		default:
			printf("输入有误,请重新输入:");
		}
	} while (0);
}

2、10 删除所有联系人信息

  这个是最简单了,我们只需要先判断通讯录是否为空,不为空我们直接把size置0即可。

void DelAllContact(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录已经为空了哦\n");
		return;
	}
	ps->size = 0;
	printf("删除成功\n");
}

三、通讯录代码的整合

 由于代码量相对来说有一点多,所以我们就将函数的声明的定义分开,这样有利于提高代码的可读性,同时会保持一个良好的思路,且方便编写代码。

  我们将函数的声明放在单独的一个contact.h的头文件,函数的实现放在一个单独的contact.c源文件,函数的主方法及调用放在另一个单独的test.c源文件。

contact.h

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

#define MAX 100
#define MAX_NAME 20
#define MAX_ADDR 20
#define MAX_TELE 12
#define MAX_SEX 5
#define INIT_SZ 2
#define INCREASE_SZ 1

typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char addr[MAX_ADDR];
	char tele[MAX_TELE];
}PeoInfo;

typedef struct Contact
{
	PeoInfo* data;
	int size;
	int capacity;
}Contact;

//初始化
void InitContact(Contact* ps);

//释放动态开辟空间
void DestoryContact(Contact* ps);

//菜单
void menu();

//添加个人信息
void AddContact(Contact* ps);

//删除个人信息
void DelContact(Contact* s);

//查询个人信息
void ReserchContact(Contact* s);

//修改个人信息
void ModifyContact(Contact* s);

//查看整个通讯录
void ShowContact(Contact* s);

//对通讯录进行排序
void SortContact(Contact* s);

//排序菜单
void SortMenu();

//删除整个通讯录信息
void DelAllContact(Contact* s);

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"

void InitContact(Contact* ps)
{
	PeoInfo* str = (PeoInfo*)calloc(INIT_SZ, sizeof(PeoInfo));
	if (str == NULL)
	{
		perror("InitContact::calloc");
		return;
	}
	ps->data = str;
	ps->size = 0;
	ps->capacity = INIT_SZ;
}

void DestoryContact(Contact* ps)
{
	free(ps->data);
	ps->capacity = 0;
	ps->size = 0;
	ps->data = NULL;
	ps = NULL;
}

void menu()
{
	printf("********************************\n");
	printf("****   1.Add      2.Del     ****\n");
	printf("****   3.Reserch  4.Modify  ****\n");
	printf("****   5.Show     6.Sort    ****\n");
	printf("****   7.DelAll   0.Exit    ****\n");
	printf("********************************\n");
}

int find(Contact* ps, char* name)
{
	for (int i = 0; i < ps->size; i++)
	{
		if (strcmp(ps->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void check_capacity(Contact* ps)
{
	if (ps->capacity == ps->size)
	{
		PeoInfo* str = (PeoInfo*)realloc(ps->data, sizeof(PeoInfo) * (ps->capacity + INCREASE_SZ));
		if (str == NULL)
		{
			perror("check_capacity::realloc");
			return;
		}
		ps->data = str;
		ps->capacity += INCREASE_SZ;
		printf("增容成功\n");
	}
}

void AddContact(Contact* ps)
{
	check_capacity(ps);
	printf("请输入要添加的姓名:");
	scanf("%s", ps->data[ps->size].name);
	printf("请输入要添加的年龄:");
	scanf("%d", &ps->data[ps->size].age);
	printf("请输入要添加的性别:");
	scanf("%s", ps->data[ps->size].sex);
	printf("请输入要添加的地址:");
	scanf("%s", ps->data[ps->size].addr);
	printf("请输入要添加的电话:");
	scanf("%s", ps->data[ps->size].tele);
	ps->size++;
}

void DelContact(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空,删除失败\n");
		return;
	}
	char name[MAX_NAME];
	printf("请输入要删除人的姓名:");
	scanf("%s", name);
	int ret = find(ps, name);
	if (ret == -1)
	{
		printf("索要删除的人不存在哦\n");
		return;
	}

	int i = 0;
	for (i = ret; i < ps->size - 1; i++)
	{
		ps->data[i] = ps->data[i + 1];
	}
	ps->size--;
	printf("删除成功\n");
}

void ReserchContact(Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要查询人的姓名:");
	scanf("%s", name);
	int ret = find(ps, name);
	if (ret == -1)
	{
		printf("通讯录中没有%s的信息哦\n", name);
		return;
	}
	printf("%-20s%-20s%-15s%-20s%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	printf("%-20s%-20d%-15s%-20s%-12s\n", ps->data[ret].name, ps->data[ret].age, ps->data[ret].sex, ps->data[ret].addr, ps->data[ret].tele);
}

void ModifyContact(Contact* ps)
{
	char name[MAX_NAME];
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = find(ps, name);
	if (ret == -1)
	{
		printf("通讯录中没有%s的信息哦\n", name);
		return;
	}
	printf("请输入姓名:");
	scanf("%s", ps->data[ret].name);
	printf("请输入年龄:");
	scanf("%d", &ps->data[ret].age);
	printf("请输入性别:");
	scanf("%s", ps->data[ret].sex);
	printf("请输入地址:");
	scanf("%s", ps->data[ret].addr);
	printf("请输入电话:");
	scanf("%s", ps->data[ret].tele);
	printf("修改成功\n");
}

void ShowContact(Contact* ps)
{
	printf("%-20s%-20s%-15s%-20s%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%-20s%-20d%-15s%-20s%-12s\n", ps->data[i].name, ps->data[i].age, ps->data[i].sex, ps->data[i].addr, ps->data[i].tele);
	}
}

void SortMenu()
{
	printf("\n");
	printf("********************************\n");
	printf("****   1.name     2.age     ****\n");
	printf("****   3.addr     4.tele    ****\n");
	printf("****   5.sex                ****\n");
	printf("********************************\n");
	printf("\n");
}
int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).name, (*((PeoInfo*)e2)).name);
}
int cmp_by_age(const void* e1, const void* e2)
{
	return (*((PeoInfo*)e1)).age - (*((PeoInfo*)e2)).age;
}
int cmp_by_addr(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).addr, (*((PeoInfo*)e2)).addr);
}
int cmp_by_tele(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).tele, (*((PeoInfo*)e2)).tele);
}
int cmp_by_sex(const void* e1, const void* e2)
{
	return strcmp((*((PeoInfo*)e1)).sex, (*((PeoInfo*)e2)).sex);
}
void SortContact(Contact* ps)
{
	int input = 0;
	if (ps->size == 0)
	{
		printf("通讯录为空,不用排序哦\n");
	}
	do
	{
		SortMenu();
		printf("请选择要根据什么排序:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_name);
			break;
		case 2:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_age);
			break;
		case 3:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_addr);
			break;
		case 4:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_tele);
			break;
		case 5:
			qsort(ps->data, ps->size, sizeof(ps->data[0]), cmp_by_sex);
			break;
		default:
			printf("输入有误,请重新输入:");
		}
	} while (0);
}

void DelAllContact(Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录已经为空了哦\n");
		return;
	}
	ps->size = 0;
	printf("删除成功\n");
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"

int main()
{
	int input = 0;
	Contact s;
	InitContact(&s);
	do
	{
		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&s);
			break;
		case 2:
			DelContact(&s);
			break;
		case 3:
			ReserchContact(&s);
			break;
		case 4:
			ModifyContact(&s);
			break;
		case 5:
			ShowContact(&s);
			break;
		case 6:
			SortContact(&s);
			break;
		case 7:
			DelAllContact(&s);
			break;
		case 0:
			DestoryContact(&s);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入有误,请重新输入:");
		}
	} while (input);
	return 0;
}

 四、总结

  我们要实现通讯录前,我们应该有一个整体的模板和思路,这样对于我们后续的实现比较有利。整个实现的过程相对来说并不是很难,中间在添加联系人和删除联系人的时候有几个细节是需要我们注意的。当我们有了整体思路,实现起来也就不是问题了。 

  对通讯录的实现就到这里,希望本篇文章会对你有所帮助,感谢阅读ovo~

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

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

相关文章

75. 序列模型的代码实现

1. 训练 在了解了上述统计工具后&#xff0c;让我们在实践中尝试一下&#xff01; 首先&#xff0c;我们生成一些数据&#xff1a;(使用正弦函数和一些可加性噪声来生成序列数据&#xff0c; 时间步为 1,2,…,1000 。) %matplotlib inline import torch from torch import nn…

新手nvm npm 卸载不用依赖包,项识别为 cmdlet、函数、脚本文件,等命令集合

nvm安装包&#xff1a;Releases coreybutler/nvm-windows GitHub下载ta就不用单独下载node了注意:vnm安装位置尽量不要动C:\Users\Administrator\AppData\Roaming\nvm\settings.txt增加下面代码node_mirror: https://npm.taobao.org/mirrors/node/ npm_mirror: https://npm.t…

java+Springboot交通事故档案管理系统

系统分为用户和管理员两个角色 用户的主要功能有&#xff1a; 1.用户注册和登陆系统 2.用户查看警察相关信息 3.用户查看我的相关事故信息&#xff0c;可以对交通事故进行交通申诉 4.用户查看交通申诉审核信息 5.退出登陆 管理员的主要功能有&#xff1a; 1.管理员输入账户登陆…

Metasploit渗透框架介绍及永恒之蓝复现

Metasploit渗透框架介绍及永恒之蓝复现一、Metasploit渗透框架介绍1.1 名词解释1.2 MSF简介1.3 MSF框架结构1.4 MSF命令汇总1.4.1 常用命令1.4.2 基本命令1.4.3 Exploits模块1.4.4 漏洞名称规则1.5 MSF模块介绍1.5.1 auxiliary(辅助模块)1.5.2 exploits(漏洞利用模块)1.5.3 pay…

Open3D 泊松盘网格采样(Python版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在图形的许多应用中,特别是在渲染中,从蓝色噪声分布生成样本是很重要的。然而,现有的有效技术不容易推广到二维以外。不过泊松盘采样是个例外,它允许在O(N)时间内生成泊松盘样本,而且该方法很容易在任意维度上…

分布式CAP和BASE理论学习笔记

参考至&#xff1a;https://blog.csdn.net/solihawk/article/details/124442443 1. CAP理论 CAP理论是计算机科学家Eric Brewer在2000年提出的理论猜想&#xff0c;在2002年被证明并成为分布式计算领域公认的定理&#xff0c;其理论的基本观念是&#xff0c;在分布式系统中不…

加密算法 AES和RSA

一&#xff0c;加密&#xff08;一&#xff09;加密基础&#xff1f;通过互联网发送数据&#xff0c;数据可能会被第三者恶意窃听&#xff0c;造成损失。因此需要给重要的数据进行加密&#xff0c;加密后的数据被称为“密文”。接收方通过解除加密或得原本的数据&#xff0c;把…

人工智能卷积算法

文章目录前言数字信号处理与卷积运算卷积公式与计算过程边缘卷积计算与0填充NumPy卷积函数二维矩阵卷积计算图像卷积应用实例总结前言 卷积运算实际上是一种常见的数学方法&#xff0c;与加法&#xff0c;乘法等运算类似&#xff0c;都是由两个输入的到一个输出。不同的是&…

迷宫问题---数据结构实践作业

迷宫问题—数据结构实践作业 ✅作者简介&#xff1a;大家好,我是新小白2022&#xff0c;让我们一起学习&#xff0c;共同进步吧&#x1f3c6; &#x1f4c3;个人主页&#xff1a;新小白2022的CSDN博客 &#x1f525;系列专栏&#xff1a;算法与数据结构 &#x1f496;如果觉得博…

什么是HAL库和标准库,区别在哪里?

参考文章https://blog.csdn.net/u012846795/article/details/122227823 参考文章 https://zhuanlan.zhihu.com/p/581798453 STM32的三种开发方式 通常新手在入门STM32的时候&#xff0c;首先都要先选择一种要用的开发方式&#xff0c;不同的开发方式会导致你编程的架构是完全…

Java 面向对象程序设计 消息、继承与多态实验 课程设计研究报告

代码&#xff1a;Java计算机课程设计面向对象程序设计对战游戏SwingGUI界面-Java文档类资源-CSDN文库 一、课程设计内容 一个游戏中有多种角色(Character)&#xff0c;例如&#xff1a;国王&#xff08;King&#xff09;、皇后&#xff08;Queen&#xff09;、骑士&#xff0…

【Linux多线程】

Linux多线程Linux线程概念什么是线程线程的优点线程的缺点线程异常线程用途Linux进程VS线程进程和线程进程的多个线程共享Linux线程控制POSIX线程库线程创建线程等待线程终止分离线程线程ID及进程地址空间布局Linux线程概念 什么是线程 在一个程序里的一个执行路线就叫做线程…

JavaScript 如何正确的分析报错信息

文章目录前言一、报错类型1.控制台报错2.终端报错二、错误追查总结前言 摸爬滚打了这么长时间…总结了一些排查错误的经验, 总的来说, 这是一篇JavaScript新手向文章. 里面会有些不那么系统性的, 呃, 知识? 一、报错类型 报错信息该怎么看, 怎么根据信息快速的追查错误. 1.…

瑞吉外卖项目

技术选型&#xff1a; 1、JAVA版本&#xff1a;JDK11 2、数据库&#xff1a;mysql5.7 Navicat 3、后端框架&#xff1a;SpringBoot SpringMVC MyBatisPlus 4、工具类&#xff1a;发邮件工具类、生成验证码工具类 5、项目优化&#xff1a;Nginx、Redis、读写分离 项目来…

2022. 12 青少年机器人技术等级考试理论综合试卷(五级)

2022.年12月青少年机器人技术等级考试理论综合试卷&#xff08;五级&#xff09; 分数&#xff1a; 100 题数&#xff1a; 30 一、 单选题(共 20 题&#xff0c; 共 80 分) 1.下列程序执行后,串口监视器显示的相应内容是&#xff1f; &#xff08; &#xff09; A.1 B.2 C.4 D.…

WPF绑定(Binding)下的数据验证IDataErrorInfo

绑定下的数据验证 WPF中Binding数据校验、并捕获异常信息的三种方式讲到了三种方式&#xff0c;其中使用ValidatinRule的方式比较推荐&#xff0c;但是如果一个类中有多个属性&#xff0c;要为每个属性都要声明一个ValidatinRule&#xff0c;这样做非常麻烦。可以让类继承自ID…

【High 翻天】Higer-order Networks with Battiston Federico (8)

目录传播与社会动力学&#xff08;2&#xff09;Opinion and cultural dynamicsVoter modelMajority modelsContinuous models of opinion dynamicsCultural dynamics传播与社会动力学&#xff08;2&#xff09; 在本节将讨论一些观点和文化动力学模型&#xff0c;它们基于物理…

【JavaSE】反射

一、概念反射是在运行期间&#xff0c;动态获取对象的属性和方法二、相关的类在Java的反射里主要有以下几个类&#xff1a;Class类&#xff0c;这是反射的起源&#xff0c;反射必须要先获取Class对象&#xff0c;其次是Field类&#xff0c;当我们需要通过反射获取私有字段时就需…

老杨说运维 | 2023,浅谈智能运维趋势(一)

&#xff08;文末附视频回顾&#xff0c;一键直达精彩内容&#xff09; 前言&#xff1a; 2022年&#xff0c;是经济被影响的一年&#xff0c;这一年无论是企业还是个人经济形势都呈下滑趋势&#xff0c;消费降级状态或许不会因为2022的结束而改观。 全球经济紧缩的状态下&am…

不仅会编程还要会英语(博主英语小笔记)1.1名词

目录 1-1名词的概念和分类 1、名词的概念 2&#xff0e;名词根据其意义可以分为专有名词和普通名词 &#xff08;1&#xff09;专有名词&#xff1a; &#xff08;2&#xff09;普通名词&#xff1a; 1-1名词的概念和分类 1、名词的概念 名词是表示人、动物、地点、物品以…