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

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

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

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

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

                                                                                        克心守己,律己则安!

1、前言

友友们,这篇文章是基于单链表来实现通讯管理系统的,所以一定要先看完我之前写过的一篇关于单链表的实现(文章链接)的文章哦~

其实基于单链表实现通讯录的思路与基于顺讯表实现通讯录的思路是一样的,在这里我就不进行赘述了。如果还没有看过我之前写的一篇基于顺序表实现通讯录(文章链接)的宝子们一定要去看看哦~

2、各种接口的实现

以下是我们希望实现的接口~

//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//前置声明
typedef struct SListNode contact;//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;//初始化通讯录
void InitContact(contact** con);//添加通讯录数据
void AddContact(contact** con);//展示通讯录数据
void ShowContact(contact* con);//删除通讯录数据
void DelContact(contact** con);//查找通讯录数据
void FindContact(contact* con);//修改通讯录数据
void ModifyContact(contact** con);//销毁通讯录数据
void DestroyContact(contact** con);

2.1 初始化通讯录

我们希望在初始化通讯录时导入之前我们原有文件中的数据,那我们就可以进行如下的操作~

//从文件中导入原数据
void DLoadContact(contact** con)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("open fail\n");return;}PeoInfo p = { 0 };while (fread(&p, sizeof(PeoInfo),1,pf)){SListPushBack(con, p);}printf("历史数据导入成功!\n");fclose(pf);pf = NULL;
}

在初始化通讯录之后加载数据! 

//初始化通讯录
void InitContact(contact** con)
{assert(con);(*con) = NULL;DLoadContact(con);
}

2.2 添加通讯录数据

//添加通讯录数据
void AddContact(contact** con)
{assert(con);PeoInfo p = {0};printf("请输入添加联系人的姓名:");scanf("%s", p.name);printf("请输入添加联系人的性别:");scanf("%s", p.sex);printf("请输入添加联系人的年龄:");scanf("%d", &(p.age));printf("请输入添加联系人的电话:");scanf("%s", p.tel);printf("请输入添加联系人的住址:");scanf("%s", p.addr);SListPushBack(con,p);printf("\n");
}

2.3 删除通讯录数据

在查找通讯录数据之外封装一个函数(findByName)来通过名字查找联系人!

(因为我们在之后的查找和修改接口中都会用到这个方法,所以我们把它封装成一个函数方便我们后续的使用!)

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}

在原有单链表的删除指定数据的接口上进行封装(让单链表摇身一变成为通讯录!)

//删除通讯录数据
void DelContact(contact** con)
{assert(con && (*con));char name[NAME_MAX];printf("请输入你要删除的联系人的名字:");scanf("%s", name);contact* pos = findByName(*con,name);if (pos == NULL){printf("您要删除的联系人不存在!\n");return;}SListErase(con, pos);printf("删除成功!\n");
}

2.4 展示通讯录数据

遍历我们的通讯录打印信息!

//展示通讯录数据
void ShowContact(contact* con)
{assert(con);contact* cur = con;printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头while (cur){printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",cur->data.name,cur->data.sex,cur->data.age,cur->data.tel,cur->data.addr);cur = cur->next;}
}

2.5 查找通讯录数据

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}

在接口内部调用该函数! 

//查找通讯录数据
void FindContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入你要查找的联系人的名字:");scanf("%s", name);contact* ret = findByName(con, name);if (ret == NULL){printf("您要查找的联系人不存在!\n");return;}printf("找到了!\n");printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",ret->data.name,ret->data.sex,ret->data.age,ret->data.tel,ret->data.addr);
}

2.6 修改通讯录数据

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}

在接口内部调用该函数! 

//修改通讯录数据
void ModifyContact(contact** con)
{assert(con);char name[NAME_MAX];printf("请输入你要修改的联系人的名字:");scanf("%s", name);contact* ret = findByName(*con, name);if (ret == NULL){printf("您要修改的联系人不存在!\n");return;}PeoInfo p = { 0 };printf("请输入修改后联系人的姓名:");scanf("%s", p.name);printf("请输入修改后联系人的性别:");scanf("%s", p.sex);printf("请输入修改后加联系人的年龄:");scanf("%d", &(p.age));printf("请输入修改后联系人的电话:");scanf("%s", p.tel);printf("请输入修改后联系人的住址:");scanf("%s", p.addr);SListModify(ret, p);printf("修改成功!\n");
}

2.7 销毁通讯录数据

因为我们希望在退出通讯管理系统的时候可以将我们的操作都保留下来,所以我们可以对其进行文件操作!

