C语言实现---通讯录

news2024/11/15 21:47:00

通讯录

  • 前言
  • 1.初始化通讯录
  • 2.SHOW展示通讯录
  • 3.ADD添加联系人的函数
  • 4.DEL删除联系人的函数
  • 5.SEARCH查找联系人的函数
  • 6.MODIFY修改联系人的函数
  • 7.销毁通讯录
  • 8.整体代码展示
    • 1.头文件"contact.h"
    • 2.源文件"contact.c"
    • 3.测试文件"test.c"

前言

那么好了好了,宝子们,之前学了进阶指针和动态内存管理,我们就拿通讯录来练练手吧,来吧开始整活!⛳️
因为我们之前就学过,写过类似的小游戏,都是将各个不同的功能封装成一个函数,我们依然延续这个做法。

1.初始化通讯录

//函数声明

//初始化
void Initcon(Contact* pc);

初始化静态版
//void Initcon(Contact* pc)
//{
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//
//}




//动态的版本
void Initcon(Contact* pc)
{
	assert(pc);
	pc->data = (Info*)malloc(DEFAULT_SZ * sizeof(Info));
	if (pc->data == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
}


//判断容量的函数
int CheckCapacity(Contact* pc);
int CheckCapacity(Contact* pc)//判断容量
{
	if (pc->sz == pc->capacity)
	{
		Info* ptr = (Info*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(Info));
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return 0;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
			return 1;
		}
	}
	return 1;
}

2.SHOW展示通讯录

//SHOW展示
void ContactSHOW(Contact* pc);



//SHOW
void ContactSHOW(const Contact* pc)
{
	assert(pc);
	int i = 0;
	//先加一个列标题
	printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
			pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].age,
			pc->data[i].tele,
			pc->data[i].home);
	}

}


3.ADD添加联系人的函数

为什么添加联系人还有静态版和动态版的?因为静态版就是你固定了这个空间的大小不能再增加,如果动态版的话,它是像弹簧一样有弹性的,你要多大我就开辟多大,要多小我就开辟多小。所以说我们都是先学完动态内存管理和结构体和指针这一块才来写通讯录的。

ADD静态
//void ContactADD(Contact* pc)
//{
//	assert(pc);
//	if (pc->sz == MAX)
//	{
//		printf("通讯录爆满!无法添加\n");
//		return;
//	}
//
//	puts("请输入姓名:");
//	scanf("%s", pc->data[pc->sz].name);
//	puts("请输入性别:");
//	scanf("%s", pc->data[pc->sz].sex);
//	puts("请输入年龄:");
//	scanf("%d", &(pc->data[pc->sz].age));
//	puts("请输入电话:");
//	scanf("%s", pc->data[pc->sz].tele);
//	puts("请输入住址:");
//	scanf("%s", pc->data[pc->sz].home);
//
//	pc->sz++;
//	printf("联系人增加成功!\n");
//}


//动态的版本
void ContactADD(Contact* pc)
{
	assert(pc);

	if (0 == CheckCapacity(pc))
	{
		return;
	}

	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].home);

	pc->sz++;
	printf("成功增加联系人\n");
}

4.DEL删除联系人的函数

在进行删除联系人,查找联系人和修改联系人的时候,我们都需要先找到这个联系人所在的位置,所以说这以下三种方法都要用一个封装find的函数。


//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
			return i;//找到了直接返回i
	}
	return -1;//找不到
}
//DEL删除
void ContactDEL(Contact* pc);

//DEL
void ContactDEL(Contact* pc)
{
	assert(pc);
	//为空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	//确定你要删除谁?
	printf("输入你要删除人的名字:>");
	char name[MAX_NAME] = { 0 };
	scanf("%s", name);
	找到你要删除人的名字
	//int i = 0;
	//int del = 0;//目的是做标记:记下删除人的下标位置
	//int flag = 0;//另一个flag的原因是,如果要删除的人根本就不存在。
	//for (i = 0; i < pc->sz; i++)
	//{
	//	if (strcmp(pc->data[i].name, name) == 0)
	//	{
	//		del = i;
	//		flag = 1;
	//		break;
	//	}
	//	if (flag == 0)
	//	{
	//		puts("要删除的人根本就不存在!\n");
	//		return;
	//	}
	//}

	//找到你要删除人的名字
	int i = 0;
	//目的是做标记:记下删除人的下标位置
	//封装一个Find函数
	int del = FindByName(pc, name);//把整个通讯录和要删除人的名字传过去
	if (del == -1)
	{
		printf("所要查找的联系人不存在!\n");
		return;
	}

	//(覆盖式删除)

	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}



