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

C语言小程序:通讯录(静态版)

哈喽各位老铁们,今天给大家带来一期通讯录的静态版本的实现,何为静态版本后面会做解释,话不多说,直接开始!
关于通讯录,其实也就是类似于我们手机上的通讯录一样,有着各种各样的功能,小编来带大家实现一部分功能就好啦(1.添加联系人 2. 删除指定联系人 3.查找指定联系人 4.修改指定联系人 5.显示全部联系人 6.排序通讯录 7.清空通讯录)要实现这些功能,首先得要有一个可以存放联系人的一块空间,而要存放的联系人的个人信息有:名字、性别、年龄、电话、家庭地址。这些个人信息类型不同,大小也不同,那该如何去存放,如何查找,又该如何去修改?我们一步一步来通过代码的方式实现这些功能

1.文件的划分

在前面发布的博客中就提到过划分文件进行编写,在之前的三子棋、扫雷的代码中就是通过划分文件,每一个文件实现相对应的功能,互不干扰,那么通讯录也要使用同样的方法

头文件:Contact.h

在头文件里面主要实现函数的声明,变量的定义、头文件的包含

源文件:Contact.c

在这个源文件里面实现通讯录的实现模块

源文件:test.c

这个源文件里面实现测试通讯录相关的功能

2.通讯录

实现一个通讯录:
1.这个通讯录可以存放100个人的信息
2.每个人的信息:
名字、性别、年龄、电话、地址
3.通讯录所包含的功能
添加联系人、删除联系人、查找联系人、修改联系人、显示通讯录、排序通讯录、清空通讯录

首先我们先搭出通讯录的基本框架:

头文件:Contact.h

//头文件的包含#include <stdio.h>

源文件: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("****  7.Clear   *****    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 7://清空break;case 0:printf("退出通讯录!\n");break;default:printf("选择错误,请重新选择:>\n");break;}} while (input);return 0;
}

但是如果这样字写,在代码可读性不高,为什么呢?当代码走到switch case 语句中,这里的case1、case2...里面的1、2..都代表什么呢?就得返回到最上面重新查看,因此这里需要完善一下,我们可以使用枚举,将我们选择的全部可能型都一一列举出来,然后进行选择,就比较方便。

优化代码:

enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SORT,CLEAR
};
//枚举的可能取值默认是从0开始,在这里刚好对应菜单里面的选项
int main()
{int input = 0;do{menu();printf("请选择通讯录的功能:>");scanf("%d", &input);switch (input){case ADD://添加联系人break;case DEL://删除联系人break;case SEARCH://查找联系人break;case MODIFY://修改联系人break;case SHOW://展示break;case SORT://排序联系人break;case CLEAR://清空break;case EXIT:printf("退出通讯录!\n");break;default:printf("选择错误,请重新选择:>\n");break;}} while (input);return 0;
}

基本框架搭建好了之后,就得有一个块空间来存放我们的联系人了,而联系人的信息又有多种,因此就需要一个结构体来存放联系人的信息,这里还存在一个问题,我们存放的联系人从哪里开始存放呢?所以我们还需要一个变量来确定联系人该存放在哪里,而且每当我们存放一个联系人,这个变量就要+1,以便下一个联系人存放在上一个联系人的后面。

注:如果我们将这个结构体创建在源文件中,就得在两个源文件中都要创建,因此为了节省空间,可以直接将结构体变量创建在头文件中

头文件:Contact.h

//表示一个联系人的各种信息
typedef struct PeoInfo
{char name[20];int age;char sex[5];char tele[12];char addr[20];
}PeoInfo;//通讯录
typedef struct Contact
{PeoInfo data[100];   //用来存放100个人的信息int sz;              //记录通讯录中有效信息的个数
}Contact;
如果这样子写还是有一个弊端,如果后期要修改通讯录中存放联系人的个数和每一个联系人信息中存放的大小,所有有关的数组都得一一修改,因此我们可以直接用#define来定义大小

代码优化:

//大小的定义
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 20//表示一个联系人的各种信息
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[MAX];   //用来存放100个人的信息int sz;              //记录通讯录中有效信息的个数
}Contact;

这样子写在后期需要修改的时候就比较方便


存放联系人的空间也搭建好了,但是创建好的空间里面刚刚开始放的是什么东西呢?我们也不知道,因此我们先得给通讯录进行初始化,让里面一个联系人也没有,让标记的变量也变为0

2.1初始化通讯录

初始化通讯录我们分装一个函数:InitContact

源文件:test.c

int main()
{int input = 0;Contact con;   //创建通讯录变量//初始化通讯录InitContact(&con);  //要修改通讯录里面的内容要传递指针do{menu();printf("请选择通讯录的功能:>");scanf("%d", &input);switch (input){case ADD://添加联系人break;case DEL://删除联系人break;case SEARCH://查找联系人break;case MODIFY://修改联系人break;case SHOW://展示break;case SORT://排序联系人break;case CLEAR://清空break;case EXIT:printf("退出通讯录!\n");break;default:printf("选择错误,请重新选择:>\n");break;}} while (input);return 0;
}

头文件Contact.h

#include <string.h>
//函数的声明
//初始化通讯录
void InitContact(Contact* pc);

源文件:Contact.c

//初始化通讯录
void InitContact(Contact* pc)
{pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));//memset函数在使用时要包含头文件<string.h>
}

