通讯录实现【C语言】

目录

前言

一、整体逻辑分析

二、实现步骤

1、创建菜单和多次操作问题

2、创建通讯录

3、初始化通讯录

4、添加联系人

5、显示联系人

6、删除指定联系人

​7、查找指定联系人

8、修改联系人信息

9、排序联系人信息

三、全部源码


前言

我们上期已经详细的介绍了自定义类型,本期我们来用学过的知识来做个小项目来练习练习。本期我们将用C语言实现通讯录静态版!后期介绍了动态内存管理和文件操作我们将会在此版本的基础上进行优化改进!

一、整体逻辑分析

我们还和以前实现三子棋和扫雷小项目一样,先对整体工程的逻辑尽可能详细的梳理,否则一开就是一顿狂敲,最后一走发现全是Bug这样就不好了!我们一开始尽可能的分析清楚,后面即使出现了问题也能快速确定!本期还是和往期一样采用多文件编程!OK,我们下面一起来梳理一下这个小项目的基本实现逻辑:

1、创建菜单和多次操作问题

2、创建通讯录

3、通讯录的初始化以及增删查改等操作

二、实现步骤

1、创建菜单和多次操作问题

我们期望当我们进行对通讯录操作时可以给我们在进行操作前给一个菜单功能我们操作!考虑到后面还要多次操作通讯录(增删查改等)我们结合起来很快想到用do..while循环处理最为合理,这里以前写过两三遍了我们直接上代码:

#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()
{int input = 0;do{menu();printf("请选择操作数:> ");scanf("%d", &input);switch (input){case 1://addbreak;case 2://delbreak;case 3://searchbreak;case 4://modifybreak;case 5://showbreak;case 6://sortbreak;case 0:printf("退出成功!\n");break;default:printf("选择数非法!\n");break;}} while (input);
}int main()
{test();return 0;
}

看效果:

2、创建通讯录

我们在对通讯录进行各种操作前先得有个通讯录吧!通讯录的本质还是描述一个人的属性例如:姓名、年龄、性别、电话、住址等!这些都是不同的类型,我们很容易想到用结构体就能解决!但这只是描述一个人,你的通讯录不可能只有一个人吧应该是有很多个!而这些联系人又是同一类型,因此采用结构体数组来创建通讯录!

typedef struct PeoInfo
{char name[20];int age;char sex[5];char tele[15];char addr[20];
}PeoInfo;

这就是描述一个人基本属性的结构体!当创建好了这个结构体后,我们就可以在test.c这个文件中do..while循环那里可以创建结构体数组来作为通讯录了!

但这样写会有个问题就是,当你存入或删除联系人后想打印出来看看是此时通讯录中的联系人时应该打印多少?我们还想不知道。所以这里我们还得再定义一个变量sz来记录通讯录的大小!

其实我们发现,sz不仅是可以记录通讯录的大小,而且增加联系人的时候只需要增加到sz位置即可,增加一个sz++,当删除一个sz--;这样其实 sz和通讯录是绑定在一起的,我们不妨在对通讯录进行一层封装,把他也封装成一个结构体,一个成员是PeoInfo结构体数组,一个是记录通讯录大小的sz:

typedef struct PeoInfo
{char name[20];int age;char sex[5];char tele[15];char addr[20];
}PeoInfo;typedef struct Contact
{PeoInfo data[100];int sz;
}Contact;

然后再在test.c文件中创建即可!

OK!这个创建通讯录记好了!其实这里还可已在稍微优化一下:我们发现两个结构体中都出现了大量的常数,我们万一后期需求有变,这些都得改!因此为了后期修改方便,我们把这些都改成#define的常量,后期修改起来容易!这里你可能会说上期不是介绍了枚举吗,这里正好是多个常量枚举不是更好吗?这里枚举确实可以达到目的,但枚举是在没开始前就能列举出来所有可能,我们这个可不是!所以,这里不用枚举!

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 20
#define MAX 100typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo data[MAX];int sz;
}Contact;

这样才是当前逻辑下的最优代码!

3、初始化通讯录

当我们创建好了通讯录后我们先对其进行一个初始化!把结构体数组的每个元素都初始化为0,通讯录大小也置为0!因为我们要改变结构体的内容所以应该传地址!我们这里采用的是memset这个函数直接初始化为0,也可以用个循环来初始化!不了解memset的点击memset

void InitContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz = 0;
}