5.SEARCH查找联系人的函数

//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
			return i;//找到了直接返回i
	}
	return -1;//找不到
}

//SEARCH
void ContactSearch(Contact* pc)
{
	assert(pc);
	//输入你要查找的人
	char name[MAX_NAME] = { 0 };
	printf("输入你要查找的人\n");
	scanf("%s", &name);
	//调用查找函数
	int pos = FindByName(pc, name);//position位置
	if (pos == -1)
	{
		printf("找不到了\n");
		return;
	}
	else
	{
		//直接粘贴SHOW函数中的:打印数据

		//先加一个列标题
		printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
		printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
			pc->data[pos].name,
			pc->data[pos].sex,
			pc->data[pos].age,
			pc->data[pos].tele,
			pc->data[pos].home);

	}
}

6.MODIFY修改联系人的函数


//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
			return i;//找到了直接返回i
	}
	return -1;//找不到
}

//MODIFY修改
void ContactModify(Contact* pc);

//MODIFY

void ContactModify(Contact* pc)
{
	assert(pc);
	//输入你要修改的人
	char name[MAX_NAME] = { 0 };
	printf("输入你要修改的人\n");
	scanf("%s", &name);
	//调用查找函数
	int pos = FindByName(pc, name);//position位置
	if (pos == -1)
	{
		printf("找不到了\n");
		return;
	}
	else
	{
		puts("请输入姓名:");
		scanf("%s", pc->data[pos].name);
		puts("请输入性别:");
		scanf("%s", pc->data[pos].sex);
		puts("请输入年龄:");
		scanf("%d", &(pc->data[pos].age));
		puts("请输入电话:");
		scanf("%s", pc->data[pos].tele);
		puts("请输入住址:");
		scanf("%s", pc->data[pos].home);
	}
	printf("修改成功!\n");
}

7.销毁通讯录

//销毁通讯录
void DestroyContact(Contact* pc);
void DestroyContact(Contact* pc)
{
	free(pc->data);//直接free
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

8.整体代码展示

在这里我们还是用到了三个窗口文件,一个是头文件“contact.h”,一个是源文件"contact.c",一个是测试文件"test.c"。

1.头文件"contact.h"

头文件里面定义了许多宏,是为了修改方便,以后大家要常用这种方法。

#pragma once

#include <string.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_HOME 20


#define DEFAULT_SZ 3//初始化默认sz为3个
#define INC_SZ 2//每次扩容2个

//一个人的所有信息
typedef struct info
{
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	int tele[MAX_TELE];
	char home[MAX_HOME];
}Info;

//通讯录

//静态版
//typedef struct contact
//{
//	Info data[MAX];
//	int sz;
//}Contact;

//动态版
typedef struct contact
{
	Info* data;//指向了存放数据的空间
	int sz;//记录的当前放的有效元素的个数
	int capacity;//通讯录当前的最大容量
}Contact;

//设置这个枚举是为了让读者更好地理解零代表退出,1代表添加,2代表删除,3代表查找,4代表修改,5代表显示,6代表排序。因为这是枚举的优点!!!
enum OPTION
{
	EXIT,//默认为0,下面的按顺序:1,2,3,4,5,6......
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};

//函数声明

//初始化
void Initcon(Contact* pc);

//ADD添加
void ContactADD(Contact* pc);

//SHOW展示
void ContactSHOW(Contact* pc);

//DEL删除
void ContactDEL(Contact* pc);

//SEARCH查找
void ContactSearch(Contact* pc);

//MODIFY修改
void ContactModify(Contact* pc);

//销毁通讯录
void DestroyContact(Contact* pc);

2.源文件"contact.c"

#include "contact.h"


初始化静态版
//void Initcon(Contact* pc)
//{
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//
//}




//动态的版本
void Initcon(Contact* pc)
{
	assert(pc);
	pc->data = (Info*)malloc(DEFAULT_SZ * sizeof(Info));
	if (pc->data == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;


}

int CheckCapacity(Contact* pc);
int CheckCapacity(Contact* pc)//判断容量
{
	if (pc->sz == pc->capacity)
	{
		Info* ptr = (Info*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(Info));
		if (ptr == NULL)
		{
			perror("CheckCapacity");
			return 0;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
			return 1;
		}
	}
	return 1;
}

ADD静态
//void ContactADD(Contact* pc)
//{
//	assert(pc);
//	if (pc->sz == MAX)
//	{
//		printf("通讯录爆满!无法添加\n");
//		return;
//	}
//
//	puts("请输入姓名:");
//	scanf("%s", pc->data[pc->sz].name);
//	puts("请输入性别:");
//	scanf("%s", pc->data[pc->sz].sex);
//	puts("请输入年龄:");
//	scanf("%d", &(pc->data[pc->sz].age));
//	puts("请输入电话:");
//	scanf("%s", pc->data[pc->sz].tele);
//	puts("请输入住址:");
//	scanf("%s", pc->data[pc->sz].home);
//
//	pc->sz++;
//	printf("联系人增加成功!\n");
//}


//动态的版本
void ContactADD(Contact* pc)
{
	assert(pc);

	if (0 == CheckCapacity(pc))
	{
		return;
	}

	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].home);

	pc->sz++;
	printf("成功增加联系人\n");
}


