精通C语言:打造高效便捷的通讯录管理系统

pFp8UCq.jpg

✨✨ 欢迎大家来到贝蒂大讲堂✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C语言项目
贝蒂的主页:Betty‘s blog

引言

在我们大致学习完C语言之后,我们就可以利用目前所学的知识去做一些有意思的项目,而今天贝蒂就带大家完成一个通讯录的简易实现,

本章你可能需要的知识:

  1. 动态内存的使用:动态内存管理
  2. 文件的创建与使用:文件操作

1. 通讯录要求

  1. 通讯录包括每个人的姓名,性别,年龄,电话与地址。
  2. 玩家可以自由选择通讯录的进出。
  3. 玩家可以自由增删查改通讯录中的数据。

2. 多文件管理

为了方便代码的管理和保证通讯录实现逻辑的清晰性,我们将采用多文件管理的模式。

  1. 创建头文件contact.c,包含所有头文件(其他源文件只需引用它即可),以及所有通讯录功能的展现。

  2. 创建源文件contact.c,负责通讯录所有功能的具体代码实现。

  3. 创建源文件text.c,负责展现通讯录实现的总体逻辑。

3. 通讯录的准备

3.1 预处理信息

为了方便我们后续更换通讯的信息,我们可以利用来定义通讯录的具体信息的大小。

#define MAX 100//最大人数
#define MAX_NAME 20//名字最大长度
#define MAX_SEX 5//性别最大长度
#define MAX_TELE 12//电话最大长度
#define MAX_ADDR 30//地址最大长度

3.2 结构体定义

每个人的通讯录都要包含姓名,性别,年龄,电话与地址等信息,这时就需要我们创建一个结构体来方便管理。

typedef struct PeoInfo
{char name[MAX_NAME];//名字int age;//年龄char sex[MAX_SEX];//性别char tele[MAX_TELE];//电话char addr[MAX_ADDR];//地址
}PeoInfo;

而我们需要用这个结构体创建一个大小为100的数组,并且我们还需要知道当前通讯录的大小才能进行增删查改的操作,这两者息息相关,为了简化代码和增加代码的可读性,我们可以将这两者重新定义一个结构体。

typedef struct contact
{PeoInfo data[MAX];//一百个人的数据int sz;//通讯录的大小
}contact;

4. 简易菜单

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

画面展示:

5. 通讯录具体功能

5.1 初始化

我们首先对通讯录进行初始化。

void InitContact(contact* pc)//初始化
{assert(pc);pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}

5.2 展示联系人

当用户选择5时自动展示通讯录中的用户,并且展示用户过程中需要进行对齐,便于用户观看。

void DisplayContact(contact* pc)//打印信息
{assert(pc);printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪","性别", "电话", "地址");//默认右对齐,修改为左对齐//中间也要留下足够的空间for (int i = 0; i < pc->sz; i++){printf("%-15s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}

5.3 添加联系人

用户选择1可以自由添加联系人,如果通讯录已满,则提醒用户通讯录已满,请先清理通讯录。

(1) 检查通讯录是否已满

如果通讯录满了返回0,未满则返回1。

int CheckContact(contact*pc)//检查大小
{assert(pc);if (pc->sz == 100){return 0;}return 1;
}
(2) 添加

当通讯录未满时,用户可以输入数据添加新用户。

void AddContact(contact* pc)//增加联系人
{assert(pc);int ret = CheckContact(pc);//检查是否满了if (ret == 0){printf("通讯录已满,请先清理通讯录!!\n");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].addr);printf("用户添加成功!\n");pc->sz++;
}

5.4 删除联系人

用户可以选择2清理通讯录,删除指定联系人

(1) 寻找下标

在删除指定练习人时我们需通过其姓名寻找该联系人的下标。找到返回其下标,否则返回-1、

int FindName(contact* pc, char name[])
{assert(pc&&name);for (int pos = 0; pos < pc->sz; pos++){if (strcmp(pc->data[pos].name, name) == 0){return pos;}}return -1;
}
(2) 删除