2.2添加联系人

初始化好通讯录的内容之后,接下来就到了我们进行通讯录功能的实现了,首先我们实现添加联系人功能,要添加联系人,我们要确定sz的大小,如果sz等于MAX了,那不就证明通讯录以及满了嘛,就再不能添加联系人了,只有sz小于MAX的时候才可以添加联系人

源文件:test.c

case ADD://添加联系人printf("添加联系人\n");AddContact(&con); //传址调用break;

头文件:Contact.h

//添加联系人
void AddContact(Contact* pc);

源文件:Contact.c

//添加联系人
void AddContact(Contact* 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++;  //每一次添加完之后sz都要++printf("添加成功\n");
}

2.3展示通讯录

要展示通讯录,可以先打印一行标题,有助于展示,打印整个通讯录就可以使用循环,设置一个循环,循环条件只要小于sz的大小就可以

源文件:test.c

case SHOW://展示ShowContact(&con);//显示通讯录不需要修改通讯录其实传值调用也可以,但是为了节省空间使用传值调用break;

头文件:Contact.h

//显示通讯录
void ShowContact(Contact* pc);

源文件:Contact.c

//显示通讯录
void ShowContact(Contact* pc)
{//先打印标题printf("%-10s %-2d %-5s %-10s %-15s\n", "名字", "年龄", "性别", "电话", "地址");int i = 0;for (i = 0; i < pc->sz; i++){printf("%-10s %-2d %-5s %-10s %-15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}
}

2.4删除联系人

要删除联系人,首先得判断这个通讯录里面有没有联系人呀,所以要先判断sz是否为0,如果为0就证明没有联系人,判断完之后,需要删除联系人,那么首先得找到所想删除的联系人的位置,然后将这个位置记录下来,通过下标的形式访问,然后进行删除,这里还要注意,如果找完了整个通讯录,没有找到与之匹配的名字,那么就没有这个人,在删除的时候就是将记录的那个位置上的人,用后面一个人的信息进行覆盖,依次类推,然后整个通讯录的总人数减1就行了

源文件:test.c

case DEL://删除联系人printf("删除联系人\n");DelContact(&con);

头文件:Contact.h

//删除联系人
void DelContact(Contact* pc);

源文件:Contact.c