//SHOW
void ContactSHOW(const Contact* pc)
{
	assert(pc);
	int i = 0;
	//先加一个列标题
	printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
			pc->data[i].name,
			pc->data[i].sex,
			pc->data[i].age,
			pc->data[i].tele,
			pc->data[i].home);
	}

}

//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
			return i;//找到了直接返回i
	}
	return -1;//找不到
}
//DEL
void ContactDEL(Contact* pc)
{
	assert(pc);
	//为空
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	//确定你要删除谁?
	printf("输入你要删除人的名字:>");
	char name[MAX_NAME] = { 0 };
	scanf("%s", name);
	找到你要删除人的名字
	//int i = 0;
	//int del = 0;//目的是做标记:记下删除人的下标位置
	//int flag = 0;//另一个flag的原因是,如果要删除的人根本就不存在。
	//for (i = 0; i < pc->sz; i++)
	//{
	//	if (strcmp(pc->data[i].name, name) == 0)
	//	{
	//		del = i;
	//		flag = 1;
	//		break;
	//	}
	//	if (flag == 0)
	//	{
	//		puts("要删除的人根本就不存在!\n");
	//		return;
	//	}
	//}

	//找到你要删除人的名字
	int i = 0;
	//目的是做标记:记下删除人的下标位置
	//封装一个Find函数
	int del = FindByName(pc, name);//把整个通讯录和要删除人的名字传过去
	if (del == -1)
	{
		printf("所要查找的联系人不存在!\n");
		return;
	}

	//(覆盖式删除)

	for (i = del; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除联系人成功!\n");
}

//SEARCH
void ContactSearch(Contact* pc)
{
	assert(pc);
	//输入你要查找的人
	char name[MAX_NAME] = { 0 };
	printf("输入你要查找的人\n");
	scanf("%s", &name);
	//调用查找函数
	int pos = FindByName(pc, name);//position位置
	if (pos == -1)
	{
		printf("找不到了\n");
		return;
	}
	else
	{
		//直接粘贴SHOW函数中的:打印数据

		//先加一个列标题
		printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
		printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
			pc->data[pos].name,
			pc->data[pos].sex,
			pc->data[pos].age,
			pc->data[pos].tele,
			pc->data[pos].home);

	}
}


//MODIFY

void ContactModify(Contact* pc)
{
	assert(pc);
	//输入你要修改的人
	char name[MAX_NAME] = { 0 };
	printf("输入你要修改的人\n");
	scanf("%s", &name);
	//调用查找函数
	int pos = FindByName(pc, name);//position位置
	if (pos == -1)
	{
		printf("找不到了\n");
		return;
	}
	else
	{
		puts("请输入姓名:");
		scanf("%s", pc->data[pos].name);
		puts("请输入性别:");
		scanf("%s", pc->data[pos].sex);
		puts("请输入年龄:");
		scanf("%d", &(pc->data[pos].age));
		puts("请输入电话:");
		scanf("%s", pc->data[pos].tele);
		puts("请输入住址:");
		scanf("%s", pc->data[pos].home);
	}
	printf("修改成功!\n");
}



void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

3.测试文件"test.c"

#include <stdio.h>
#include "contact.h"