通过寻找到的下标,我们可以利用后面的数据依次覆盖来达到删除的目的。

注意:我们不能覆盖最后一个数据否则就会发生数组越界,这时我们只需减去通讯录此时的大小就好了。

void DeleteContact(contact* pc)//删除联系人
{assert(pc);assert(pc->sz >= 0);char name[MAX_NAME];printf("请输入需要删除人的姓名:> ");scanf("%s", name);int pos = FindName(pc, name);if (pos == -1){printf("通讯录中并没有这个人!!\n");return;}for (int i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];//覆盖}printf("删除成功\n");pc->sz--;
}

删除前:

删除后 :

5.5 查找联系人

通过选择3查找指定联系人,没有找到则提醒用户没有该用户,查找到就打印其信息。

void SearchContact(contact* pc)//查找联系人
{assert(pc);char name[MAX_NAME];printf("请输入需要查找人的姓名:> ");scanf("%s", name);int pos = FindName(pc, name);if (pos == -1){printf("通讯录中并没有这个人!!\n");return;}printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪","性别", "电话", "地址");printf("%-15s\t%-5d\t%-5s\t%-12s\t%-30s", pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);
}

5.6 修改联系人

我们可以通过选择4修改指定联系人的信息。

void ModifyContact(contact* pc)//修改联系人
{assert(pc);char name[MAX_NAME];printf("请输入需要修改人的姓名:> ");scanf("%s", name);int pos = FindName(pc, name);if (pos == -1){printf("通讯录中并没有这个人!!\n");return;}printf("请输入联系人的姓名:> ");scanf("%s", pc->data[pos].name);printf("请输入联系人的年龄:> ");scanf("%d", &(pc->data[pos].age));printf("请输入联系人的性别:> ");scanf("%s", pc->data[pos].sex);printf("请输入联系人的电话:> ");scanf("%s", pc->data[pos].tele);printf("请输入联系人的地址:> ");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}

修改前:

修改后:

5.7 排序联系人

我们可以选择6对通讯录进行排序,可以按照姓名,年纪,性别,电话,地址排序。

int cmp1(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
int cmp2(const void* p1, const void* p2)
{return ((PeoInfo*)p1)->age- ((PeoInfo*)p2)->age;
}
int cmp3(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->sex, ((PeoInfo*)p2)->sex);
}
int cmp4(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->tele, ((PeoInfo*)p2)->tele);
}
int cmp5(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}
void SortByName(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp1);
}
void SortByAge(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp2);
}
void SortBySex(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp3);
}
void SortByTele(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortByAddr(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortContact(contact* pc)//排序联系人
{assert(pc);printf("请选择如何排序:> ");char input[20];scanf("%s", input);if (strcmp(input, "姓名")==0){SortByName(pc);//按姓名排序}else if (strcmp(input, "年龄") == 0){SortByAge(pc);//按年龄排序}else if (strcmp(input, "性别") == 0){SortBySex(pc);//按性别排序}else if (strcmp(input, "电话") == 0){SortByTele(pc);//按电话排序}else if (strcmp(input, "地址") == 0){SortByAddr(pc);//按地址排序}else{printf("输入非法,请重新输入\n");}
}

6. 改进通讯录

6.1 动态内存开辟

上述通讯录有一个致命的缺点——通讯录大小固定,为了解决这个问题我可以使用我们前面学过的动态内存开辟

(1) 新增变量

为了方便我们知道此时的容量大小,我们将在结构体中加入新的变量。

typedef struct contact
{PeoInfo *data;//动态开辟的数据int sz;//通讯录的大小int capacity;//通讯录的容量
}contact;
(2) 初始化
void InitContact(contact* pc)//初始化
{assert(pc);pc->sz = 0;pc->data = (PeoInfo*)calloc(2, sizeof(PeoInfo));if (pc->data == NULL){perror("InitContact:");return;}pc->capacity = 2;/*memset(pc->data, 0, sizeof(pc->data));*/
}
(3) 增容

当通讯录用户数量满时增加内存空间。

void CheckCapacity(contact* pc)//增容
{if (pc->sz == pc->capacity){PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));if (tmp != NULL){pc->data = tmp;}else{perror("CheckCapacity:");return;}pc->capacity += 2;printf("增容成功\n");}
}

6.2 文件保存

我们发现每当我们关闭程序时我们写入的数据会被清空,我们要想保存上次写入的数据就应该使用文件操作

(1) 加载数据

每次初始化时就要将上次文件的数据导入进来。

void LoadContact(contact* pc)//加载上次数据
{PeoInfo tmp = { 0 };FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){return;}//读取文件,存放到通讯录while (fread(&tmp, sizeof(PeoInfo), 1, pf))//返回值为0就是遇见文件末尾{CheckCapacity(pc);pc->data[pc->sz] = tmp;pc->sz++;}fclose(pf);pf = NULL;
}
(2) 保存数据