//删除联系人
void DelContact(Contact* pc)
{char name[MAX_NAME] = { 0 };//判断通讯录是否为空if (0 == pc->sz){printf("通讯录为空,无法删除!\n");return;}printf("请输入你要删除联系人的姓名:>");scanf("%s", name);int i = 0;int pos = 0;for (i = 0; i < pc->sz; i++){//找到所要删除的联系人所在的位置if (0 == strcmp(pc->data[i].name, name)){pos = i;break;}}if (i == pc->sz){printf("找不到所要删除的联系人\n");return;}//进行删除for (i = pos; i < pc->sz - 1; i++) //判断条件这里所要交换的比总数少一个{pc->data[i] = pc->data[i + 1];}//删除完之后sz减一pc->sz--;printf("删除成功\n");
}

2.5查找联系人

查找联系人和删除练习人的基本步骤一样,先判断是否为空通讯录,然后进行查找,记录位置,然后打印

源文件:test.c

case SEARCH://查找联系人printf("查找联系人\n");SearchContact(&con);break;

头文件:Contact.h

//查找联系人
void SearchContact(Contact* pc);

源文件:Contact.c

//查找联系人
void SearchContact(Contact* pc)
{char name[MAX_NAME] = { 0 };if (pc->sz == 0){printf("通讯录为空,查找不到!");return;}printf("请输入你要查找联系人的姓名:>");scanf("%s", name);int i = 0;int pos = 0;for (i = 0; i < pc->sz; i++){//找到所要查找的联系人所在的位置if (0 == strcmp(pc->data[i].name, name)){pos = i;break;}}if (i == pc->sz){printf("找不到所要查找的联系人\n");return;}//打印导航栏printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");//打印数据printf("%-10s %-4d %-5s %-12s %-30s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);
}

写到这里,我们不难发现这个查找联系人的过程重复了两次,在删除联系人和查找的时候都出现了,因此我们可以简化一下代码,直接将查找的过程分装一个查找函数,然后在使用的时候代码就不显得那么冗余,每次使用查找就直接调用这个函数

代码优化:

static int FindByName(const Contact* pc, char name[]) //使用static修饰,        //只在本源文件中使用
{int i = 0;int pos = 0;for (i = 0; i < pc->sz; i++){//找到所要删除的联系人所在的位置if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1;
}//删除联系人
void DelContact(Contact* pc)
{char name[MAX_NAME] = { 0 };//判断通讯录是否为空if (0 == pc->sz){printf("通讯录为空,无法删除!\n");return;}printf("请输入你要删除联系人的姓名:>");scanf("%s", name);int pos = FindByName(pc, name);int i = 0;if (pos == -1){printf("找不到所要删除的联系人\n");return;}//进行删除for (i = pos; i < pc->sz - 1; i++) //判断条件这里所要交换的比总数少一个{pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}//查找联系人
void SearchContact(const Contact* pc) //使用const修饰更安全
{char name[MAX_NAME] = { 0 };if (pc->sz == 0){printf("通讯录为空,查找不到!");return;}printf("请输入你要查找联系人的姓名:>");scanf("%s", name);int pos = FindByName(pc, name);int i = 0;if (pos == -1){printf("找不到所要查找的联系人\n");return;}//打印导航栏printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");//打印数据printf("%-10s %-4d %-5s %-12s %-30s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);
}

2.6修改联系人

要修改联系人,首先的找到联系人的位置,然后输入信息将其修改

源文件:test.c

case MODIFY://修改联系人printf("修改联系人\n");ModifyContact(&con);break;

头文件:Contact.h

//修改联系人
void ModifyContact(Contact* pc);

源文件:Contact.c

//修改联系人
void menu1()
{printf("**********************************\n");printf("******1.姓名*********2.年龄*******\n");printf("******3.性别*********4.电话*******\n");printf("*************5.地址***************\n");printf("**********************************\n");
}
void ModifyContact(Contact* pc)
{int input = 0;char name[MAX_NAME] = { 0 };printf("请输入你要修改的联系人姓名:>");scanf("%s", name);//查找int pos = FindByName(pc, name);int i = 0;if (pos == -1){printf("找不到所要查找的联系人\n");return;}//修改printf("请输入要修改的具体信息:>\n");menu1();scanf("%d", &input);switch (input){case 1:printf("请输入新的姓名:>");scanf("%s", pc->data[pos].name);break;case 2:printf("请输入新的年龄:>");scanf("%d", &pc->data[pos].age);break;case 3:printf("请输入新的性别:>");scanf("%s", pc->data[pos].sex);break;case 4:printf("请输入新的电话:>");scanf("%s", pc->data[pos].tele);break;case 5:printf("请输入新的地址:>");scanf("%s", pc->data[pos].addr);break;default:printf("输入有误,修改失败\n");return;}printf("修改成功\n");
}

2.7排序联系人

要排序联系人,也就意味着要排序结构体成员,就需要用到qsort排序,如果不清楚可以点击查看->qsort排序详解

源文件:test.c

case SORT://排序联系人SortContact(&con);break;

头文件:Contcat.h

#include <stdlib.h>
//排序联系人
void SortContact(Contact* pc);

源文件:Contact.c

void menu2()
{printf("***************************\n");printf("******** 1.NAME  **********\n");printf("******** 2.AGE   **********\n");printf("***************************\n");
}//按照名字排序
int cmp_byname(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}//按照年龄来排序
int cmp_byage(const void* p1, const void* p2)
{return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}//排序联系人
void SqrtContact(Contact* pc)
{int input = 0;if (pc->sz == 0){printf("通讯录没有联系人,无法排序!\n");return;}menu2();printf("请选择排序的对象:>");scanf("%d", &input);switch (input){case 1:qsort(pc, pc->sz, sizeof(PeoInfo), cmp_byname);break;case 2:qsort(pc, pc->sz, sizeof(PeoInfo), cmp_byage);break;}printf("排序成功\n");//排序成功之后打印一下ShowContact(pc);
}

2.8清空联系人

清空联系人本质上就是再将通讯录初始化,我们只需要再进行调用初始化函数就可以了

源文件:test.c

case CLEAR://清空联系人ClearContact(&con);break;

头文件:Contact.h

//清空联系人
void ClearContact(Contact* pc);

源文件:Contact.c

//清空联系人
void ClearContact(Contact* pc)
{//初始化通讯录InitContact(pc);printf("清空成功\n");//初始完之后再打印ShowContact(pc);
}

3.完整代码

头文件:Contact.h

#pragma once//头文件的包含#include <stdio.h>
#include <string.h>
#include <stdlib.h>//大小的定义
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 20//表示一个联系人的各种信息
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[MAX];   //用来存放100个人的信息int sz;              //记录通讯录中有效信息的个数
}Contact;//函数的声明
//初始化通讯录
void InitContact(Contact* pc);//添加联系人
void AddContact(Contact* pc);//显示通讯录
void ShowContact(const Contact* pc);//删除联系人
void DelContact(Contact* pc);//查找联系人
void SearchContact(const Contact* pc);//修改联系人
void ModifyContact(Contact* pc);//排序联系人
void SqrtContact(Contact* pc);//清空联系人
void ClearContact(Contact* pc);

源文件:test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "Contact.h"//测试通讯录相关的功能void menu()
{printf("**************************************\n");printf("****  1.Add     *****    2.Del    ****\n");printf("****  3.Search  *****    4.Modify ****\n");printf("****  5.Show    *****    6.Sqrt   ****\n");printf("****  7.Clear   *****    0.Exit   ****\n");printf("**************************************\n");
}enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SHOW,SQRT,CLEAR
};int main()
{int input = 0;Contact con;   //创建通讯录变量//初始化通讯录InitContact(&con);  //要修改通讯录里面的内容要传递指针do{menu();printf("请选择通讯录的功能:>");scanf("%d", &input);switch (input){case ADD://添加联系人printf("添加联系人\n");AddContact(&con); //传址调用break;case DEL://删除联系人printf("删除联系人\n");DelContact(&con);break;case SEARCH://查找联系人printf("查找联系人\n");SearchContact(&con);break;case MODIFY://修改联系人printf("修改联系人\n");ModifyContact(&con);break;case SHOW://展示ShowContact(&con);//显示通讯录不需要修改通讯录其实传值调用也可以,但是为了节省空间使用传值调用break;case SQRT://排序联系人SqrtContact(&con);break;case CLEAR://清空联系人ClearContact(&con);break;case EXIT:printf("退出通讯录!\n");break;default:printf("选择错误,请重新选择:>\n");break;}} while (input);return 0;
}

源文件:Contact.c

#define _CRT_SECURE_NO_WARNINGS 1#include "Contact.h"
//通讯录的实现模块//初始化通讯录
void InitContact(Contact* pc)
{pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}//添加联系人
void AddContact(Contact* 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++;  //每一次添加完之后sz都要++printf("添加成功\n");
}//显示通讯录
void ShowContact(const Contact* pc)
{printf("%-10s %-4s %-5s %-12s %-15s\n", "名字", "年龄", "性别", "电话", "地址");int i = 0;for (i = 0; i < pc->sz; i++){printf("%-10s %-4d %-5s %-12s %-15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);}
}//查找
static int FindByName(const Contact* pc, char name[])
{int i = 0;int pos = 0;for (i = 0; i < pc->sz; i++){//找到所要联系人所在的位置if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1;
}
//删除联系人
void DelContact(Contact* pc)
{char name[MAX_NAME] = { 0 };//判断通讯录是否为空if (0 == pc->sz){printf("通讯录为空,无法删除!\n");return;}printf("请输入你要删除联系人的姓名:>");scanf("%s", name);int pos = FindByName(pc, name);int i = 0;if (pos == -1){printf("找不到所要删除的联系人\n");return;}//进行删除for (i = pos; 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 };if (pc->sz == 0){printf("通讯录为空,查找不到!");return;}printf("请输入你要查找联系人的姓名:>");scanf("%s", name);int pos = FindByName(pc, name);int i = 0;if (pos == -1){printf("找不到所要查找的联系人\n");return;}//打印导航栏printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");//打印数据printf("%-10s %-4d %-5s %-12s %-30s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);
}//修改联系人
void menu1()
{printf("*********************************\n");printf("******1.姓名*********2.年龄*******\n");printf("******3.性别*********4.电话*******\n");printf("*************5.地址**************\n");printf("*********************************\n");
}
void ModifyContact(Contact* pc)
{int input = 0;char name[MAX_NAME] = { 0 };printf("请输入你要修改的联系人姓名:>");scanf("%s", name);//查找int pos = FindByName(pc, name);int i = 0;if (pos == -1){printf("找不到所要查找的联系人\n");return;}//修改printf("请输入要修改的具体信息:>\n");menu1();scanf("%d", &input);switch (input){case 1:printf("请输入新的姓名:>");scanf("%s", pc->data[pos].name);break;case 2:printf("请输入新的年龄:>");scanf("%d", &pc->data[pos].age);break;case 3:printf("请输入新的性别:>");scanf("%s", pc->data[pos].sex);break;case 4:printf("请输入新的电话:>");scanf("%s", pc->data[pos].tele);break;case 5:printf("请输入新的地址:>");scanf("%s", pc->data[pos].addr);break;default:printf("输入有误,修改失败\n");return;}printf("修改成功\n");
}void menu2()
{printf("***************************\n");printf("******** 1.NAME  **********\n");printf("******** 2.AGE   **********\n");printf("***************************\n");
}//按照名字排序
int cmp_byname(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}//按照年龄来排序
int cmp_byage(const void* p1, const void* p2)
{return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}//排序联系人
void SqrtContact(Contact* pc)
{int input = 0;if (pc->sz == 0){printf("通讯录没有联系人,无法排序!\n");return;}menu2();printf("请选择排序的对象:>");scanf("%d", &input);switch (input){case 1:qsort(pc, pc->sz, sizeof(PeoInfo), cmp_byname);break;case 2:qsort(pc, pc->sz, sizeof(PeoInfo), cmp_byage);break;}printf("排序成功\n");//排序成功之后打印一下ShowContact(pc);
}//清空联系人
void ClearContact(Contact* pc)
{//初始化通讯录InitContact(pc);printf("清空成功\n");//初始完之后再打印ShowContact(pc);
}

关于通讯录的代码就展现在这里了,但是这只是静态版本,还有很多的不足,当退出程序后下一次再进入程序我们之前的信息就回收了,还有各个数组的大小都是固定的,没办法随时随地的变化,在后面也会补发上关于通讯录的动态版本的代码,最后感谢大家的支持!谢谢

相关文章:

C语言小程序:通讯录(静态版)

哈喽各位老铁们&#xff0c;今天给大家带来一期通讯录的静态版本的实现&#xff0c;何为静态版本后面会做解释&#xff0c;话不多说&#xff0c;直接开始&#xff01;关于通讯录&#xff0c;其实也就是类似于我们手机上的通讯录一样&#xff0c;有着各种各样的功能&#xff0c;…...

写CSDN博客两年半的收获--总结篇

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;练习时长两年半的java博主 &#x1f39f;️个人主页&#xff1a;君临๑ ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 不知不觉间&#xff0c;在csdn写博客也有两年半的时间了&#x…...

中科亿海微FPGA应用(一、点灯)

1.软件&#xff1a; https://download.csdn.net/download/weixin_41784968/87564071 需要申请license才能使用&#xff1a;软件试用申请_软件试用申请_中科亿海微电子科技&#xff08;苏州&#xff09;有限公司 2.开发板&#xff1a; 芯片EQ6HL45&#xff0c;42.5k LUT。 3…...

ElasticSearch - SpringBoot整合ES:实现搜索结果排序 sort

文章目录00. 数据准备01. Elasticsearch 默认的排序方式是什么&#xff1f;02. Elasticsearch 支持哪些排序方式&#xff1f;03. ElasticSearch 如何指定排序方式&#xff1f;04. ElasticSearch 如何按照相关性排序&#xff1f;05. ElasticSearch 查询结果如何不按照相关性排序…...

IDEA的全新UI可以在配置里启用了,快来试试吧!

刚看到IDEA官方昨天发了这样一条推&#xff1a;IDEA的新UI可以在2022.3版本上直接使用了&#xff01;开启方法如下&#xff1a;打开IDEA的Setting界面&#xff0c;在Appearance & Behavior下有个被标注为Beta标签的New UI菜单&#xff0c;具体如下图&#xff1a;勾选Enable…...

第九章 镜像架构和规划 - 备份处于活动状态时自动进行故障转移

文章目录第九章 镜像架构和规划 - 备份处于活动状态时自动进行故障转移备份处于活动状态时自动进行故障转移备份不活动时的自动故障转移对各种中断场景的镜像响应响应主要中断场景的自动故障转移第九章 镜像架构和规划 - 备份处于活动状态时自动进行故障转移 备份处于活动状态…...

Barra模型因子的构建及应用系列七之Liquidity因子

一、摘要 在前期的Barra模型系列文章中&#xff0c;我们构建了Size因子、Beta因子、Momentum因子、Residual Volatility因子、NonLinear Size因子和Book-to-Price因子&#xff0c;并分别创建了对应的单因子策略&#xff0c;其中Size因子和NonLinear Siz因子具有很强的收益能力…...

走进二叉树的世界 ———性质讲解

二叉树的性质和证明前言1.二叉树的概念和结构特殊的二叉树&#xff1a;二叉树的性质前言 本篇博客主要讲述的是有关二叉树的一些概念&#xff0c;性质以及部分性质的相关证明&#xff0c;如果大伙发现了啥错误&#xff0c;可以在评论区指出&#x1f618;&#x1f618; 1.二叉树…...

【SSM】Spring + SpringMVC +MyBatis 框架整合

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ SSM框架整合一、导入相关依赖二、配置web.xml文…...

【算法基础】一篇文章彻底弄懂Dijkstra算法|多图解+代码详解

博主简介&#xff1a;努力学习的大一在校计算机专业学生&#xff0c;热爱学习和创作。目前在学习和分享&#xff1a;算法、数据结构、Java等相关知识。博主主页&#xff1a; 是瑶瑶子啦所属专栏: 算法 &#xff1b;该专栏专注于蓝桥杯和ACM等算法竞赛&#x1f525;近期目标&…...

第二十三天01MySQL多表查询与事务

目录 1. 多表查询 1.1 概述 1.1.1 数据准备 1.1.2 介绍 1.1.3 分类 1.2 内连接 1.2.1 语法 1.2.2 案例演示 1.3 外连接 1.3.1 语法 1.3.2 案例演示 1.4 子查询 1.4.1 介绍 1.4.2 标量子查询 1.4.3 列子查询 1.4.4 行子查询 1.4.5 表子查询 1.5 案例 1.5.1 介…...

TCP协议详解

1.TCP的准备条件在古代的时候&#xff0c;古人们经常写书信进行交流&#xff0c;写书信的前提是你要知道这份信是要寄给谁在网络中&#xff0c;我们通过ip端口号找对目标对象&#xff0c;但是现在网站一般会对ip端口注册一个域名&#xff0c;所以我们一般就是对域名进行查找&am…...

Activiti7与Spring、Spring Boot整合开发

Activiti整合Spring 一、Activiti与Spring整合开发 1.1 Activiti与Spring整合的配置 1)、在pom.xml文件引入坐标 如下 <properties><slf4j.version>1.6.6</slf4j.version><log4j.version>1.2.12</log4j.version> </properties> <d…...

基于SpringBoot实现冬奥会运动会科普平台【源码+论文】

基于SpringBoot实现冬奥会科普平台演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#…...

一文吃透SpringBoot整合mybatis-plus(保姆式教程)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

C++ primer plus(第六版)编程练习答案 第4章 复合类型

一、程序清单 arrayone.cpp // arrayone.cpp -- small arrays of integers #include <iostream> int main() {using namespace std;int yams[3]; // creates array with three elementsyams[0] = 7; // assign value to first elementyams[1] = 8;yams[2] = 6;i…...

Kafka源码分析之Producer(一)

总览 根据kafka的3.1.0的源码example模块进行分析&#xff0c;如下图所示&#xff0c;一般实例代码就是我们分析源码的入口。 可以将produce的发送主要流程概述如下&#xff1a; 拦截器对发送的消息拦截处理&#xff1b; 获取元数据信息&#xff1b; 序列化处理&#xff1b;…...

springboot校友社交系统

050-springboot校友社交系统演示录像开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;e…...

python flask项目部署

flask上传服务器pyhon安装下载Anacondasudo wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.3.1-Linux-x86_64.sh可根据需要安装对应的版本https://repo.anaconda.com/archive/解压anaconda压缩包bash Anaconda3-5.3.1-Linux-x86_64.sh解压过程中会…...

常见排序算法(C语言实现)

文章目录排序介绍插入排序直接插入排序希尔排序选择排序选择排序堆排序交换排序冒泡排序快速排序递归实现Hoare版本挖坑法前后指针版本非递归实现Hoare版本挖坑法前后指针版本快排的优化三值取中小区间优化归并排序递归实现非递归实现计数排序排序算法复杂度及稳定性分析不同算…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...