void menu()
{
	printf("*******************************\n");
	printf("******   1.add   2.del   ******\n");
	printf("******   3.search   4.modify  *\n");
	printf("******   5.show   6.sort   ****\n");
	printf("******   0.exit            ****\n");
	printf("*******************************\n");

}
void test()
{
	//首先我得有个通讯录
	Contact con;
	//初始化通讯录
	Initcon(&con);
	int input = 0;
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			ContactADD(&con);
			break;
		case DEL:
			ContactDEL(&con);
			break;
		case SEARCH:
			ContactSearch(&con);
			break;
		case MODIFY:
			ContactModify(&con);
			break;
		case SHOW:
			ContactSHOW(&con);
			break;
		case SORT:
			//排序?qsort
			//按照姓名?
			//按照年龄?......
			break;
		case EXIT:
			
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			break;
		};

	} while (input);
}


int main()
{
	test();
	return 0;
}

注意:

  • 运用枚举,可以增加代码的可读性,避免自己写代码以及别人阅读代码时不明确0,1,2,3,4,5,6的具体意义。
  • 用#define定义一些常用数据,如联系人个数1000,以便之后需要修改时只需修改一处,而不是修改全部用到1000的地方。

好了,今天的分享就到这里了

如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!

在这里插入图片描述

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

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

相关文章

解决键盘长按才有反应

问题分析&#xff1a; 排除键盘自身没有问题&#xff0c;那就应该是电脑设置的问题&#xff0c;目前我遇到的不小心长按shift键设置了【筛选键】 解决方式&#xff1a; 打开设置搜索筛选建&#xff0c;关闭&#xff0c;粘带键也会出现类似问题。

【go语言】结构体

结构体 结构体定义 type name struct{value1 type1value2 type2...... }组成结构体的数据称为字段&#xff0c;每一个字段有一个类型和一个名字&#xff0c;每一个字段的名字必须唯一&#xff0c;字段的类型任意。 创建结构体 type myStruct struct{i1 intf1 float32str st…

【软件测试】开发/测试模型

开发/测试模型 瀑布模型 设计&#xff1a;技术文档(设计那些接口&#xff0c;库表&#xff0c;mq&#xff0c;定时任务)&#xff0c;UI视觉稿 特点&#xff1a;线性的结构。 优点&#xff1a;每个阶段做什么&#xff0c;产出什么非常清晰 缺点&#xff1a;测试人员介入太晚…

了解CISP,看这篇文章就够了,附上CISP证书题库资料

前言 【点击此处领取CISP题库资料和网络安全学习资】 什么是CISP&#xff1f; CISP是中国信息安全测评中心依据中编办赋予的职能&#xff0c;建立和发展的一整套完整的信息安全保障人才培训体系&#xff0c;从2002年开始启动。 CISP (CertifiedInformation Security Profes…

分享55个C源码源代码总有一个是你想要的

分享55个C源码源代码总有一个是你想要的 链接&#xff1a;https://pan.baidu.com/s/1_zbaunqvmYRhCiX7hbiqmg?pwd8888 提取码&#xff1a;8888 1. 项目名称 apachesubversion版本控制系统 v1.10.3 Ceph分布式文件系统 v17.2.5 clip命令行插图处理器 v0.8 curve分布式存…

在前端设计中,子元素的基线和父元素的基线分别是什么意思?并利用Bootstrap的类align-items-baseline实现子元素在其父容器内基线对齐。

子元素的基线和父元素的基线是用于文本对齐的重要概念。让我解释一下它们分别指的是什么&#xff1a; 子元素的基线&#xff08;Baseline of Child Elements&#xff09;&#xff1a; 子元素的基线是指子元素内文本的底部边缘&#xff0c;特别是字母的底部边缘。在包含文本的元…

医药行业电力供应3大难题?教你如何破解

电力是现代社会不可或缺的基础设施之一&#xff0c;它支持着工业、商业和生活的各个方面。在这个数字化、电气化的时代&#xff0c;电力配电系统扮演着关键的角色&#xff0c;确保电能以可靠、高效、安全的方式分发到我们的家庭、企业和工厂。 然而&#xff0c;要保持电力分配的…

LeetCode 518.零钱兑换II 动态规划 + 完全背包 + 组合数

给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整数。 示例…

DevOps持续集成与交付

概述 Jenkins是一个支持容器化部署的、使用Java运行环境的开源软件&#xff0c;使用Jenkins平台可以定制化不同的流程与任务、以自动化的机制支持DevOps领域中的CI与CD&#xff0c;在软件开发与运维的流程中自动化地执行软件工程项目的编译、构建、打包、测试、发布以及部署&a…