当程序正常结束时保存数据。

void SaveContact(contact* pc)//保存数据
{FILE* pfWrite = fopen("contact.txt", "wb");if (pfWrite == NULL){perror("fopen:");return;}//写通讯录中数据到文件中int i = 0;for (i = 0; i < pc->sz; i++){fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pfWrite);}fclose(pfWrite);pfWrite = NULL;printf("保存成功\n");}

7. 通讯录逻辑的搭建

  1. 用户通过数字选择功能。
  2. 每次选择完之后返回菜单。
  3. 选择退出之后保存数据,程序结束。
enum Option//利用枚举增加代码的可读性
{EXIT,//0ADD,DEL,SEARCH,MODIFY,DISPLAY,SORT
};
void test()
{int input = 0;contact con;InitContact(&con);do{menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DeleteContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case DISPLAY:DisplayContact(&con);break;case SORT:SortContact(&con);break;case EXIT:SaveContact(&con);//退出保存数据DestroyContact(&con);break;default:printf("非法输入,请重新输入\n");break;}} while (input);
}
int main()
{test();return 0;
}

8. 完整代码

8.1 contact.h

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define MAX_NAME 20//名字最大长度
#define MAX_SEX 5//性别最大长度
#define MAX_TELE 12//电话最大长度
#define MAX_ADDR 30//地址最大长度
typedef struct PeoInfo
{char name[MAX_NAME];//名字int age;//年龄char sex[MAX_SEX];//性别char tele[MAX_TELE];//电话char addr[MAX_ADDR];//地址
}PeoInfo;
typedef struct contact
{PeoInfo *data;//动态开辟的数据int sz;//通讯录的大小int capacity;//通讯录的容量
}contact;
void InitContact(contact* pc);//初始化
void DisplayContact(contact* pc);//打印信息
void AddContact(contact* pc);//增加联系人
void DeleteContact(contact* pc);//删除联系人
void SearchContact(contact* pc);//查找联系人
void ModifyContact(contact* pc);//修改联系人
void SortContact(contact* pc);//排序联系人
void SaveContact(contact* pc);//保存数据
void DestroyContact(contact* pc);//销毁内存

8.2 contact.c

#include"contact.h"
void CheckCapacity(contact* pc)//增容
{if (pc->sz == pc->capacity){PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));if (tmp != NULL){pc->data = tmp;}else{perror("CheckCapacity:");return;}pc->capacity += 2;printf("增容成功\n");}
}
void LoadContact(contact* pc)//加载上次数据
{PeoInfo tmp = { 0 };FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){return;}//读取文件,存放到通讯录while (fread(&tmp, sizeof(PeoInfo), 1, pf))//返回值为0就是遇见文件末尾{CheckCapacity(pc);pc->data[pc->sz] = tmp;pc->sz++;}fclose(pf);pf = NULL;
}void InitContact(contact* pc)//初始化
{assert(pc);pc->sz = 0;pc->data = (PeoInfo*)calloc(2, sizeof(PeoInfo));if (pc->data == NULL){perror("InitContact:");return;}pc->capacity = 2;LoadContact(pc);/*memset(pc->data, 0, sizeof(pc->data));*/
}
void DisplayContact(contact* pc)//打印信息
{assert(pc);printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪","性别", "电话", "地址");//默认右对齐,修改为左对齐//中间也要留下足够的空间for (int i = 0; i < pc->sz; i++){printf("%-15s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}void AddContact(contact* pc)//增加联系人
{assert(pc);CheckCapacity(pc);//检查是否满了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].addr);printf("用户添加成功!\n");pc->sz++;
}
int FindName(contact* pc, char name[])
{assert(pc&&name);for (int pos = 0; pos < pc->sz; pos++){if (strcmp(pc->data[pos].name, name) == 0){return pos;}}return -1;
}
void DeleteContact(contact* pc)//删除联系人
{assert(pc);assert(pc->sz >= 0);char name[MAX_NAME];printf("请输入需要删除人的姓名:> ");scanf("%s", name);int pos = FindName(pc, name);if (pos == -1){printf("通讯录中并没有这个人!!\n");return;}for (int i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];//覆盖}printf("删除成功\n");pc->sz--;
}
void SearchContact(contact* pc)//查找联系人
{assert(pc);char name[MAX_NAME];printf("请输入需要查找人的姓名:> ");scanf("%s", name);int pos = FindName(pc, name);if (pos == -1){printf("通讯录中并没有这个人!!\n");return;}printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪","性别", "电话", "地址");printf("%-15s\t%-5d\t%-5s\t%-12s\t%-30s", pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);
}
void ModifyContact(contact* pc)//修改联系人
{assert(pc);char name[MAX_NAME];printf("请输入需要修改人的姓名:> ");scanf("%s", name);int pos = FindName(pc, name);if (pos == -1){printf("通讯录中并没有这个人!!\n");return;}printf("请输入联系人的姓名:> ");scanf("%s", pc->data[pos].name);printf("请输入联系人的年龄:> ");scanf("%d", &(pc->data[pos].age));printf("请输入联系人的性别:> ");scanf("%s", pc->data[pos].sex);printf("请输入联系人的电话:> ");scanf("%s", pc->data[pos].tele);printf("请输入联系人的地址:> ");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}
int cmp1(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
int cmp2(const void* p1, const void* p2)
{return ((PeoInfo*)p1)->age- ((PeoInfo*)p2)->age;
}
int cmp3(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->sex, ((PeoInfo*)p2)->sex);
}
int cmp4(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->tele, ((PeoInfo*)p2)->tele);
}
int cmp5(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}
void SortByName(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp1);
}
void SortByAge(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp2);
}
void SortBySex(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp3);
}
void SortByTele(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortByAddr(contact* pc)
{qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortContact(contact* pc)//排序联系人
{assert(pc);printf("请选择如何排序:> ");char input[20] = { 0 };scanf("%s", input);if (strcmp(input, "姓名")==0){SortByName(pc);//按姓名排序}else if (strcmp(input, "年龄") == 0){SortByAge(pc);//按年龄排序}else if (strcmp(input, "性别") == 0){SortBySex(pc);//按性别排序}else if (strcmp(input, "电话") == 0){SortByTele(pc);//按电话排序}else if (strcmp(input, "地址") == 0){SortByAddr(pc);//按地址排序}else{printf("输入非法,请重新输入\n");}
}
void DestroyContact(contact* pc)
{free(pc->data);pc->data= NULL;pc->capacity = 0;pc->sz = 0;printf("销毁成功\n");
}
void SaveContact(contact* pc)//保存数据
{FILE* pfWrite = fopen("contact.txt", "wb");if (pfWrite == NULL){perror("fopen:");return;}//写通讯录中数据到文件中int i = 0;for (i = 0; i < pc->sz; i++){fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pfWrite);}fclose(pfWrite);pfWrite = NULL;printf("保存成功\n");}

8.3 text.c

#include"contact.h"enum Option//利用枚举增加代码的可读性
{EXIT,//0ADD,DEL,SEARCH,MODIFY,DISPLAY,SORT
};void menu()
{printf("***********************************\n");printf("**    1.add          2.delete    **\n");printf("**    3.search       4.modify    **\n");printf("**    5.display      6.sort      **\n");printf("**             0.exit            **\n");printf("***********************************\n");
}
void test()
{int input = 0;contact con;InitContact(&con);do{menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DeleteContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case DISPLAY:DisplayContact(&con);break;case SORT:SortContact(&con);break;case EXIT:SaveContact(&con);//退出保存数据DestroyContact(&con);break;default:printf("非法输入,请重新输入\n");break;}} while (input);
}int main()
{test();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

个人 AI 的革命:Nvidia‘s Chat with RTX 深度探索

个人 AI 的革命&#xff1a;Nvidias Chat with RTX 深度探索 Nvidia 推出的 Chat with RTX 预示着个人 AI 新时代的到来。2 月 13 日&#xff0c;Nvidia 官宣了自家的 AI 聊天机器人&#xff0c;这不仅是人工智能交互的渐进式改进&#xff1b;更代表了个人如何利用自己的数据进…

EXTI外部中断

&#xff1f; 难点&#xff1a;中断向量表、看门狗、NVIC的优先级位&#xff1f;EXTI框图&#xff1f; ------------------------ 中断系统 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;--->例如&#xff1a;…

Python一级考试笔记

Python一级考试笔记【源源老师】 前置知识&#xff1a;&#xff08;了解即可&#xff09; Python常见的几种编程环境&#xff1a;IDLE&#xff08;自带&#xff09;、Visual Studio Code、Jupyter、pyCharm&#xff1b; python版本&#xff1a;python3 和 python2&#xff08;…

最适合初学者的Python入门详细攻略,一文讲清,赶紧收藏!

前言 目前python可以说是一门非常火爆的编程语言&#xff0c;应用范围也非常的广泛&#xff0c;工资也挺高&#xff0c;未来发展也极好。 Python究竟应该怎么学呢&#xff0c;我自己最初也是从零基础开始学习Python的&#xff0c;给大家分享Python的学习思路和方法。一味的买…

OpenAI Sora 初体验

OpenAI Sora 初体验 就在刚刚&#xff0c;OpenAI 再次投下一枚重磅炸弹——Sora&#xff0c;一个文本到视频生成模型。 我第一时间体验了 Sora。看过 Sora 的能力后&#xff0c;我真的印象深刻。对细节的关注、无缝的角色刻画以及生成视频的绝对质量真正将可能性提升到了一个新…

电路设计(15)——篮球赛24秒违例倒计时报警器的proteus仿真

1.设计要求 设计、制作一个篮球赛24秒违例倒计时报警器。要求&#xff1a; &#xff08;1&#xff09;具有倒计时功能。可完整实现从“24”秒开始依序倒计时并显示倒计时过程&#xff0c;显示时间间隔为1秒。 &#xff08;2&#xff09;具有消隐功能。当“24”秒倒计时…

云计算基础-云计算概念

云计算定义 云计算是一种基于互联网的计算方式&#xff0c;通过这种计算方式&#xff0c;共享的软硬件资源和信息可以按需提供给计算机和其他设备。云计算依赖资源共享以达成规模经济&#xff0c;类似基础设置(如电力网)。 云计算最基本的概念就是云加端&#xff0c;我们有一个…

网络原理(HTTP篇)

网络原理HTTP 前言HTTPHTTP的工作流程抓包工具抓取HTTP报文HTTP报文格式 请求报文具体细节首行URLURL的基本格式URL encode 方法 报头(header)HostContent-Length 和 Content-TypeUser-Agent&#xff08;UA&#xff09;RefererCookie&#xff08;重要&#xff09; 前言 如图&a…

【Linux】 Linux 小项目—— 进度条

进度条 基础知识1 \r && \n2 行缓冲区3 函数介绍 进度条实现版本 1代码实现运行效果 版本2 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 基础知识 1 \r &&a…

MessageQueue --- RabbitMQ

MessageQueue --- RabbitMQ RabbitMQ IntroRabbitMQ 核心概念RabbitMQ 分发类型Dead letter (死信)保证消息的可靠传递 RabbitMQ Intro 2007年发布&#xff0c;是一个在AMQP&#xff08;高级消息队列协议&#xff09;基础上完成的&#xff0c;可复用的企业消息系统&#xff0c;…

社区养老|社区养老服务系统|基于springboot社区养老服务系统设计与实现(源码+数据库+文档)

社区养老服务系统目录 目录 基于springboot社区养老服务系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员部分功能 &#xff08;1&#xff09; 用户管理 &#xff08;2&#xff09;服务种类管理 &#xff08;3&#xff09;社区服务管理 &#xff08…

数据恢复软件哪个好?排名前十的数据恢复软件清单!

数据已经成为我们生活中不可或缺的一部分。从珍贵的家庭照片到重要的商业文件&#xff0c;我们在智能手机、笔记本电脑和 PC 等设备上以各种形式存储数据。但是&#xff0c;由于硬件故障、软件损坏、意外删除或病毒攻击等各种原因&#xff0c;可能会发生数据丢失。这些情况可能…

大模型计算量纲

大模型计算量纲 1. 模型参数量(llama 13B为例) {"architectures": ["LLaMAForCausalLM"],"bos_token_id": 0,"eos_token_id": 1,"hidden_act": "silu","hidden_size": 5120,"intermediate_size&…

随机过程及应用学习笔记(一)概率论(概要)

概率是随机的基础&#xff0c;在【概率论&#xff08;概要&#xff09;】这个部分中仅记录学习随机过程及应用的基本定义和结果。 前言 首先&#xff0c;概率论研究的基础是概率空间。概率空间由一个样本空间和一个概率测度组成&#xff0c;样本空间包含了所有可能的结果&…

【探索Linux】—— 强大的命令行工具 P.22(POSIX信号量)

阅读导航 引言一、POSIX信号量的基本概念二、信号量的相关操作1 . 初始化信号量sem_init ( )&#xff08;1&#xff09;原型&#xff08;2&#xff09;参数&#xff08;3&#xff09;返回值&#xff08;4&#xff09;示例代码 2 . 等待信号量&#xff08;1&#xff09;sem_wait…

Linux第56步_根文件系统第3步_将busybox构建的根文件系统烧录到EMMC

1、第1次将“rootfs”打包 1)、打开第1个终端&#xff0c;准备在“mnt”目录下创建挂载目录“rootfs”&#xff1b; 输入“ls回车” 输入“cd /mnt回车” 输入“ls回车”&#xff0c;查看“mnt”目录下的文件和文件夹 输入“sudo mkdir rootfs回车”&#xff0c;在“mnt”…

如何在30天内使用python制作一个卡牌游戏

如何在30天内使用python制作一个卡牌游戏 第1-5天&#xff1a;规划和设计第6-10天&#xff1a;搭建游戏框架第11-20天&#xff1a;核心游戏机制开发第21-25天&#xff1a;游戏界面和用户体验第26-30天&#xff1a;测试和发布附加建议游戏类型游戏规则设计界面设计技术选型第6-…

Linux操作系统基础(九):Linux用户与权限

文章目录 Linux用户与权限 一、文件权限概述 二、终端命令&#xff1a;组管理 三、终端命令&#xff1a;用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…

第五节 zookeeper集群与分布式锁_2

1.分布式锁概述 1.1 什么是分布式锁 1&#xff09;要介绍分布式锁&#xff0c;首先要提到与分布式锁相对应的是线程锁。 线程锁&#xff1a;主要用来给方法、代码块加锁。当某个方法或代码使用锁&#xff0c;在同一时刻仅有一个线程执行该方法或该代码段。 线程锁只在同一J…

【LeetCode: 107. 二叉树的层序遍历 II + BFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…