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

【C语言进阶篇】模拟实现通讯录 (内附源码)


在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏:《C语言初阶篇》 《C语言进阶篇》

⛺️生活的理想,就是为了理想的生活!

文章目录

  • 📋 前言
  • 一 、 通讯录的简介
    • 1.1 联系人的类型定义
    • 1.2 通讯录的定义
    • 1.3 通讯录要实现的功能
  • 二 、 如何实现这些功能
    • 2.1 test.c 的实现
      • mian() 函数的实现
      • menu() 菜单函数的实现
      • test() 通讯录选择的实现
    • 2.2 Contact.h 的声明
    • 2.3 Contact.c 功能函数的定义
      • 0️⃣ 初始化通讯录
      • 1️⃣ 新增联系人的实现
      • 2️⃣ 删除联系人的实现
      • 3️⃣查询联系人的实现
      • 4️⃣ 修改联系人的实现
      • 5️⃣ 查看所有联系人
      • 6️⃣ 排序联系人
  • 三、通讯录功能的测试
      • 1️⃣ 新增联系人的测试
      • 2️⃣ 删除联系人的测试
      • 3️⃣查询联系人的测试
      • 4️⃣ 修改联系人的测试
      • 5️⃣ 查看所有联系人
      • 6️⃣ 排序联系人
  • 四、通讯录整体工程
        • test.c
        • contact.c
        • contact.h
  • 📝全篇总结

📋 前言

  🌈hello! 各位宝子们大家好啊,结构体我们都学完了,那么我们今天就来点实战把!
  ⛳️给大家现编一个通讯录,其实并不难只需要用到我们的结构体知识就可以,大家一起动动手吧!
  📚本期文章收录在《C语言进阶篇》,大家有兴趣可以看看呐
  ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!

🔥 注:结构体的文章在这里嗷!《结构体的万字解析》

一 、 通讯录的简介

通讯录大家可以说是在熟悉不过了,那么今天就来用我们所学的C语言知识实现一下。通讯录无非就是增加联系人和删除等,增删查改这些功能。>

  • 而每个 联系人 又是 不同元素 的集合
  • 这时我们的结构体就排上用场了

1.1 联系人的类型定义

既然是联系人,那么我们相信大家一定储存的都是联系人的:

  • 姓名 年龄 性别 电话 地址
  • 这些基本的元素,这些知道了我们的结构体也就可以定义了

📚 代码演示:

由于数组的数字使用起来不方便更改和没有什么特殊意义,所以我们就把这些数组可以定义的宏来。

  • 可以让数组大小更容易更改
  • 还可以让别人一眼就知道这些数字的含义
#define MAX 1000
#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;

1.2 通讯录的定义

联系人的类型我们知道了那么通讯录还不要创建嘛,首先我们需要一个数组来存放每个人的信息!和一个整形来统计我们存放了多少人。

  • 那么就用 PeoInfo data[100]来负责存放100个联系人的信息。
  • int sz,来统计存放了多少个人
  • 这里由于不知道到底存放多少个字节合适所以用宏定义一个MAX定义为100也好修改

📚 代码演示:

//通讯录的定义
#define MAX 100
typedef struct Contact
{PeoInfo data[MAX];//指向了存放数据的空间int sz;//记录当前存放的有效元素的个数
}Contact;

1.3 通讯录要实现的功能

上面我们给大家说了,通讯录的一些功能大家都清楚那么该怎么实现呢?今天就来给大家用多文件的形式一起实现一下!

  • 我们来先看一下大纲是怎么样的

在这里插入图片描述

二 、 如何实现这些功能

2.1 test.c 的实现

在这个文件里面就是我们的主文件用来负责测试和调用函数的,main()函数就在次文件里面包含着!

  • 首先、这个文件要完成菜单的选择以及测试函数的的调用
  • 二、是操作通讯的选项实现

mian() 函数的实现

main函数的功能很简单就是调用test() 函数进行测试就好了其他什么也不用干!

📚 代码演示:

int main()
{test();return 0;}

menu() 菜单函数的实现

这里做一个简易的菜单就好了,只需要让使用者知道每个选项该怎么操作就好了!

