当前位置: 首页 > news >正文

数据结构·顺序表应用

        本节应用是要用顺序表实现一个通讯录,收录联系人的姓名、性别、电话号码、住址、年龄

                        ​​​​​​​        

        顺序表的实现在上一节中已经完成了,本节的任务其实就是应用上节写出来的代码的那些接口函数功能,做出来一个好看的,可视化的东西

        首先把准备工作做好,创立好通讯录的头文件Contest.h和源文件Contest.c还有测试源文件,再把上一节的顺序表文件链接过来,在这节中直接使用上节的函数功能

        ​​​​​​​        ​​​​​​​        

1. 通讯录数据类型

        首先我们在Contect.h文件中把通讯录结构体写出来,再改一个好写的名字

                        

                这边数组长度是用宏定义的,为了方便以后更改

2. 通讯录操作方法

        现在我们写一下通讯录的操作发方法,跟之前的写法一样,写一个菜单函数,然后用do···while和switch语句让用户选择要进行什么操作

        在Contect.c文件中写menu()函数,并包含上它的头文件Contect.h

  

        用户操作方案,写在test.c中:

   

        

3. 顺序表改成通讯录

        现在我们要将上节的顺序表稍加修改,将arr中的元素从int型改成通讯录结构体型的,此时,需要在SeqList.h中包含上Contect.h

        修改一下SLDatatype的表示对象为Info就完成了

4. 通讯录里提供的操作

        这个时候我们需要用到SeqList文件中的内容了,但是我们不能在Contest.h中引用SeqList.h了,这样会导致头文件嵌套问题,你包含我,我包含你,没完没了,程序就出错了,所以我们的头文件包含要定好一个顺序,就像这样

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

        确定好这个顺序了,那我们如何使用SeqList.h文件中的内容呢,此时的解决方法就是前置声明,因为内容在后面,但是我们要在前面使用它,所以我们可以在前面声明一下这个内容,就可以在前面使用它了

        ​​​​​​​        

        前置声明之后再改个名字,从顺序表改成通讯录,方便后边辨识和使用

        这时我们运行一下会发现喜提一大堆错误,这时不要慌,问题就出现在之前顺序表的查找和打印函数上了,它们的类型错误导致的报错,我们只需要把它们注释掉就可以了

4.1 通讯录的初始化和销毁

        这块功能非常简单,我们只需要复用SeqList.h中的函数就可以

        ​​​​​​​        

                

        然后在测试文件中调试一下

        发现没问题,该创建的东西都创建好了

4.2 "增""删""查""改""查看通讯录"

4.2.1 "增"

        首先创建一个临时变量info暂时存放一个人的所有信息,然后复用函数就可以了

        在把增的功能添加到主函数之前,我们要在do···while外边写好创建、初始化和销毁通讯录顺序表的功能

        ​​​​​​​        ​​​​​​​        

        然后把ContectAdd()函数放到"增"的位置就好了

        ​​​​​​​        ​​​​​​​        

4.2.2 "查看通讯录"

        先写查看通讯录用来方便检验之后的代码

        然后把这个功能加到main函数里头

4.2.3 "查"

        查找的话可以通过那5个方面去查,这里我就写一个通过名字查的

        这个FindByName()函数因为后面还要用,所以就单拎出来写的,注意用到了字符串操作函数,要引用一下头文件。

4.2.4 "删"

    

4.2.5 "改"

5. 完整代码

Contect.h完整代码

//通讯录数据类型
#define NAME_MAX 100
#define GENDER_MAX 10
#define TEL_MAX 12
#define ADDR_MAX 100
typedef struct PersonInfo
{char name[NAME_MAX];char gender[GENDER_MAX];char tel[TEL_MAX];char addr[ADDR_MAX];int age;
}Info;//通讯录菜单
void menu();//使用顺序表的前置声明
struct SeqList;
typedef struct SeqList Contect;//通讯录里提供的操作
//通讯录的初始化和销毁
void ContectInit(Contect* pcon);
void ContectDestory(Contect* pcon);//增、删、改、查、查看通讯录
//增
void ContectAdd(Contect* pcon);//查看通讯录
void ContectShow(Contect* pcon);//查
void ContectFind(Contect* pcon);//删
void ContectDel(Contect* pcon);//改
void ContectModify(Contect* pcon);