4、添加联系人

我们前面已经说过了,只需要在sz的位置增加即可!但要考虑通讯录满的情况!

void AddContact(Contact* pc) 
{assert(pc);//通讯录已满if (pc->sz == MAX){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);pc->sz++;printf("添加成功!\n");
}

OK,我们下面先来写一个显示联系人,来验证一下是否添加成功!

5、显示联系人

显示联系人就是把通讯录中的联系人打印在控制台!

void ShowContact(Contact* pc)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");for (int i = 0; i < pc->sz; i++){printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}

OK,我们来看看是否添加成功以及显示联系人!

OK,添加联系人和显示联系人都成功了!说明我们上面逻辑没有问题!

6、删除指定联系人

我们输入要删除的人的姓名,进行查找,找到了删除,否则输出没有此联系人!注意考虑通讯录为空的情况!这里提到了查找,这个查找和通讯录的那个查找有点不一样,这个是查找后返回下标即可,那个是还要打印联系人信息功能不一样。因此我们单独在封装一个函数!

//查找要删除的人并返回下标
int FindContact(const Contact* pc, const char* name)
{for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//没找到
}//删除联系人
void DelContact(Contact* pc)
{assert(pc);//通讯录为空if (pc->sz == 0){printf("通讯录为空,无法删除!\n");return;}char name[NAME_MAX] = { 0 };printf("请输入要删除人的姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){//删除for (int i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!\n");}else{printf("没有此联系人!\n");}
}

这里要注意的是比较字符串要用strcmp,不能用 == 这个我们在字符串函数和内存函数那一期详细介绍过!另外注意删除的时候那里下标越界问题!

看效果:

 7、查找指定联系人

查找指定联系人还是先按指定方式进行查找, 找到了打印,否则输出没有此联系人!这里显示一个联系人的这个里后面修改联系人也可能要用所以我们为了方便把他封装成一个函数后面直接调用即可!


//显示单个联系人信息
void Print(const Contact* pc, int pos)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}//查找指定联系人
void Search(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("请输入要查找联系人姓名:> ");scanf("%s", name);int pos = -1;//初始化为-1表示没有此联系人for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){pos = i;//找到了break;}}if (pos != -1){Print(pc, pos);}else{printf("没有此联系人!\n");}
}

其实还可以在简洁一点,上面已经实现了FindContact我们可以用一下:

void Search(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("请输入要查找联系人姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){Print(pc, pos);}else{printf("没有此联系人!\n");}
}

看效果:

8、修改联系人信息

修改联系人信息这块就有很多可能,比如只修改一项例如名字或性别等,也有可能修改多项例如名字、年龄等,也有可能得全部修改这几种情况。当我们要修改之前群殴我们能还是期望有一个菜单供我们选择,当修改完一项后我们可能还要继续修改。基于此我们采用和test.c文件中得do...while循环+菜单!

//修改联系人信息菜单
void menu1()
{system("cls");printf("*****************************************\n");printf("********* 1. name     2. age   **********\n");printf("********* 3. sex      4. tele  **********\n");printf("********* 5. addr     6. all   **********\n");printf("********* 0. exit              **********\n");printf("*****************************************\n");
}//修改名字
void ModName(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人姓名:> ");scanf("%s", pc->data[ret].name);printf("修改成功!\n");
}//修改年龄
void ModAge(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人年龄:> ");scanf("%d", &pc->data[ret].age);printf("修改成功!\n");
}//修改性别
void ModSex(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人性别:> ");scanf("%s", &pc->data[ret].sex);printf("修改成功!\n");
}//修改电话
void ModTele(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人电话:> ");scanf("%s", &pc->data[ret].tele);printf("修改成功!\n");
}//修改住址
void ModAddr(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人住址:> ");scanf("%s", &pc->data[ret].addr);printf("修改成功!\n");
}void ModAll(Contact* pc, int ret)
{assert(pc);printf("请输入联系人姓名:> ");scanf("%s", pc->data[ret].name);printf("请输入联系人年龄:> ");scanf("%d", &pc->data[ret].age);printf("请输入联系人性别:> ");scanf("%s", pc->data[ret].sex);printf("请输入联系人电话:> ");scanf("%s", pc->data[ret].tele);printf("请输入联系人住址:> ");scanf("%s", pc->data[ret].addr);printf("修改成功!\n");
}//修改联系人
void ModContact(Contact* pc)
{assert(pc);//判断是否为空if (pc->sz == 0){printf("通讯录为空,无法修改!\n");return;}char name[NAME_MAX] = { 0 };printf("请输入要修改系人姓名:> ");scanf("%s", name);//判断是否有该联系人int ret = FindContact(pc, name);//有该联系人if (ret != -1){int n = 0;do{menu1();printf("请选择修改内容:> ");scanf("%d", &n);//修改switch (n){case 1:ModName(pc,ret);break;case 2:ModAge(pc, ret);break;case 3:ModSex(pc, ret);break;case 4:ModTele(pc, ret);break;case 5:ModAddr(pc, ret);break;case 6:ModAll(pc, ret);break;case 0:printf("修改结束!\n");break;default:printf("选择数非法!\n");break;}} while (n);}else{printf("没有此联系人!\n");}
}

看效果:(小编做了清屏)

修改前:

 修改后:

OK,还是比较成功的!我们再来进行对他实现一下排序!

9、排序联系人信息

我们上面已经实现了通讯录的增删查改的基本功能!我们想让他再有一个排序功能,比如按名字排序,或年龄排序!我们在指针进阶那块介绍过回调函数,这里我们用qsort进行对通讯录排序!我们期望还是和上面一样一开始有个菜单选择!


//排序菜单
void menu2()
{system("cls");printf("**********************************\n");printf("***** 1. name    2. age **********\n");printf("**********************************\n");
}//名字比较函数
int cmp_name(const void* str1, const void* str2)
{//return strcmp(((PeoInfo*)str1)->name, ((PeoInfo*)str2)->name);return strcmp((((Contact*)str1)->data)->name, (((Contact*)str2)->data)->name);
}//名字排序
void SortName(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
}//年龄比较函数
int cmp_age(const void* str1, const void* str2)
{//return ((PeoInfo*)str1)->age - ((PeoInfo*)str2)->age;return (((Contact*)str1)->data)->age - (((Contact*)str2)->data)->age;
}
//年龄排序
void SortAge(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
}//排序联系人信息
void SortContact(Contact* pc)
{assert(pc);//判断为空if (pc->sz == 0){printf("通讯录为空,无法排序!\n");Sleep(3000);system("cls");return;}menu2();int n = 0;printf("请选择排序方式:> ");scanf("%d", &n);//排序switch (n){case 1:SortName(pc);system("cls");printf("排序成功!\n");break;case 2:SortAge(pc);system("cls");printf("排序成功!\n");break;default:printf("选择数非法!\n");Sleep(3000);system("cls");break;}
}

看效果:

排序前(年龄):

 排序后(年龄):

排序前(名字):

 排序后(名字):

OK,实现了排序!

三、全部源码

 contact.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<windows.h>#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 15
#define ADDR_MAX 20
#define MAX 100typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char tele[TELE_MAX];char addr[ADDR_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo data[MAX];int sz;
}Contact;//初始化通讯录
void InitContact(Contact* pc);//添加联系人
void AddContact(Contact* pc);//显示联系人
void ShowContact(const Contact* pc);//删除联系人
void DelContact(Contact* pc);//查找指定联系人
void Search(const Contact* pc);//修改联系人
void ModContact(Contact* pc);//排序联系人信息
void SortContact(Contact* pc);

contact.c

