C语言进阶——通讯录模拟实现

🌇个人主页:_麦麦_
📚今日名言:只有走在路上,才能摆脱局限,摆脱执着,让所有的选择,探寻,猜测,想象都生机勃勃。——余秋雨《文化苦旅》

目录
一、前言
二、正文
1.大体框架
2.界面显示
3. 创建通讯录
4.初始化通讯录
5.增加联系人
6.显示联系人
7. 删除联系人
8.查找联系人
9.修改联系人
10. 排序联系人
三、结语
一、前言
在上一章的结构体的学习中,相信小伙伴们或多或少都有所收获,但是有的小伙伴可能会问,结构体到底能用来做什么呢?今天,我们就借助结构体和之前所学的知识来实现通讯录。
二、正文
1.大体框架
相信在座的小伙伴们一定有人做过类似的小游戏或项目,编程的大忌就是将所有的代码都放在同一个文件里,写的时候有多好爽快,后期对代码进行修改和维护的时候就有痛苦。这期通讯录的实现我们大致分为三个模块,一个用于测试通讯录,即对各种函数的调用【text.c】;另一个用于通讯录的实现,其中放置着通讯录功能的具体实现【contact.c】;最后一个就是函数的声明了[contact.h].
2.界面显示
就像之前的扫雷与三子棋游戏一样,这个通讯录的第一步一定是要让使用者看到通讯录的页面,继而在使用者选择之后进行下一步的操作。因而我们仍旧采取do while 循环,先将页面显示,再根据使用者的输入进行相应的操作。具体实现代码如下:
//通讯录界面显示
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");
}int main()
{ int input = 0;do{menu(); //打印菜单printf("请选择你所需的功能:");scanf("%d", &input);switch (input){case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 0:printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n");}}while (input);return 0;
}

在以上代码的逻辑下,使用者刚开始就能够看到我们设置好的界面,并进行功能的输入,如果输入为0就退出通讯录,通讯录为功能相应的数字就进行相应的功能【还未填写完整】,若为其他数字,则重新输入。
3. 创建通讯录
为了实现我们菜单中的各个功能,首先我们要有这些功能的受体——通讯录,只有创建好通讯录 ,才能进行功能的操作。在生活中,我们手机上的通讯录都存有联系人的相关信息,例如姓名,年龄,性别,手机号码等等 ,其次在后面的功能中我们还需要知道这个通讯录中联系人的数量是多少。显然,我们需要一个自定义结构变量来定义通讯录,在这个结构体中有两个变量,一个是存放联系人信息的变量,另一个是存放联系人数量的变量。而存放联系人的信息显然需要一个数组,数组的大小即对应着能存放多少联系人,而数组中的元素就是联系人的信息,这也无法用一个单一类型变量来定义,所以我们还需要额外定义一个结构体变量来代表联系人的各种信息。具体代码如下:
//结构体——联系人的信息
struct peo
{char name[20]; //姓名char sex[10]; //性别int age; //年龄 char addr[40]; //地址char tel[20]; //电话
};//结构体——通讯录
typedef struct contact
{struct peo Peo[contact_num]; //通讯录中联系人的信息int sz; //当前存放联系人的个数
}contact;
4.初始化通讯录
在通讯录的创建之后,就是对其的初始化了,为了方便,我们就都置成0就好了。
//Init_Contact——初始化通讯录void Init_Contact(contact* pc)
{pc->sz = 0;memset(pc, 0, sizeof(pc->Peo));
}
5.增加联系人
在通讯录的创建和初始化完成之后,就是通讯录功能的实现了。首先是“增加联系人”这一功能。我们先是定义一个函数,这个函数的参数就是我们的通讯录,采用传递通讯录地址的方式,返回值为空,因为我们只是对通讯录的内容进行改变,并不需要返回任何东西。然后是函数的具体实现,我们要做的是在联系人信息这一数组中添加一个联系人,并在添加之后将通讯录当前存储的联系人数量+1。此外如果通讯录已满,我们需要提醒使用者无法再添加联系人。具体代码如下:
//Add——增加联系人void Add(contact* Contact){assert(Contact);if (Contact->sz < contact_num){printf("请输入联系人的姓名:>\n");scanf("%s", (Contact->Peo[Contact->sz]).name);printf("请输入联系人的性别:>\n");scanf("%s", Contact->Peo[Contact->sz].sex);printf("请输入联系人的年龄:>\n");scanf("%d", &(Contact->Peo[Contact->sz].age));printf("请输入联系人的地址:>\n");scanf("%s", Contact->Peo[Contact->sz].addr);printf("请输入联系人的电话:>\n");scanf("%s", Contact->Peo[Contact->sz].tel);Contact->sz++;}elseprintf("通讯录已满无法添加\n");}
6.显示联系人
为了观察我们在执行增加联系人这个函数是否成功,我们接下来进行“显示联系人”这一功能的实现。同样的先是定义显示联系人这一函数,函数参数是通讯录,采取传址调用的方式,无需返回任何参数。函数的实现就是依据通讯录中所存储的联系人数量,来调用存储联系人信息的数组,并将其显示在屏幕上,为了数据显示的整齐和美观,笔者对打印的数据类型进行了小小的改善,对数据所占空间进行了设置,并将数据左对齐并在数据后输出一个水平制表符。
//Show——展示联系人void Show( const contact* Contact){assert(Contact);int pos = 0; //联系人对应下标printf("%-20s\t%-10s\t%-4s\t%-40s\t%-20s\n","姓名", "性别", "年龄", "地址", "电话");for (pos = 0; pos < Contact->sz; pos++){printf("%-20s\t%-10s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,Contact->Peo[pos].sex,Contact->Peo[pos].age,Contact->Peo[pos].addr,Contact->Peo[pos].tel);}}

7. 删除联系人
首先是“删除联系人”这一函数的定义,参数为通讯录这一结构体,采取传址调用的方式,返回参数无。继而是函数具体的实现,笔者是根据使用者所输入的所要删除联系人的姓名来找到联系人在数组中对应的下标,从而进行各项信息的删除。这里有个小技巧,无论是删除联系人,修改联系人,搜索联系人都需要在根据输入的姓名对联系人进行查找,因而我们可以将这个功能封装成一个函数,在使用这一功能的时候只需要调用就行了。具体代码实现如下:
//Find_by_name——通过姓名,找到联系人所对应的下标int Find_by_name( const contact* Contact, char *name){int i = 0;for (i = 0; i < Contact->sz; i++){if (strcmp(&(Contact->Peo[i].name),name)==0)return i;}return -1;}//Del——删除联系人void Del(contact* Contact){char name[20] = { 0 };int i = 0;printf("请输入要删除的联系人:>");scanf("%s", name);int pos = Find_by_name(Contact, &name);if (-1 == pos){printf("该联系人不存在\n");return;}else{for (i = pos; i < Contact->sz-1; i++){Contact->Peo[i] = Contact->Peo[i + 1];}Contact->sz--;}}

8.查找联系人
首先是对“查找联系人”函数的定义,函数参数为通讯录,采取传址调用的方式,返回参数为0。然后是具体功能的实现,先是根据输入的姓名查找到对应的下标,再将其显示在屏幕上。具体代码如下:
//Search——搜索联系人void Search(const contact* Contact){char name[20] = {0};printf("请输入要寻找的联系人:>");scanf("%s", name);int pos= Find_by_name(Contact, &name);if (-1==pos){printf("该联系人不存在\n");return;}else{printf("%-10s\t%-6s\t%-4s\t%-40s\t%-20s\n", "姓名", "性别", "年龄", "地址", "电话");printf("%-10s\t%-6s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,Contact->Peo[pos].sex,Contact->Peo[pos].age,Contact->Peo[pos].addr,Contact->Peo[pos].tel);} }

9.修改联系人
首先是对“修改联系人”函数的定义,函数参数为通讯录,采取传址调用的方式,返回参数为0。然后是具体功能的实现,先是根据输入的姓名查找到对应的下标,再依据添加联系人的代码实现联系人信息的修改。具体代码如下:
//Modify——修改联系人void Modify(contact* Contact){assert(Contact);char name[20] = { 0 };printf("请输入要修改的联系人\n");scanf("%s", name);int pos = Find_by_name(Contact, &name);if (-1 == pos){printf("该联系人不存在\n");return;}else{printf("请输入联系人的姓名:>\n");scanf("%s", (Contact->Peo[pos]).name);printf("请输入联系人的性别:>\n");scanf("%s", Contact->Peo[pos].sex);printf("请输入联系人的年龄:>\n");scanf("%d", &(Contact->Peo[pos].age));printf("请输入联系人的地址:>\n");scanf("%s", Contact->Peo[pos].addr);printf("请输入联系人的电话:>\n");scanf("%s", Contact->Peo[pos].tel);}}

10. 排序联系人
对联系人排序依据有很多,这里仅对联系人的年龄进行排序。采取冒泡排序的方式,冒泡排序的实现在前面的推文已经介绍过了,有兴趣的小伙伴可以康一康。https://blog.csdn.net/m0_73953114/article/details/128766018
//sort——按照年龄对联系人进行排序void sort(contact* Contact,contact* tmp){//执行冒泡排序的趟数int i = 0;for (i = 0; i < Contact->sz - 1; i++){//一趟冒泡排序中交换的次数int j = 0;for (j = 0; j < Contact->sz - 1-i; j++){if (Contact->Peo[j].age > Contact->Peo[j + 1].age){tmp->Peo[0] = Contact->Peo[j];Contact->Peo[j] = Contact->Peo[j + 1];Contact->Peo[j + 1] = tmp->Peo[0];}}}}

到这里,整个通讯录就写完了,整体的代码如下:
//main.c
#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");
}int main()
{contact Contact; //创建通讯录contact tmp;Init_Contact(&Contact); //初始化通讯录Init_Contact(&tmp); int input = 0;do{menu(); //打印菜单printf("请选择你所需的功能:");scanf("%d", &input);switch (input){case 1:Add(&Contact);break;case 2:Del(&Contact);break;case 3:Search(&Contact);break;case 4:Modify(&Contact);break;case 5:Show(&Contact);break;case 6:sort(&Contact,&tmp);break;case 0:printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n");}}while (input);return 0;
}//contact.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#define contact_num 100
#include <stdio.h>
#include <string.h>
#include <assert.h>//结构体——联系人的信息
struct peo
{char name[20]; //姓名char sex[10]; //性别int age; //年龄char addr[40]; //地址char tel[20]; //电话
};
//结构体——通讯录
typedef struct contact
{struct peo Peo[contact_num]; //通讯录中联系人的信息int sz; //当前存放联系人的个数
}contact;void Init_Contact(contact* pc); //初始化通讯录
void Add(contact* Contact); //添加联系人
void Show(const contact* Contact); //展示联系人
void Search(const contact* Contact); //搜索联系人
void Del(contact* Contact); //删除联系人
void Modify(contact* Contact); //修改联系人
void sort(contact* Contact,contact* tmp); //排序联系人——年龄//contact.c
#include "contact.h"//Init_Contact——初始化通讯录void Init_Contact(contact* pc)
{pc->sz = 0;memset(pc, 0, sizeof(pc->Peo));
}//Add——增加联系人void Add(contact* Contact){assert(Contact);if (Contact->sz < contact_num){printf("请输入联系人的姓名:>\n");scanf("%s", (Contact->Peo[Contact->sz]).name);printf("请输入联系人的性别:>\n");scanf("%s", Contact->Peo[Contact->sz].sex);printf("请输入联系人的年龄:>\n");scanf("%d", &(Contact->Peo[Contact->sz].age));printf("请输入联系人的地址:>\n");scanf("%s", Contact->Peo[Contact->sz].addr);printf("请输入联系人的电话:>\n");scanf("%s", Contact->Peo[Contact->sz].tel);Contact->sz++;}elseprintf("通讯录已满无法添加\n");}//Show——展示联系人void Show( const contact* Contact){assert(Contact);int pos = 0;printf("%-10s\t%-6s\t%-4s\t%-40s\t%-20s\n","姓名", "性别", "年龄", "地址", "电话");for (pos = 0; pos < Contact->sz; pos++){printf("%-10s\t%-6s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,Contact->Peo[pos].sex,Contact->Peo[pos].age,Contact->Peo[pos].addr,Contact->Peo[pos].tel);}}//Find_by_name——通过姓名,找到联系人所对应的下标int Find_by_name( const contact* Contact, char *name){int i = 0;for (i = 0; i < Contact->sz; i++){if (strcmp(&(Contact->Peo[i].name),name)==0)return i;}return -1;}//Search——搜索联系人void Search(const contact* Contact){char name[20] = {0};printf("请输入要寻找的联系人:>");scanf("%s", name);int pos= Find_by_name(Contact, &name);if (-1==pos){printf("该联系人不存在\n");return;}else{printf("%-10s\t%-6s\t%-4s\t%-40s\t%-20s\n", "姓名", "性别", "年龄", "地址", "电话");printf("%-10s\t%-6s\t%-4d%\t%-40s\t%-20s\n", Contact->Peo[pos].name,Contact->Peo[pos].sex,Contact->Peo[pos].age,Contact->Peo[pos].addr,Contact->Peo[pos].tel);} }//Del——删除联系人void Del(contact* Contact){char name[20] = { 0 };int i = 0;printf("请输入要删除的联系人:>");scanf("%s", name);int pos = Find_by_name(Contact, &name);if (-1 == pos){printf("该联系人不存在\n");return;}else{for (i = pos; i < Contact->sz-1; i++){Contact->Peo[i] = Contact->Peo[i + 1];}Contact->sz--;}}//Modify——修改联系人void Modify(contact* Contact){assert(Contact);char name[20] = { 0 };printf("请输入要修改的联系人\n");scanf("%s", name);int pos = Find_by_name(Contact, &name);if (-1 == pos){printf("该联系人不存在\n");return;}else{printf("请输入联系人的姓名:>\n");scanf("%s", (Contact->Peo[pos]).name);printf("请输入联系人的性别:>\n");scanf("%s", Contact->Peo[pos].sex);printf("请输入联系人的年龄:>\n");scanf("%d", &(Contact->Peo[pos].age));printf("请输入联系人的地址:>\n");scanf("%s", Contact->Peo[pos].addr);printf("请输入联系人的电话:>\n");scanf("%s", Contact->Peo[pos].tel);}}//sort——按照年龄对联系人进行排序void sort(contact* Contact,contact* tmp){//执行冒泡排序的趟数int i = 0;for (i = 0; i < Contact->sz - 1; i++){//一趟冒泡排序中交换的次数int j = 0;for (j = 0; j < Contact->sz - 1-i; j++){if (Contact->Peo[j].age > Contact->Peo[j + 1].age){tmp->Peo[0] = Contact->Peo[j];Contact->Peo[j] = Contact->Peo[j + 1];Contact->Peo[j + 1] = tmp->Peo[0];}}}}
三、结语
关于通讯录的讲解就已经全部结束了,下期我们会分享自定义类型的其他成员!
关注我 _麦麦_分享更多干货:_麦麦_的博客_CSDN博客-领域博主
大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下期见!
相关文章:
C语言进阶——通讯录模拟实现
🌇个人主页:_麦麦_ 📚今日名言:只有走在路上,才能摆脱局限,摆脱执着,让所有的选择,探寻,猜测,想象都生机勃勃。——余秋雨《文化苦旅》 目录 一、前言 二、正…...
【C#基础】C# 变量和常量的使用
序号系列文章1【C#基础】C# 程序通用结构总结2【C#基础】C# 程序基础语法解析3【C#基础】C# 数据类型总结文章目录前言一. 变量(variable)1,变量定义及初始化2,变量的类别3,接收输出变量二. 常量(constant&…...
nvm安装后出现‘node‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
出现这个问题多半是path地址不对。 打开系统环境变量。看看path里面有没有?没有的话,加上就行! 我的报错原因就是因为path里没有自动加上nvm的相关路径。 注意项: 1,在安装nvm之前,提前要把本机以前安装…...
张驰咨询:关于六西格玛,有一些常见的疑惑!
很多想要学习六西格玛的学员,经常会有这些困惑: 以前没有接触过六西格玛,需要什么基础吗?自学还是培训?哪些行业会用到六西格玛呢?学习六西格玛对以后的工作有哪些帮助?如何选择六西格玛培…...
【Vercel】教你部署imsyy/home个人主页
本篇博客教你如何部署一个自己的个人主页 项目地址:https://github.com/imsyy/home 本文首发于 慕雪的寒舍 1.fork仓库vercel部署 首先我们点击fork,将仓库复刻到自己的账户 随后进入vercel,点击dashboard-add new-project 选择你复刻的仓库…...
GeekChallenge
2.GeekChallenge 1.web 1.朋友的学妹 url:http://49.234.224.119:7413/ 右键点击查看源码,找到flagU1lDe0YxQF80c19oNExwZnVsbGxsbGx9 然后base64解码得到SYC{F1_4s_h4Lpfullllll} 2.EZwww url:http://47.100.46.169:3901/ 根据网站提示…...
Java文件IO
文章目录Java中的文件操作File常用构造方法方法文件内容的读写——数据流InputStreamFileInputStream利用Scanner进行字符读取OutputStreamPrintWriter按字符读取文件(FileReader)练习代码实例如何按字节进行数据读如何按字节进行数据写如何按字符进行数据读如何按字符进行数据…...
useSSL使用安全套接字协议(史上最全最详细)
useSSL使用安全套接字协议(史上最全最详细) SSL即为:Secure Sockets Layer 安全套接字协议。 useSSLfalse和useSSLtrue的区别: 在MySQL进行连接时: 如果MySQL的版本是5.7之后的版本必须要加上useSSLfalse,…...
面向对象复习(2)
面向对象(2) 对象与引用 java语言中除基本类型之外的变量都称之为引用类型 java中的对象时通过引用对其操作的 Car bm new Car(); 右边的new Car是以Car类为模板,调用无参构造函数,在堆空间中创建一个Car对象 左边的Car bm 在栈中创建了一个Car类型的引用变量,所谓Car的…...
python中使用numpy包的向量矩阵相乘
一直对np的线性运算不太清晰,正好上课讲到了,做一个笔记整个理解一下 1.向量和矩阵 在numpy中,一重方括号表示的是向量vector,vector没有行列的概念。二重方括号表示矩阵matrix,有行列。 代码显示如下: …...
ElasticSearch 学习(一)
目录一、Elasticsearch 简介二、Elasticsearch 发展史三、Elasticsearch 功能四、Elasticsearch 特点五、Elasticsearch 应用场景一、Elasticsearch 简介 Elasticsearch 是一个实时的分布式搜索分析引擎,它能让你以前所未有的速度和规模,去探索你的数据…...
【新】华为OD机试 - 交换字符(Python)| 刷完获取OD招聘渠道
交换字符 题目 给定一个字符串 S 变化规则: 交换字符串中任意两个不同位置的字符 M S 都是小写字符组成 1 <= S.length <= 1000 输入 一串小写字母组成的字符串 输出 按照要求变换得到最小字符串 示例一 输入 abcdef输出 abcdef示例二 输入 bcdefa输出 acde…...
手把手教你解决传说中的NPE空指针异常
1. 前言最近有好几个初学java的小伙伴,甚至是学习到了JavaWeb、框架阶段的小伙伴也跑来问壹哥,该如何解决Java中的NullPointerException空指针异常。因为NPE是初学者特别常见的典型异常,所以壹哥在这里专门写一篇文章,来手把手地教…...
【pytorch安装】conda安装pytorch无法安装cpu版本(完整解决过程)
问题描述 在安装pytorch过程中,发现最后验证torch时总是返回结果为False,结果翻上去发现自己安装的是cpu版本的。 然后又通过conda去更换不同版本尝试,发现都是cpu版本的。 问题分析 通过conda安装pytorch是从源中搜索匹配指令中的文件&am…...
云计算ACP云服务器ECS实例题库
😘作者简介:一名99年软件运维应届毕业生,正在自学云计算课程。👊宣言:人生就是B(birth)和D(death)之间的C(choise),做好每一个选择。&…...
面试题:作用域、变量提升、块级作用域、函数作用域、暂存性死区、var和let的区别
<script>var a 10;(function () {console.log(a)a 5console.log(window.a)var a 20;console.log(a)})() </script> 上述代码: 1、主要是涉及到变量提升和函数作用域,var a20这行代码会在函数作用域中提升var a 至最顶部…...
JAVA练习49-爬楼梯
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目-爬楼梯 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 2月13日练习内容…...
深兰科技机器人商丘制造基地正式投产,助力商丘经济高质量发展
2月9日,深兰科技机器人商丘制造基地投产仪式在商丘市梁园区北航创新园隆重举行。商丘市人大常委会副主任、梁园区委书记张兵,梁园区区长薛天江、河南省装备制造业协会会长张桦,河南省机器人行业协会会长王济昌,深兰科技集团董事长…...
ES倒排索引/查询、写入流程
ES学习笔记 Elasticsearch学习笔记_巨輪的博客-CSDN博客 Elasticsearch学习之图解Elasticsearch中的_source、_all、store和index属性_BUse的博客-CSDN博客 倒排索引 倒排索引:ES倒排索引底层原理及FST算法的实现过程_es fst_Elastic开源社区的博客-CSDN博客 【…...
2023软考考哪个证书好?
软考有三个级别(初级,中级和高级),这三个级别分别对应5个方向,下面这张图片呢,可以一目了然,一些小小建议!!!遵循一个原则:首先选专业对口的科目&…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