Contect.c完整代码

#include"SeqList.h"//通讯录菜单
void menu()
{printf("******************通讯录*******************\n");printf("*********1.添加联系人 2.删除联系人*********\n");printf("*********3.修改联系人 4.查找联系人*********\n");printf("*********5.查看通讯录 0.退出通讯录*********\n");printf("*******************************************\n");
}//通讯录里提供的操作
//通讯录的初始化和销毁
void ContectInit(Contect* pcon)
{SLInit(pcon);
}
void ContectDestory(Contect* pcon)
{SLDestory(pcon);
}//增、删、改、查、查看通讯录
//增
void ContectAdd(Contect* pcon)
{//创建一个通讯录结构体用来临时存放一个人的所有信息Info info;printf("请输入联系人姓名:>");scanf("%s", info.name);printf("请输入联系人性别:>");scanf("%s", info.gender);printf("请输入联系人电话:>");scanf("%s", info.tel);printf("请输入联系人地址:>");scanf("%s", info.addr);printf("请输入联系人年龄:>");scanf("%d", &info.age);//保存到通讯录顺序表中SLPushBack(pcon, info);
}//查看通讯录
void ContectShow(Contect* pcon)
{	for (int i = 0; i < pcon->size; i++){printf("-------------------------------\n");printf("姓名:%s\n", pcon->arr[i].name);printf("性别:%s\n", pcon->arr[i].gender);printf("电话:%s\n", pcon->arr[i].tel);printf("地址:%s\n", pcon->arr[i].addr);printf("年龄:%d\n", pcon->arr[i].age);}
}//查
#include<string.h>
int FindByName(Contect* pcon, char name[])
{for (int i = 0; i < pcon->size; i++){if (strcmp(pcon->arr[i].name, name) == 0){//找到了return i;}}//没找到return -1;
}void ContectFind(Contect* pcon)
{char name[NAME_MAX];printf("请输入要查找的人名:>");scanf("%s", name);int ret = FindByName(pcon, name);if (ret < 0){printf("要查找的联系人不存在!\n");return;}//找到了,打印一下查找的联系人的信息printf("-------------------------------\n");printf("姓名:%s\n", pcon->arr[ret].name);printf("性别:%s\n", pcon->arr[ret].gender);printf("电话:%s\n", pcon->arr[ret].tel);printf("地址:%s\n", pcon->arr[ret].addr);printf("年龄:%d\n", pcon->arr[ret].age);
}//删
void ContectDel(Contect* pcon)
{//删除前先查找,找到了可以删,找不到不能删printf("请输入要删除的联系人姓名:>");char name[NAME_MAX];scanf("%s", name);int ret = FindByName(pcon, name);if (ret < 0){printf("要删除的联系人不存在!\n");return;}//执行删除操作SLErase(pcon, ret);printf("删除成功\n");
}//改
void ContectModify(Contect* pcon)
{//修改前先查找,找到了改,找不到不能改printf("请输入要修改的联系人姓名:>");char name[NAME_MAX];scanf("%s", name);int ret = FindByName(pcon, name);if (ret < 0){printf("要修改的联系人不存在!\n");return;}//执行修改操作printf("开始修改!\n");printf("请输入姓名:>");scanf("%s", pcon->arr[ret].name);printf("请输入性别:>");scanf("%s", pcon->arr[ret].gender);printf("请输入电话:>");scanf("%s", pcon->arr[ret].tel);printf("请输入地址:>");scanf("%s", pcon->arr[ret].addr);printf("请输入年龄:>");scanf("%d", &pcon->arr[ret].age);printf("联系人修改成功!\n");
}

SeqList.h完整代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contect.h"typedef Info SLDatatype;typedef struct SeqList
{SLDatatype* arr;	//存储数据的底层结构int capacity;		//记录顺序表的空间大小int size;			//有效数据个数
}SL;//初始化和销毁
void SLInit(SL* ps);
void SLDestory(SL* ps);
//void SLPrint(SL* ps);//顺序表插入数据
//从尾部插入
void SLPushBack(SL* ps, SLDatatype x);
//从头部插入
void SLPushFront(SL* ps, SLDatatype x);//顺序表删除数据
//从尾部删除
void SLPopBack(SL* ps);
//从头部删除
void SLPopFront(SL* ps);//顺序表任意位置增删数据
//指定位置前面增加数据
void SLInsert(SL* ps, int pos, SLDatatype x);
//删除指定位置数据
void SLErase(SL* ps, int pos);//在顺序表中查找x
//int SLFind(SL* ps, SLDatatype x);//在顺序表中把pos位置的数据改成x
void SLChange(SL* ps, int pos, SLDatatype x);

SeqList.c完整代码

#include"SeqList.h"//初始化和销毁	
void SLInit(SL* ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLDestory(SL* ps)
{assert(ps);if (ps->arr)//arr不是空的再释放,也可以不判断{free(ps->arr);//free空指针函数什么都不会做}	ps->arr = NULL;ps->capacity = ps->size = 0;
}//void SLPrint(SL* ps)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		printf("%d ", ps->arr[i]); 
//	}
//	printf("\n");
//}//顺序表插入数据
//判断空间是否足够,不够就扩容
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity)//空间不够时{int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//为了防止扩容失败导致数据丢失,扩容后的空间地址先不给ps->arrSLDatatype* tmp = (SLDatatype*)realloc(ps->arr, newCapacity * sizeof(SLDatatype));if (tmp == NULL)//扩容失败{printf("realloc fail!\n");exit(1);//错误退出码1}//扩容成功ps->arr = tmp;ps->capacity = newCapacity;}
}//从尾部插入
//逻辑:空间足够就直接尾插,空间不够就扩容,扩容一般是扩容当前空间的2倍
void SLPushBack(SL* ps, SLDatatype x)
{assert(ps);//判断空间够不够,不够就扩容SLCheckCapacity(ps);//走到这里时空间肯定够了,直接在后面插入数据ps->arr[ps->size++] = x;//ps->size++;
}//从头部插入
//逻辑:将所有数据向后挪一位,再在第一位插入数据
void SLPushFront(SL* ps, SLDatatype x)
{assert(ps);//判断空间够不够,不够就扩容SLCheckCapacity(ps);//此时空间够了,将所有数据往后挪一位,再放数据for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}
//在添加完元素之后一定要记得 ps->size 增加一个//顺序表删除数据
//从尾部删除
//逻辑:顺序表为空,不能执行删除,顺序表不为空直接删最后一个数据
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//数据为空报警//顺序表不为空ps->size--;//看不见最后一位等于删了最后一位
}
//从头部删除
//逻辑:顺序表为空不删,顺序表不为空将数据们往前挪一位
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//顺序表不为空for (int i = 0; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}
//在删除完数据之后也要记得减size//顺序表任意位置增删数据
//指定位置前面增加数据
void SLInsert(SL* ps, int pos, SLDatatype x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);//pos及之后的数据往后挪一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}//删除指定位置数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//pos以后的数据向前挪一位for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//在顺序表中查找x
//int SLFind(SL* ps, SLDatatype x)
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;//找到了返回下标
//		}
//	}
//	return -1;//没找到返回-1
//}//在顺序表中把pos位置的数据改成x
void SLChange(SL* ps, int pos, SLDatatype x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->arr[pos] = x;
}

        最后,这套代码是用完一次之后里面存的联系人信息就没了,这时我们可以借助文件操作函数,将数据保存下来,这样下次打开的时候还能加载出来

C语言·文件操作-CSDN博客文章浏览阅读923次,点赞24次,收藏21次。本节介绍了文件的用处,如何用文件指针打开和关闭文件,流的读写函数fgetc fputc fgets fputs fscanf fprintf fread fwrite,和字符串的的格式化输入输出函数sscanf sprintf控制文件指针实现随机读写的函数fseek ftell rewind,文件结束相关函数feof ferror,文件缓冲区的概念https://blog.csdn.net/atlanteep/article/details/134894644?spm=1001.2014.3001.5501

相关文章:

数据结构·顺序表应用

本节应用是要用顺序表实现一个通讯录&#xff0c;收录联系人的姓名、性别、电话号码、住址、年龄 ​​​​​​​ 顺序表的实现在上一节中已经完成了&#xff0c;本节的任务其实就是应用上节写出来的代码的那些接口函数功能&#xff0c;做出来一个好看的&#xff0c;可…...

第一个 OpenGL 程序:旋转的立方体(VS2022 / MFC)

文章目录 OpenGL API开发环境在 MFC 中使用 OpenGL初始化 OpenGL绘制图形重置视口大小 创建 MFC 对话框项目添加 OpenGL 头文件和库文件初始化 OpenGL画一个正方形OpenGL 坐标系改变默认颜色 重置视口大小绘制立方体使用箭头按键旋转立方体深度测试添加纹理应用纹理换一个纹理 …...

剩余银饰的重量 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 有N块二手市场收集的银饰&#xff0c;每块银饰的重量都是正整数&#xff0c;收集到的银饰会被熔化用于打造新的饰品。 每一回合&#xff0c;从中选出三块 最重的…...

redis远程连接不上解决办法

问题描述&#xff1a; redis远程服务端运行在192.168.3.90计算机上&#xff0c;客户端计算机&#xff08;ip:192.168.3.110&#xff09;通过redsi-cli.exe客户端工具连接时&#xff0c;没有反应&#xff0c;连接不上。 如图所示&#xff1a; 解决步骤&#xff1a; 步骤一&…...

利用Anaconda安装pytorch和paddle深度学习环境+pycharm安装后不能调用pytorch和paddlepaddle框架

问题现象&#xff1a; 之前安装后不能在添加pytorch和paddlepaddle框架 原因&#xff08;疑似&#xff09;&#xff1a; 在终端中显示pytorch和paddle在C盘但是安装是安装在J盘 解决办法&#xff1a; 卸载、删除文件重新安装后可以看到文件位置在J盘中 但是选择时还是显示C…...

Eclipses安装教程

一、下载开发工具包 1、开发工具包JDK 下载地址链接&#xff1a;https://www.oracle.com/cn/java/technologies/downloads/ 下载教程&#xff1a; 1&#xff09;点击链接&#xff0c;可以跳转到页面 2&#xff09;下滑页面&#xff0c;找到开发工具包 3&#xff09; 记住下载之…...

安装python版opencv的一些问题

安装python版opencv的一些问题 OpenCV是知名的开源计算机视觉算法库&#xff0c;提供了C\Python\Java版共享库。 在Python中使用OpenCV格外简单&#xff0c;一句命令就能安装&#xff0c;一行import就能引入&#xff0c;可谓是神器。然而&#xff0c;在实际使用中可能遇到一些…...

RabbitMQ入门实战

RabbitMQ 是一个开源的消息中间件&#xff0c;实现了高级消息队列协议&#xff08;AMQP&#xff09;&#xff0c;用于在分布式系统中进行消息传递。它能够在应用之间传递消息&#xff0c;解耦应用组件&#xff0c;提高系统的可伸缩性和可维护性。RabbitMQ 使用高级消息队列协议…...

vue3-模版引用ref

1. 介绍 概念&#xff1a;通过 ref标识 获取真实的 dom对象或者组件实例对象 2. 基本使用 实现步骤&#xff1a; 调用ref函数生成一个ref对象 通过ref标识绑定ref对象到标签 代码如下&#xff1a; 父组件&#xff1a; <script setup> import { onMounted, ref } …...

C# 十大排序算法

以下是常见的十大排序算法&#xff08;按照学习和实现的顺序排列&#xff09;&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;希尔排序&#xff08;Shell Sort&…...

面试之Glide如何绑定Activity的生命周期

Glide绑定Activity生命周期 Glide.with() 下面都是它的重载方法&#xff0c;Context&#xff0c;Activity&#xff0c;FragmentActivity, Fragment, android.app.Fragment fragment,View都可以作为他的参数&#xff0c;内容大同小异&#xff0c;都是先getRetriever&#xff0…...

从 fatal 错误到 sync.Map:Go中 Map 的并发策略

为什么 Go 语言在多个 goroutine 同时访问和修改同一个 map 时&#xff0c;会报出 fatal 错误而不是 panic&#xff1f;我们该如何应对 map 的数据竞争问题呢&#xff1f; 这篇文章将带你一步步了解背后的原理&#xff0c;并引出解决 map 并发问题的方案。 Map 数据竞争 首先…...

Simon算法详解

0.0 Intro 相关的算法&#xff1a; Deutsh-Jozsa算法&#xff1a; 第一个量子算法对经典算法取得指数级加速的算法 美中不足在于只能确定函数是平衡的还是非平衡的&#xff0c;无法确定函数具体的内容&#xff0c;即无法直接解出函数 Bernstein-Vazirani算法&#xff…...

jrebel IDEA 热部署

1 下载 2022.4.1 JRebel and XRebel - IntelliJ IDEs Plugin | Marketplace 2 选择下载好的zip 离线安装IDEA 插件 重启IDEA 3 打开 [Preference -> JRebel & XRebel] 菜单&#xff0c;输入 GUID address 为 https://jrebel.qekang.com/1e67ec1b-122f-4708-87d…...

pdf拆分成各个小pdf的方法

背景:由于某些缘故,一个大的pdf需要拆分成页数少的pdf,或者pdf需要去掉指定页,那么就有必要对pdf进行重新编辑,这里需要用到一个库,直接进行操作即可。 当使用Python时,可以使用PyMuPDF库来拆分PDF文件。以下是一个示例代码, import fitz # PyMuPDF def split_pdf(i…...

IntelliJ IDEA 常用快捷键一览表(通用型,提高编写速度,类结构、查找和查看源码,替换与关闭,调整格式)

文章目录 IntelliJ IDEA 常用快捷键一览表1-IDEA的日常快捷键第1组&#xff1a;通用型第2组&#xff1a;提高编写速度&#xff08;上&#xff09;第3组&#xff1a;提高编写速度&#xff08;下&#xff09;第4组&#xff1a;类结构、查找和查看源码第5组&#xff1a;查找、替换…...

MSVS C# Matlab的混合编程系列2 - 构建一个复杂(含多个M文件)的动态库:

前言: 本节我们尝试将一个有很多函数和文件的Matlab算法文件集成到C#的项目里面。 本文缩语: MT = Matlab 问题提出: 1 我们有一个比较复杂的Matlab文件: 这个MATLAB的算法,写了很多的算法函数在其他的M文件里面,这样,前面博客的方法就不够用了。会报错: 解决办法如下…...

上位机图像处理和嵌入式模块部署(qt图像处理)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多人一想到图像处理&#xff0c;本能的第一反应就是opencv&#xff0c;这也没有错。但是呢&#xff0c;这里面还是有一个问题的&#xff0c;不知…...

AI教我学编程之C#类的实例化与访问修饰符

前言 在这篇文章中&#xff0c;我将带大家深入了解C#编程语言的核心概念&#xff0c;包括类的实例化、访问修饰符的应用&#xff0c;以及C#中不同数据类型的默认值。我会通过逐步分析和具体实例&#xff0c;详细解释如何在C#中正确创建和操作对象&#xff0c;并探讨如何通过访…...

【笔记】Blender4.0建模入门-3物体的基本操作

Blender入门 ——邵发 3.1 物体的移动 演示&#xff1a; 1、选中一个物体 2、选中移动工具 3、移动 - 沿坐标轴移动 - 在坐标平面内移动 - 自由移动&#xff08;不好控制&#xff09; 选中物体&#xff1a;右上的大纲窗口&#xff0c;点击物体名称&#xff0c;物体的轮…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...