//将输入的数据保存到文件中
void SaveContact(contact** con)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("open fail!\n");return;}contact* cur = *con;while (cur){fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);cur = cur->next;}printf("历史数据保存成功!\n");fclose(pf);pf = NULL;
}

 在销毁通讯录之前保留数据!

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

3、完整源码

SeqList.h

#pragma once//避免头文件被多次引用
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"
typedef PeoInfo SListDataType;//便于改变数据类型//定义一个结构体类型的节点
typedef struct SListNode
{SListDataType data;struct SListNode* next;//存储下一个节点的地址
}SListNode;//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x);//2. 打印单链表
void PrintSList(SListNode* phead);//3. 头插
void SListPushFront(SListNode** phead, SListDataType x);//4. 头删
void  SListPopFront(SListNode** phead);//5. 尾差
void SListPushBack(SListNode** phead, SListDataType x);//6. 尾删
void  SListPopBack(SListNode** phead);//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x);//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x);//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x);//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos);//11. 销毁单链表
void SListDestroy(SListNode** phead);

Contact.h

#define _CRT_SECURE_NO_WARNINGS//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//前置声明
typedef struct SListNode contact;//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;//初始化通讯录
void InitContact(contact** con);//添加通讯录数据
void AddContact(contact** con);//展示通讯录数据
void ShowContact(contact* con);//删除通讯录数据
void DelContact(contact** con);//查找通讯录数据
void FindContact(contact* con);//修改通讯录数据
void ModifyContact(contact** con);//销毁通讯录数据
void DestroyContact(contact** con);

SeqList.c