#include"contact.h"//初始化通讯录
void InitContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz = 0;
}//增加联系人
void AddContact(Contact* pc) 
{assert(pc);//通讯录已满if (pc->sz == MAX){printf("通讯录已满,无法添加!\n");Sleep(2000);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);pc->sz++;printf("添加成功!\n");Sleep(1000);
}//显示联系人
void ShowContact(const Contact* pc)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");for (int i = 0; i < pc->sz; i++){printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}//查找要删除的人并返回下标
int FindContact(const Contact* pc, const char* name)
{for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//没找到
}//删除联系人
void DelContact(Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法删除!\n");Sleep(2000);return;}char name[NAME_MAX] = { 0 };printf("请输入要删除人的姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){//删除for (int i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!\n");Sleep(1000);}else{printf("没有此联系人!\n");Sleep(2000);}
}//显示单个联系人信息
void Print(const Contact* pc, int pos)
{assert(pc);printf("%-s\t%-s\t%-5s\t%-15s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");printf("%-s\t%-d\t%-5s\t%-15s\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}//查找指定联系人
void Search(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("请输入要查找联系人姓名:> ");scanf("%s", name);int pos = FindContact(pc, name);if (pos != -1){Print(pc, pos);}else{printf("没有此联系人!\n");Sleep(2000);system("cls");}
}//修改联系人信息菜单
void menu1()
{system("cls");printf("*****************************************\n");printf("********* 1. name     2. age   **********\n");printf("********* 3. sex      4. tele  **********\n");printf("********* 5. addr     6. all   **********\n");printf("********* 0. exit              **********\n");printf("*****************************************\n");
}//修改名字
void ModName(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人姓名:> ");scanf("%s", pc->data[ret].name);
}//修改年龄
void ModAge(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人年龄:> ");scanf("%d", &pc->data[ret].age);
}//修改性别
void ModSex(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人性别:> ");scanf("%s", &pc->data[ret].sex);
}//修改电话
void ModTele(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人电话:> ");scanf("%s", &pc->data[ret].tele);
}//修改住址
void ModAddr(Contact* pc, int ret)
{assert(pc);printf("请输入修改后联系人住址:> ");scanf("%s", &pc->data[ret].addr);
}void ModAll(Contact* pc, int ret)
{assert(pc);printf("请输入联系人姓名:> ");scanf("%s", pc->data[ret].name);printf("请输入联系人年龄:> ");scanf("%d", &pc->data[ret].age);printf("请输入联系人性别:> ");scanf("%s", pc->data[ret].sex);printf("请输入联系人电话:> ");scanf("%s", pc->data[ret].tele);printf("请输入联系人住址:> ");scanf("%s", pc->data[ret].addr);
}//修改联系人
void ModContact(Contact* pc)
{assert(pc);//判断是否为空if (pc->sz == 0){printf("通讯录为空,无法修改!\n");Sleep(2000);system("cls");return;}char name[NAME_MAX] = { 0 };printf("请输入要修改系人姓名:> ");scanf("%s", name);//判断是否有该联系人int ret = FindContact(pc, name);//有该联系人if (ret != -1){int n = 0;do{menu1();Print(pc, ret);printf("请选择修改内容:> ");scanf("%d", &n);//修改switch (n){case 1:ModName(pc,ret);break;case 2:ModAge(pc, ret);break;case 3:ModSex(pc, ret);break;case 4:ModTele(pc, ret);break;case 5:ModAddr(pc, ret);break;case 6:ModAll(pc, ret);break;case 0:printf("修改结束!\n");Sleep(2000);system("cls");break;default:printf("选择数非法!\n");Sleep(2000);system("cls");break;}} while (n);}else{printf("没有此联系人!\n");Sleep(2000);system("cls");}
}//排序菜单
void menu2()
{system("cls");printf("**********************************\n");printf("***** 1. name    2. age **********\n");printf("**********************************\n");
}//名字比较函数
int cmp_name(const void* str1, const void* str2)
{//return strcmp(((PeoInfo*)str1)->name, ((PeoInfo*)str2)->name);return strcmp((((Contact*)str1)->data)->name, (((Contact*)str2)->data)->name);
}//名字排序
void SortName(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
}//年龄比较函数
int cmp_age(const void* str1, const void* str2)
{//return ((PeoInfo*)str1)->age - ((PeoInfo*)str2)->age;return (((Contact*)str1)->data)->age - (((Contact*)str2)->data)->age;
}
//年龄排序
void SortAge(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
}//排序联系人信息
void SortContact(Contact* pc)
{assert(pc);//判断为空if (pc->sz == 0){printf("通讯录为空,无法排序!\n");Sleep(3000);system("cls");return;}menu2();int n = 0;printf("请选择排序方式:> ");scanf("%d", &n);//排序switch (n){case 1:SortName(pc);system("cls");printf("排序成功!\n");break;case 2:SortAge(pc);system("cls");printf("排序成功!\n");break;default:printf("选择数非法!\n");Sleep(3000);system("cls");break;}
}

test.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");
}void test()
{int input = 0;Contact con;InitContact(&con);do{menu();printf("请选择操作数:> ");scanf("%d", &input);switch (input){case 1:AddContact(&con);system("cls");break;case 2:DelContact(&con);system("cls"); break;case 3:system("cls");Search(&con);break;case 4:ModContact(&con);break;case 5:system("cls");ShowContact(&con);break;case 6:SortContact(&con);break;case 0:printf("退出成功!\n");break;default:printf("选择数非法!\n");break;}} while (input);
}int main()
{test();return 0;
}

OK,本期分享就到这里!好兄弟,我们下期再见!

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

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

相关文章

mongodb.使用自带命令工具导出导入数据

在一次数据更新中&#xff0c;同事把老数据进行了清空操作&#xff0c;但是新的逻辑数据由于某种原因&#xff08;好像是她的电脑中病毒了&#xff09;&#xff0c;一直无法正常连接数据库进行数据插入&#xff0c;然后下午2点左右要给甲方演示&#xff0c;所以要紧急恢复本地的…

于vue3+vite+element pro + pnpm开源项目

河码桌面是一个基于vue3viteelement pro pnpm 创建的monorepo项目&#xff0c;项目采用的是类操作系统的web界面&#xff0c;操作起来简单又方便&#xff0c;符合用户习惯&#xff0c;又没有操作系统的复杂&#xff01; 有两个两个分支&#xff0c;一个是web版本&#xff0c;…

机器学习深度学习——机器翻译(序列生成策略)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——seq2seq实现机器翻译&#xff08;详细实现与原理推导&#xff09; &#x1f4da;订阅专栏&#xff1a;机…

【Freertos基础入门】队列(queue)的使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、队列是什么&#xff1f;二、队列的操作二、示例代码总结 前言 本系列基于stm32系列单片机来使用freerots FreeRTOS是一个广泛使用的开源实时操作系统&…

Linux网络编程:Socket套接字编程

文章目录&#xff1a; 一&#xff1a;定义和流程分析 1.定义 2.流程分析 3.网络字节序 二&#xff1a;相关函数 IP地址转换函数inet_pton inet_ntop&#xff08;本地字节序 网络字节序&#xff09; socket函数(创建一个套接字) bind函数(给socket绑定一个服务器地址结…

企业数据库遭到360后缀勒索病毒攻击,360勒索病毒解密

在当今数字化时代&#xff0c;企业的数据安全变得尤为重要。随着数字化办公的推进&#xff0c;企业的生产运行效率得到了很大提升&#xff0c;然而针对网络安全威胁&#xff0c;企业也开始慢慢引起重视。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的服务器遭到了…

go 协程并发数控制

错误的写法&#xff1a; 这里的<-ch 是为了从channel 中读取 数据&#xff0c;为了不使channel通道被写满&#xff0c;阻塞 go 协程数的创建。但是请注意&#xff0c;go workForDraw(v, &wg) 是不阻塞后续的<-ch 执行的&#xff0c;所以就一直go workForDraw(v, &…

Find My资讯|苹果Vision Pro开发者需将设备配对 AirTag

最近苹果Vision Pro获开发者申请&#xff0c;苹果要求获批的申请者使用 Measure and Fit 应用确认合适的佩戴尺寸&#xff0c;并会根据申请者提交的信息&#xff0c;定制不同的 Vision Pro 开发者套件&#xff0c;以便于契合申请者的面部特征&#xff0c;提供更好的佩戴体验。 …

iPhone 15受益:骁龙8 Gen 3可能缺席部分安卓旗舰机

明年一批领先的安卓手机的性能可能与今年的机型非常相似。硅成本的上涨可能是原因。 你可以想象&#xff0c;2024年许多最好的手机都会在Snapdragon 8 Gen 3上运行&#xff0c;这是高通公司针对移动设备的顶级芯片系统的更新&#xff0c;尚未宣布。然而&#xff0c;来自中国的…

基于libevent的tcp服务器

libevent使用教程_evutil_make_socket_nonblocking_易方达蓝筹的博客-CSDN博客 一、准备 centos7下安装libevent库 yum install libevent yum install -y libevent-devel 二、代码 server.cpp /** You need libevent2 to compile this piece of code Please see: http://li…

多种方法实现 Nginx 隐藏式跳转(隐式URL,即浏览器 URL 跳转后保持不变)

多种方法实现 Nginx 隐藏式跳转(隐式URL,即浏览器 URL 跳转后保持不变)。 一个新项目,后端使用 PHP 实现,前端不做路由,提供一个模板,由后端路由控制。 Route::get(pages/{name}, [\App\Http\Controllers\ResourceController::class, getResourceVersion])

独立站SEO是什么意思?自主网站SEO的含义?

什么是独立站SEO优化&#xff1f;自建站搜索引擎优化是指什么&#xff1f; 独立站SEO&#xff0c;作为网络营销的重要一环&#xff0c;正在逐渐引起人们的关注。在当今数字化时代&#xff0c;独立站已经成为许多企业、个人宣传推广的首选平台之一。那么&#xff0c;究竟什么是…

【c语言】文件操作

朋友们&#xff0c;大家好&#xff0c;今天分享给大家的是文件操作的相关知识&#xff0c;跟着我一起学习吧&#xff01;&#xff01; &#x1f388;什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数据文件 程序文…

如何用输入函数为数组赋值

在编写程序时我们经常使用数组&#xff0c;而数组的大小可能是很大的但是我们并不需要为每个元素都自己赋值&#xff0c;我们可能会自定义输入数组元素个数&#xff0c;我们应该如何实现通过输入函数为数组赋值呢&#xff1f; 目录 第一种&#xff1a; 第二种&#xff1a; 第一…

Floyd(多源汇最短路)

Floyd求最短路 给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。 再给定 k 个询问&#xff0c;每个询问包含两个整数 x 和 y&#xff0c;表示查询从点 x 到点 y 的最短距离&#xff0c;如果路径不存在&#xff0c;则输出 impo…

深入理解python虚拟机:程序执行的载体——栈帧

栈帧&#xff08;Stack Frame&#xff09;是 Python 虚拟机中程序执行的载体之一&#xff0c;也是 Python 中的一种执行上下文。每当 Python 执行一个函数或方法时&#xff0c;都会创建一个栈帧来表示当前的函数调用&#xff0c;并将其压入一个称为调用栈&#xff08;Call Stac…

分布式 - 服务器Nginx:一小时入门系列之负载均衡

文章目录 1. 负载均衡2. 负载均衡策略1. 轮询策略2. 最小连接策略3. IP 哈希策略4. 哈希策略5. 加权轮询策略 1. 负载均衡 跨多个应用程序实例的负载平衡是一种常用技术&#xff0c;用于优化资源利用率、最大化吞吐量、减少延迟和确保容错配置。‎使用 nginx 作为非常有效的HT…

高速PCB设计初学者容易犯的一些错误

高速PCB设计初学者容易犯的一些错误 硬件开发人员设计PCB时&#xff0c;应力求所设计PCB满足以下条件&#xff1a; PCB应首先满足规定的电气性能指标&#xff0c;原则上时电流越大&#xff0c;走线越宽&#xff1b;电压越大&#xff0c;线与线之间的距离越大&#xff1b;PCB应…

下一代计算:嵌入AI的云/雾/边缘/量子计算

计算系统在过去几十年中推动了计算机科学的发展&#xff0c;现在已成为企业世界的核心&#xff0c;提供基于云计算、雾计算、边缘计算、无服务器计算和量子计算的服务。现代计算系统解决了现实世界中许多需要低延迟和低响应时间的问题。这有助于全球各地的青年才俊创办初创企业…

【Kubernetes】Kubernetes的Pod控制器

Pod控制器 一、Pod 控制器的概念1. Pod 控制器及其功用2. Pod 控制器有多种类型2.1 ReplicaSet2.2 Deployment2.3 DaemonSet2.4 StatefulSet2.5 Job2.6 Cronjob 3. Pod 与控制器之间的关系 二、Pod 控制器的使用1. Deployment2. SatefulSet2.1 为什么要有headless&#xff1f;2…