FileManager/本地文件增删改查, Cache/图像缓存处理 的操作

1. FileManager 本地文件管理器&#xff0c;增删改查文件 1.1 实现 // 本地文件管理器 class LocalFileManager{// 单例模式static let instance LocalFileManager()let folderName "MyApp_Images"init() {createFolderIfNeeded()}// 创建特定应用的文件夹func cr…

在英文电脑系统中,中文显示??????

如果操作系统是英文的&#xff0c;那么无论是在cmd界面&#xff0c;还是在Visual Studio的调试界面&#xff0c;中文显示都是一串问号??????? 这是因为在英文系统中&#xff0c;Console 的默认代码页是 437(OEM -United States)&#xff0c;不支持中文输入输出&#xff…

照片后期处理软件DxO FilmPack 6 mac中文说明

DxO FilmPack 6 for Mac是一款照片后期处理软件。它可以模拟超过60种著名胶片品牌和类型的色彩和颗粒感&#xff0c;使照片具有复古、艺术和时尚风格。 ​DxO FilmPack 6 mac支持RAW和JPG格式的照片&#xff0c;并提供丰富的调整选项&#xff0c;如亮度、对比度、曝光、阴影和高…

十六.镜头知识之工业镜头的质量判断因素

十六.镜头知识之工业镜头的质量判断因素 文章目录 十六.镜头知识之工业镜头的质量判断因素1.分辨率(Resolution)2.明锐度(Acutance)3.景深(DOF)&#xff1a;4. 最大相对孔径与光圈系数5.工业镜头各参数间的相互影响关系5.1.焦距大小的影响情况5.2.光圈大小的影响情况5.3.像场中…

【Java 进阶篇】深入理解SQL查询语言(DQL)

SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系型数据库的强大编程语言。它提供了各种命令和语句&#xff0c;用于执行各种操作&#xff0c;包括数据查询、插入、更新和删除。本文将深入探讨SQL查询语言&#xff08;DQL&#xff09;&#xff0c;它是…

Bootstrap的弹性盒子布局学习笔记

Bootstrap的弹性盒子布局学习笔记 目录 01-综述02-利用类d-flex与类d-inline-flex将容器定义为弹性盒子03-对弹性容器的的元素在水平方向上进行排列顺序设置03-对弹性容器的的元素在垂直方向上进行排列顺序设置04-弹性盒子内所有元素在主轴方向上的对齐方式05-1-弹性盒子内各行…

myArm 全新七轴桌面型机械臂

引言 在不断演进的科技世界中&#xff0c;我们始终追求创新和卓越&#xff0c;以满足客户的需求并超越他们的期望。今天&#xff0c;我们很高兴地宣布我们的最新产品——myArm 300 Pi&#xff0c;一款七轴的桌面型机械臂。这款产品的独特之处在于其灵活性和可编程性&#xff0c…

16. Seata 分布式事务

Spring Cloud 微服务系列文章&#xff0c;点击上方合集↑ 1. 简介 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。 事务是保障一系列操作要么都成功&#xff0c;要么都失败。就比如转账&#xff1a;A转账100元给B&#xff0…

sentinel-dashboard-1.8.0.jar开机自启动脚本

启动阿里巴巴的流控组件控制面板需要运行一个jar包&#xff0c;通常需要运行如下命令&#xff1a; java -server -Xms4G -Xmx4G -Dserver.port8080 -Dcsp.sentinel.dashboard.server127.0.0.1:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.0.jar &…

如何评估测试用例的优先级?

评估测试用例的优先级&#xff0c;有助于我们及早发现和解决可能对系统稳定性和功能完整性产生重大影响的问题&#xff0c;助于提高测试质量&#xff0c;提高用户满意度。 如果没有做好测试用例的优先级评估&#xff0c;往往容易造成对系统关键功能和高风险场景测试的忽略&…

STM32定时器

目录 基本定时器结构框图 通用定时器结构框图 高级定时器结构框图 ​编辑TIMx时基单元 定时工作原理 影子寄存器 ​编辑 定时器中断基本结构 定时器计时中断 定时器外部中断 输出比较 OC 输出比较模式 PWM基本结构 输出比较常用函数 使用PWM来驱动舵机 输入捕…