📚 代码演示:

//菜单
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");
}

test() 通讯录选择的实现

既然是通讯录的选择,那么我们一般使用的都是多分支语句 switch 所以我们这次也按照 switch 来实现每次操作的选择。

  • 由于 switch 语句里面的 1 2 3 数字的含义不是很明确
  • 所以我们使用枚举来列举一下,这样每个选项是什么意思
  • 就一目了然了

🔥 注:不会枚举的可以看看这篇文章《枚举 联合 位段》里面有详细讲解哦!一看就懂!

📚 代码演示:


//枚举选项
enum  OPTION
{EXIT,ADD,  DEL,  SEARCH,  MODIFY,  SHOW,  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:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("退出通讯录!\n");break;default:printf("输入错误请重新输入!\n");break;}} while (input);
}

2.2 Contact.h 的声明

好了主文件我们的编写完了,接下来就是对我们所调用的函数进行声明和定义。

  • 而点h 文件刚好是用来声明函数的
  • 下面我们就把需要调用的函数先声明一下后面去实现

🔥 注:由于很多头文件我们,每个文件都要调用,而Contact.h 这个文件我们也需要调用。

  • 所以就把一些都要用的声明提前写到点 h 的文件里面
  • 例如前面的声明,和宏这些放到点 h 的文件里面使用起来方便一些

📚 代码演示:

#pragma once
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX 1000
#define MAX_NAME  20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30#define DEFAULT_SZ 3
#define INC_SZ 2//联系人的类型定义
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;//枚举选项
enum  OPTION
{EXIT,ADD,  DEL,  SEARCH,  MODIFY,  SHOW,  SORT,  };
//初始化通讯录函数
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查询联系人
void SearchContact(const Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//显示所有联系人
void ShowContact(const Contact* pc);
//排序结构体
void SortContact(Contact* pc);

2.3 Contact.c 功能函数的定义

  ⛳️ 通讯录的大体框架我们都搭建起来了,接下来我们就是各种函数的实现。然后通讯录的整体工程就完成啦!

0️⃣ 初始化通讯录

这里没什么可注意的,唯一需要注意的一点就是:

  • assert()断言一下确保程序的可执行性
  • 和 结构体数组初始化要用 memset 函数初始化

📚 代码演示:

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

1️⃣ 新增联系人的实现

新增的大概思想就是根据我们的 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");
}

2️⃣ 删除联系人的实现

删除联系人怎么实现呢?这里是不是得先写一个查找函数先来找到我们需要删除联系人的下标然后再进行删除。

  • 一 、这里要注意的意思如果联系人为空就无法删除
  • 二,查找函数的实现不需要声明因为我们只需要在这一个文件下用不需要跨文件使用
  • 三 、 删除完联系人后我们需要把删除的联系人的那个节点后面的联系人都给向左填充,这样我们的通讯录才又是一个有序数组!
  • 还有一个重要的点是 删除完联系人,我们的有效人数 sz 也要减一

📚 代码演示:

// 查询联系人
int FindByName(const Contact* pc, char name[])
{//找到要删除的人int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}//删除指定联系人
void DelContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除!\n");return;}char name[MAX_NAME] = { 0 };assert(pc);//删除联系人printf("请输入要删除人的名字:>");scanf("%s", name);//查询联系人int del = FindByName(pc, name);if (del == -1){printf("要删除的人不存在,删除失败!\n");return;}int i = 0;for (i = del; i < pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!\n");
}

3️⃣查询联系人的实现

这个就比较简单了,前面我们已经简单的实现了一个查找函数用来查找下标。

  • 这里需注意的是由于我们只需要查找联系人而不用修改
  • 所以我们在接收只指针的时候要记得,使用 const 进行修饰
  • 来确保指针指向的内容不会被我们改变而引发程序错乱

📚 代码演示:

//查询联系人
void SearchContact(const Contact* pc)
{char name[MAX_NAME] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在!\n");return;}else{printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}}

4️⃣ 修改联系人的实现

修改联系人我们该怎么办呢?答案肯定还是使用下标的方法进行更改了!诶这里大家有没有发现我们查询函数的便捷性,所以像这种只要多次使用的功能一定要封装成函数。

  • 这样使用起来就会方便很多

📚 代码演示:

//修改联系人
void ModifyContact(Contact* pc)
{char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要修改的人不存在!\n");return;}else{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");return;}
}

5️⃣ 查看所有联系人

这里更加简单只需要使用循环来遍历我们的数组就可以了。

  • 而这里我们也是只访问并不修改,所以使用指针接收的时候
  • 一定要用 const 来修饰我们的指针确保指针指向的内容不会改变

📚 代码演示:

//显示所有联系人
void ShowContact(const Contact* pc)
{int i = 0;//打印列标题printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\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);}}

6️⃣ 排序联系人

这里就需要用到我们 库函数 qsort 函数一键排序了,十分的方便

  • 不会的可以去看一下博主前面的文章,看完秒会

🔥 注:文章链接在这里。《qsort的使用详解》

📚 代码演示:

int cmp(const void* p1, const void* p2)
{return  (*((PeoInfo*)p1)->name, *((PeoInfo*)p2)->name);
}//结构体比较函数
void SortContact(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);printf("已按照姓名排序成功!\n");
}

三、通讯录功能的测试

所有函数都实现了那么我们就来查看一下每个功能的是否正常呢?接下来我们就来测试一下!

1️⃣ 新增联系人的测试

  • 这里我们就可以看到新增联系人的函数实现成功了!

在这里插入图片描述

2️⃣ 删除联系人的测试

  ⛳️这里就可以看到本来我们是有3个联系人的,然后进删除选了就只剩俩个联系人了!

在这里插入图片描述

3️⃣查询联系人的测试

在这里插入图片描述

4️⃣ 修改联系人的测试

这里我们就把翠花的信息重新修改,为小美了,说明这个函数也实现了

在这里插入图片描述

5️⃣ 查看所有联系人

在这里插入图片描述

6️⃣ 排序联系人

在这里插入图片描述

四、通讯录整体工程

test.c