#include"SList.h"//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x)
{SListNode* NewNode = (SListNode*)malloc(sizeof(SListNode));//开辟空间if (NewNode == NULL)//判断空间是否开辟成功{perror("malloc fail");return NULL;}NewNode->data = x;//赋值NewNode->next = NULL;//置空return NewNode;
}#if 0
//2. 打印单链表
void PrintSList(SListNode* phead)
{if (phead == NULL){printf("NULL");//如果链表没有元素就打印NULLreturn;}SListNode* cur = phead;//循环单链表打印while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}
#endif//3. 头插
void SListPushFront(SListNode** phead, SListDataType x)
{assert(phead);SListNode* newnode = SListCreatNode(x);//创建一个新节点newnode->next = *phead;*phead = newnode;
}//4. 头删
void  SListPopFront(SListNode** phead)
{assert(phead);assert(*phead);//如果没有数据就不用头删,并报错SListNode* cur = (*phead)->next;free(*phead);*phead = cur;
}//5. 尾插
void SListPushBack(SListNode** phead, SListDataType x)
{assert(phead);if (*phead == NULL){*phead = SListCreatNode(x);//创建新节点并插入}else{SListNode* tail = *phead;while (tail->next != NULL)//找到尾节点{tail = tail->next;}tail->next = SListCreatNode(x);//创建新节点并插入}
}//6. 尾删
void  SListPopBack(SListNode** phead)
{assert(phead);assert(*phead);//链表为空就不进行尾删SListNode* tail = *phead;if (tail->next == NULL)//如果链表就只有一个元素就进行头删{SListPopFront(phead);}else{while (tail->next->next != NULL){tail = tail->next;}free(tail->next);tail->next = NULL;}
}#if 0
//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x)
{assert(phead);while (phead->next != NULL)//注意最后一个节点是没有查找的{if (phead->data == x)return phead;phead = phead->next;}if (phead->data == x)return phead;//最后一个节点没有查找elsereturn NULL;//没找到
}
#endif//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x)
{assert(pos);pos->data = x;
}//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x)
{assert(phead);assert(*phead);if (pos == *phead)//如果pos位置刚好是第一个节点就进行头插{SListPushFront(phead, x);}else{SListNode* newnode = SListCreatNode(x);SListNode* cur = *phead;while (cur->next != pos)//找到pos前一个节点{cur = cur->next;}cur->next = newnode;newnode->next = pos;}
}//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos)
{assert(phead && *phead && pos);if (pos == *phead)//如果pos位置就是第一个节点就进行头删{SListPopFront(phead);}else{SListNode* cur = *phead;while (cur->next != pos)//找到pos前一个节点{cur = cur->next;}cur->next = pos->next;free(pos);}
}//11. 销毁单链表
void SListDestroy(SListNode** phead)
{assert(*phead && phead);SListNode* cur = *phead;while (cur != NULL){SListNode* tmp = cur->next;free(cur);cur = tmp;}*phead = NULL;
}

Contact.c

#include"SList.h"//从文件中导入原数据
void DLoadContact(contact** con)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("open fail\n");return;}PeoInfo p = { 0 };while (fread(&p, sizeof(PeoInfo),1,pf)){SListPushBack(con, p);}printf("历史数据导入成功!\n");fclose(pf);pf = NULL;
}//初始化通讯录
void InitContact(contact** con)
{assert(con);(*con) = NULL;DLoadContact(con);
}//添加通讯录数据
void AddContact(contact** con)
{assert(con);PeoInfo p = {0};printf("请输入添加联系人的姓名:");scanf("%s", p.name);printf("请输入添加联系人的性别:");scanf("%s", p.sex);printf("请输入添加联系人的年龄:");scanf("%d", &(p.age));printf("请输入添加联系人的电话:");scanf("%s", p.tel);printf("请输入添加联系人的住址:");scanf("%s", p.addr);SListPushBack(con,p);printf("\n");
}//展示通讯录数据
void ShowContact(contact* con)
{assert(con);contact* cur = con;printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头while (cur){printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",cur->data.name,cur->data.sex,cur->data.age,cur->data.tel,cur->data.addr);cur = cur->next;}
}//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}//删除通讯录数据
void DelContact(contact** con)
{assert(con && (*con));char name[NAME_MAX];printf("请输入你要删除的联系人的名字:");scanf("%s", name);contact* pos = findByName(*con,name);if (pos == NULL){printf("您要删除的联系人不存在!\n");return;}SListErase(con, pos);printf("删除成功!\n");
}//查找通讯录数据
void FindContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入你要查找的联系人的名字:");scanf("%s", name);contact* ret = findByName(con, name);if (ret == NULL){printf("您要查找的联系人不存在!\n");return;}printf("找到了!\n");printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",ret->data.name,ret->data.sex,ret->data.age,ret->data.tel,ret->data.addr);
}//修改通讯录数据
void ModifyContact(contact** con)
{assert(con);char name[NAME_MAX];printf("请输入你要修改的联系人的名字:");scanf("%s", name);contact* ret = findByName(*con, name);if (ret == NULL){printf("您要修改的联系人不存在!\n");return;}PeoInfo p = { 0 };printf("请输入修改后联系人的姓名:");scanf("%s", p.name);printf("请输入修改后联系人的性别:");scanf("%s", p.sex);printf("请输入修改后加联系人的年龄:");scanf("%d", &(p.age));printf("请输入修改后联系人的电话:");scanf("%s", p.tel);printf("请输入修改后联系人的住址:");scanf("%s", p.addr);SListModify(ret, p);printf("修改成功!\n");
}//将输入的数据保存到文件中
void SaveContact(contact** con)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("open fail!\n");return;}contact* cur = *con;while (cur){fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);cur = cur->next;}printf("历史数据保存成功!\n");fclose(pf);pf = NULL;
}
//销毁通讯录数据
void DestroyContact(contact** con)
{SaveContact(con);SListDestroy(con);
}

 这里我就没有单独去写一个菜单了,本身的意义也并不大,但是如果友友们想写一个来玩一玩,可以看看我之前那篇基于顺序表实现通讯录(文章链接,那里有菜单的模版(只要改几个接口的名字就行了)~

4、 完结散花

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

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

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

我们下期不见不散~~

​​​​

相关文章:

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

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章专栏&#xff1a;C语言实战项目 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 1、前言 友友们&#xff0c;这篇文章是基于单链…...

MATLAB入门介绍

MATLAB是由MathWorks公司开发的一款专业的数学计算软件&#xff0c;主要用于算法开发、数据可视化、数据分析以及数值计算等领域。它提供了一个易于使用的环境&#xff0c;让用户可以通过矩阵计算、函数和数据绘图、用户界面的创建以及编程和文档编写来解决各种数学问题。 MATL…...

【k8s】:深入理解 Kubernetes 中的污点(Taints)与容忍度(Tolerations)

【k8s】&#xff1a;深入理解 Kubernetes 中的污点&#xff08;Taints&#xff09;与容忍度&#xff08;Tolerations&#xff09; 1、污点&#xff08;Taints&#xff09;2、容忍度&#xff08;Tolerations&#xff09;3、示例演示-测试污点的具体应用场景3.1 给节点打污点&…...

Angular 使用DomSanitizer防范跨站脚本攻击

跨站脚本Cross-site scripting 简称XSS&#xff0c;是代码注入的一种&#xff0c;是一种网站应用程序的安全漏洞攻击。它允许恶意用户将代码注入到网页上&#xff0c;其他用户在使用网页时就会收到影响&#xff0c;这类攻击通常包含了HTML和用户端脚本语言&#xff08;JS&…...

(八)PostgreSQL的数据库管理

PostgreSQL的数据库管理 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;57771 创建数据库 CREATE DATABASE创建一…...

外包干了30天,技术倒退明显

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01; 而我已经在一个企业干了四年的功能…...

ruoyi-nbcio-plus基于vue3的flowable的自定义业务单表例子的升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…...

【ENSP】华为三层交换机配置AAA认证,开启telnet服务

配置步骤 1.给交换机配置ip地址&#xff0c;以便登陆 2.配置AAA&#xff0c;用户名&#xff0c;密码&#xff0c;服务类型&#xff0c;用户权限 3.配置接入设备的数量 4.开启telnet服务 LSW2交换机配置 u t m #关闭提示 sys …...

collections模块下的Counter函数讲解

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 &#xff08;目前正在带领大家一起提升认知&#xff0c;感兴趣可以来围观一下&#xff09; &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍 ❤️感谢大家点赞&#x1f44d;&…...

HarmonyOS开发实例:【分布式邮件】

概述 基于TS扩展的声明式开发范式编程语言编写的一个分布式邮件系统&#xff0c;可以由一台设备拉起另一台设备&#xff0c;每次改动邮件内容&#xff0c;都会同步更新两台设备的信息。效果图如下&#xff1a; 搭建OpenHarmony开发环境 完成本篇Codelab我们首先要完成开发环境…...

llama2.c与chinese-baby-llama2语言模型本地部署推理

文章目录 简介Github文档克隆源码英文模型编译运行中文模型&#xff08;280M&#xff09;main函数 简介 llama2.c是一个极简的Llama 2 LLM全栈工具&#xff0c;使用一个简单的 700 行 C 文件 ( run.c ) 对其进行推理。llama2.c涉及LLM微调、模型构建、推理端末部署&#xff08…...

008、Python+fastapi,第一个后台管理项目走向第8步:ubutun 20.04下安装vscode+python环境配置

一、说明 白飘了3个月无影云电脑&#xff0c;开始选了个windows server 非常不好用&#xff0c;后台改为ubuntu想升级到22&#xff0c;没成功&#xff0c;那就20.04吧。 今天先安装下开发环境&#xff0c;后续2个月就想把他当做开发服务器&#xff0c;不知道行不行&#xff0c;…...

2024.4.16 驱动开发

思维导图...

如何在 Ubuntu 14.04 上更改 PHP 设置

简介 PHP 是一种服务器端脚本语言&#xff0c;被许多流行的 CMS 和博客平台如 WordPress 和 Drupal 所使用。它也是流行的 LAMP 和 LEMP 堆栈的一部分。更新 PHP 配置设置是设置基于 PHP 的网站时的常见任务。定位确切的 PHP 配置文件可能并不容易。通常在服务器上会有多个 PH…...

【光伏企业】光伏项目怎么做才能提高效率?

一、精细化项目管理 项目规划&#xff1a;在项目启动前&#xff0c;进行充分的调研和规划&#xff0c;明确项目的目标、规模、预算和时间表&#xff0c;确保各项资源得到合理分配。 团队建设&#xff1a;组建一支高效、专业的项目团队&#xff0c;确保团队成员具备光伏领域的…...

毕设选51还是stm32?51太简单?

如果你更倾向于挑战和深入学习&#xff0c;STM32可能是更好的选择。如果你希望更专注于底层硬件原理&#xff0c;51可能更适合。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff…...

ip addr和ifconfig区别

ip addr和ifconfig都是用于配置和管理网络接口的工具 1. ifconfig ifconfig是较旧的网络配置工具&#xff0c;属于net-tools套件的一部分。 该命令主要用于配置、显示和控制网络接口的参数&#xff0c;如IP地址、子网掩码、广播地址等。 ifconfig命令的功能相对有限&#xff…...

Springboot+Vue项目-基于Java+MySQL的房产销售系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…...

向量数据库中的向量是什么?

在向量数据库中&#xff0c;向量通常指的是高维空间中的点或方向&#xff0c;它们由一组数值组成&#xff0c;这些数值表示该点在空间中的位置或方向。在机器学习和人工智能领域&#xff0c;向量经常用于表示各种类型的数据&#xff0c;如文本、图像、音频等。 具体来说&#x…...

【重回王座】ChatGPT发布最新模型gpt-4-turbo-2024-04-09

今天&#xff0c;新版GPT-4 Turbo再次在大型模型排行榜上荣登榜首&#xff0c;成功超越了此前领先的Claude 3 Opus。另外&#xff0c;新模型在处理长达64k的上下文时&#xff0c;性能竟能够与旧版在处理26k上下文时的表现相当。 目前GPT-4 Turbo仅限于ChatGPT Plus的用户&…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...