#define _CRT_SECURE_NO_WARNINGS 1
//实现一个通讯录
// 名字
// 年龄
// 性别
// 电话
// 地址
// 
// 通讯录的功能可以存放
//增加联系人
// 删除联系人
// 修改联系人
// 查找联系人
// 显示所有联系人
// 排序功能
//
#include <stdio.h>
#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 ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("退出通讯录!\n");break;default:printf("输入错误请重新输入!\n");break;}} while (input);
}
int main()
{test();return 0;}

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"//初始化通讯录函数
void InitContact(Contact* pc)
{assert(pc);pc->data = (PeoInfo*)malloc(DEFAULT_SZ *sizeof(PeoInfo));if (pc->data == NULL){perror("InitContact");return;}pc->sz = 0;pc->capacity = DEFAULT_SZ;}//检查容量
int  CheckCapacity(Contact* pc)
{if (pc->sz == pc->capacity){PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));if (ptr == NULL){perror("CheckCapacity");return 0;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功!\n");return 1;}}return 1;
}
//增加联系人
void AddContact(Contact* pc)
{assert(pc);CheckCapacity(pc);if (0 == CheckCapacity(pc)){return ;}else{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");}}//显示所有联系人
void ShowContact(const Contact* pc)
{int i = 0;//打印列标题printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\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);}}// 查询联系人
int FindByName(const Contact* pc, char name[])
{//找到要删除的人int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}//删除指定联系人
void DelContact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除!\n");return;}char name[MAX_NAME] = { 0 };assert(pc);//删除联系人printf("请输入要删除人的名字:>");scanf("%s", name);//查询联系人int del = FindByName(pc, name);if (del == -1){printf("要删除的人不存在,删除失败!\n");return;}int i = 0;for (i = del; i < pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!\n");
}//查询联系人
void SearchContact(const Contact* pc)
{char name[MAX_NAME] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在!\n");return;}else{printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}}//修改联系人
void ModifyContact(Contact* pc)
{char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1){printf("要修改的人不存在!\n");return;}else{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");return;}
}//
//int cmp(const void* p1, const void* p2)
//{
//	return   (((Contact*)p1)->data)->age- (((Contact*)p2)->data)->age;
//}int cmp(const void* p1, const void* p2)
{return  (*((PeoInfo*)p1)->name, *((PeoInfo*)p2)->name);
}//结构体比较函数
void SortContact(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);printf("已按照姓名排序成功!\n");
}void DestroyContact(Contact* pc)
{free(pc->data);pc->sz = 0;pc->capacity = 0;
}

contact.h

#pragma once
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX 1000
#define MAX_NAME  20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30#define DEFAULT_SZ 3
#define INC_SZ 2//联系人的类型定义
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;//枚举选项
enum  OPTION
{EXIT,ADD,  DEL,  SEARCH,  MODIFY,  SHOW,  SORT,  };//初始化通讯录函数
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查询联系人
void SearchContact(const Contact* pc);
//修改联系人
void ModifyContact(Contact* pc);
//显示所有联系人
void ShowContact(const Contact* pc);
//排序结构体
void SortContact(Contact* pc);
void DestroyContact(Contact* pc);

📝全篇总结

✅ 归纳:
好了以上就是用简易通讯录的实现是不是很有趣呢!本期只用到了指针和结构体的内容!下期给大家带来动态通讯录的改造!
  初始化通讯录
  新增联系人的实现
  删除联系人的实现
  查询联系人的实现
  修改联系人的实现
  查看所有联系人
  排序联系人
☁️ 好了把上面的知识全部掌握我相信各位铁汁们,对结构体和指针的应用更加得心应手了!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
在这里插入图片描述

相关文章:

【C语言进阶篇】模拟实现通讯录 (内附源码)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言一 、 通讯录的简介1.1 联系人的类型定义1.2 通讯录的定义1.3 通讯录要实现的功能 二 、 如何…...

Python web实战之 Django 的模板语言详解

关键词&#xff1a; Python、web开发、Django、模板语言 概要 作为 Python Web 开发的框架之一&#xff0c;Django 提供了一套完整的 MVC 模式&#xff0c;其中的模板语言为开发者提供了强大的渲染和控制前端的能力。本文介绍 Django 的模板语言。 1. Django 模板语言入门 Dj…...

使用ChatGPT编写技术文档

技术文档对于任何项目都是至关重要的&#xff0c;因为它确保所有利益相关者都在同一层面上&#xff0c;并允许有效的沟通和协作。创建详细而准确的技术文档可能既耗时又具有挑战性&#xff0c;特别是对于那些不熟悉主题或缺乏强大写作技巧的人来说。ChatGPT 是一个强大的人工智…...

Java超级玛丽小游戏制作过程讲解 第四天 创建并完成常量类03

今天继续来完成常量类。 package com.sxt;import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List;public class StaticValue {//背景public static Buff…...

webpack基础知识八:说说如何借助webpack来优化前端性能?

一、背景 随着前端的项目逐渐扩大&#xff0c;必然会带来的一个问题就是性能 尤其在大型复杂的项目中&#xff0c;前端业务可能因为一个小小的数据依赖&#xff0c;导致整个页面卡顿甚至奔溃 一般项目在完成后&#xff0c;会通过webpack进行打包&#xff0c;利用webpack对前…...

JAVA SE -- 第十五天

&#xff08;全部来自“韩顺平教育”&#xff09; 多线程 一、线程相关概念 1、程序&#xff1a;是为完成特定任务、用某种语言编写的一组指令的集合。 2、进程&#xff1a;是指运行中的程序&#xff0c;如QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程…...

macOS 环境变量加载探究

使用 macOS 安装环境&#xff0c;见到过很数种环境变量配置方法&#xff0c;每次也都是按照别人的代码&#xff0c;人家配置在哪 我就配置在哪&#xff0c;其实不太清楚有什么区别&#xff0c;决定记录下。 本机 macOS 13.3&#xff0c;从 macOS Catalina(10.15) 开始&#xf…...

在程序中如何判断该线程的线程id(get_id())的返回值是一个无效值

std::thread::id() 是std::thread::id的默认构造函数&#xff0c;它会创建一个空的std::thread::id对象。一个空的std::thread::id对象代表一个无效的线程标识符。 可以通过 std::thread::id 的成员函数 std::thread::id::operator() 来判断一个 std::thread::id 是否是一个空值…...

ffmpeg-ffplay代码架构简述

全局变量 /* Minimum SDL audio buffer size, in samples. */ // 最小音频缓冲 #define SDL_AUDIO_MIN_BUFFER_SIZE 512 /* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */ // 计算实际音频缓冲大小&#xff0c;并不需要太频繁…...

⛳ 多线程面试-什么是多线程上下文切换?

目录 ⛳ 多线程面试&#xff0d;什么是多线程上下文切换&#xff1f;&#x1f381; Java中用到的线程调度算法是什么&#xff1f;&#x1f3a8; 什么是线程饥饿 &#xff1f;你对线程优先级的理解是什么&#xff1f; ⛳ 多线程面试&#xff0d;什么是多线程上下文切换&#xff…...

vb+SQL车辆管理系统设计与实现

摘 要 随着信息时代的到来,信息高速公路的兴起,全球信息化进入了一个新的发展时期。人们越来越认识到计算机强大的信息模块处理功能,使之成为信息产业的基础和支柱。 我国经济的快速发展,汽车已经成为人们不可缺少的交通工具。对于拥有大量车辆的机关企事业来说,车辆的…...

java的枚举类

枚举类的概念和使用 1.枚举类的理解&#xff1a;类的对象只有有限个&#xff0c;确定的。我们称此为枚举类。 2.当需要定义一组常量时&#xff0c;强烈建议使用枚举类。对象便是所指的常量。 3.如果枚举类中只有一个对象&#xff0c;则可以作为单例模式的实现方式。 定义枚举类…...

基于java早餐店点餐系统源码设计与实现

摘 要 多姿多彩的世界带来了美好的生活&#xff0c;行业的发展也是形形色色的离不开技术的发展。作为时代进步的发展方面&#xff0c;信息技术至始至终都是成就行业发展的重要秘密。不论何种行业&#xff0c;大到国家、企业&#xff0c;小到团体、个人都在多方位的结合信息化技…...

ODOO16如何处理采购运输正常损耗的成本价核算?

《会计准则》规定&#xff1a;商品流通企业在采购商品过程中发生的运输费、装卸费、运输途中的合理损耗都归为采购存货成本中。 例如&#xff1a;采购A产品1000个&#xff0c;单价10元/个&#xff0c;途中运输正常损耗率是5%&#xff0c;因此实际入库是950个&#xff0c;入库金…...

【数据预测】基于白鲸优化算法BWO的VMD-KELM光伏发电功率预测 短期功率预测【Matlab代码#54】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. 白鲸优化算法BWO2. 变分模态分解VMD3. 核极限学习机KELM4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】 1. 白鲸…...

函数式编程-将过程作为返回值的应用:分步过程

之前的文章提到函数式编程的一等函数&#xff08;First-class Function&#xff09;四个性质中有“可以将过程作为返回值”这一点&#xff0c;但这一点在实际使用中不如“将过程作为参数”&#xff08;高阶函数&#xff09;用得多。本文介绍一种这个性质用于分步函数的应用。 …...

Mysql-学习笔记

文章目录 1. 数据库1.1 Mysql安装及常用代码1.2 SQL介绍1.3 SQL分类1. DDL-操作数据库&#xff0c;表2. DML-对表中的数据进行增删改3. DQL-对表中的数据进行查询条件查询模糊查询排序查询分组查询分页查询 4. DCL-对数据库进行权限控制外键约束表关系-多对多多表查询事务 1. 数…...

【雕爷学编程】Arduino动手做(187)---1.3寸OLED液晶屏模块2

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…...

Windows用户如何安装新版本cpolar内网穿透

Windows用户如何安装新版本cpolar内网穿透 文章目录 Windows用户如何安装新版本cpolar内网穿透 在科学技术高度发达的今天&#xff0c;我们身边充斥着各种电子产品&#xff0c;这些电子产品不仅为我们的工作带来极大的便利&#xff0c;也让生活变得丰富多彩。我们可以使用便携的…...

MacBookPro安装Win10,Wifi不能用了,触控板不能用了(2)

一、问题 去年在MacBookPro上装过Win10&#xff0c;当初只分配了60G空间。各方面原因需要重装系统&#xff0c;上个月装了一晚上&#xff0c;也无法连接Wifi&#xff0c;触控板只能当鼠标左键用。 后来发现是没有相关驱动造成的&#xff0c;于是从Mac系统联网找到网卡驱动&am…...

理解C++中变量的作用域

理解C中变量的作用域 常规变量&#xff08;如前面定义的所有变量&#xff09;的作用域很明确&#xff0c;只能在作用域内使用它们&#xff0c;如果您在作用域外使用它们&#xff0c;编译器将无法识别&#xff0c;导致程序无法通过编译。在作用域外面&#xff0c;变量是未定义的…...

vue+element-ui给全局请求设置一个loading样式

老项目后台管理&#xff0c;要在每个页面请求的时候都添加一个loading&#xff0c;为了统一和防止一个页面多次请求页面出现闪烁的情况同意在request.js中添加了一个全局loading。 想要的效果&#xff1a; 1.在请求的时候创建一个loading样式&#xff0c;请求结束是关闭。 2…...

传球游戏

题目描述 上体育课的时候&#xff0c;小蛮的老师经常带着同学们一起做游戏。这次&#xff0c;老师带着同学们一起做传球游戏。 游戏规则是这样的&#xff1a;n个同学站成一个圆圈&#xff0c;其中的一个同学手里拿着一个球&#xff0c;当老师吹哨子时开始传球&#xff0c;每个…...

智能卡通用安全检测指南 思度文库

范围 本标准规定了智能卡类产品进行安全性检测的一般性过程和方法。 本标准适用于智能卡安全性检测评估和认证。 规范性引用文件 下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件&#xff0c;仅注日期的版本适用于本文件。凡是不注日期的引用文件&#xff0c;…...

Maven设置阿里云路径(防止加载过慢)

<?xml version"1.0" encoding"UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding …...

JavaScript原型链污染漏洞复现与防范

目录 什么是原型链污染漏洞&#xff1f; 复现原型链污染漏洞 防范原型链污染漏洞 什么是原型链污染漏洞&#xff1f; 原型链污染是JavaScript中的一种安全漏洞&#xff0c;利用该漏洞可以修改对象的原型&#xff0c;从而影响对象及其属性的行为。攻击者可以通过修改原型链来…...

初识MySQL数据库之用户管理

目录 一、用户管理 二、用户 1. 用户信息 2. 创建用户 3. 用户登录测试 4. 删除用户 5. 设置用户远端登录 6. 修改密码 6.1 修改当前用户的密码 6.2 root用户修改指定用户的密码 三、权限 1. 数据库中的各个权限含义 2. 给用户授权 3. 查看用户拥有权限 4. 授权…...

JVM 类文件结构(class文件)

JVM 本文链接&#xff1a;https://blog.csdn.net/feather_wch/article/details/132116849 类文件结构 1、class文件的组成 无符号数&#xff1a;基本数据类型 u1 u2 u3 u4 描述 数字字符串索引引用 表&#xff1a;复合数据类型&#xff0c;无符号数 表组&#xff0c; _inf…...

PAT乙题1011

答案 #include<iostream> #include<cstdio> using namespace std; typedef long long int ll; int main() {int n,cnt1;cin >> n;while (n--){ll a, b, c; cin >> a >> b >> c;printf("Case #%d: ", cnt);a b > c ? puts(…...

【并发专题】单例模式的线程安全(进阶理解篇)

目录 背景前置知识类加载运行全过程 单例模式的实现方式一、饿汉式基本介绍源码分析 二、懒汉式基本介绍源码分析改进 三、懒汉式单例终极解决方案&#xff08;静态内部类&#xff09;&#xff08;推荐使用方案&#xff09;基本介绍源码分析 感谢 背景 最近学习了JVM之后&…...