设计一个简单的通讯录

news2024/11/26 11:33:10

目录

导读:

一、主函数

1. 打印功能菜单

2. 用枚举常量列举功能给功能赋值(0-5)

3. main主函数

二、头文件

三、通讯录各功能的实现

1. 初始化通讯录

2. 增加联系人

3. 展示所有联系人信息

4.  删除指定联系人

5. 查询指定联系人信息

6. 修改指定联系人信息

7. 销毁通讯录

四、各模块全部代码

1. 主函数

2. 头文件

3. 功能实现

五、代码运行展示

1. 添加联系人

2. 展示联系人信息

​3. 查找联系人

4. 修改联系人并展示

5. 删除联系人并展示

6. 退出通讯录 


导读:

通讯录中所涉及到的动态内存管理相关知识在:

C语言动态内存管理(malloc, calloc,realloc)详解-CSDN博客

柔性数组:

柔性数组详解-CSDN博客

结构体等自定义类型相关知识:

结构体、枚举以及联合类型在内存中的存储与大小计算-CSDN博客

还有之前写过的一个简易的三子棋游戏:

三子棋小游戏代码实现_流浪者与猴的博客-CSDN博客

该通讯录功能为增、删、查、改以及展示目前存放的所有联系人信息,更多功能以及优化等待博主后续的努力

该代码分三个模块:主函数(test_16.c)、具体功能的实现(contact.c)、以及函数的声明(contact.h)

一、主函数

在开头引用contact.h头文件,函数内涵所用到的所有函数以及结构体声明

#include "contact.h"

1. 打印功能菜单

void menu()
{
	printf("***************************************\n");
	printf("**** 1.add          2.del    **********\n");
	printf("**** 3.search       4.modify **********\n");
	printf("**** 5.show         0.exit     **********\n");
	printf("***************************************\n");
}

2. 用枚举常量列举功能给功能赋值(0-5)

enum Option  //列举出通讯录功能
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
};

3. main主函数

使用do...while循环以及switch来实现功能的反复使用,其中的结构体和函数声明在自身创的头文件中,再开头以及引用

int main()
{
	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 EXIT:
			DestroyContact(&con);//销毁空间
			printf("退出\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

二、头文件

头文件中包括库函数、各功能函数、结构体等声明,以供在其他模块更好的使用

#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 20   
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2



//类型的声明
typedef 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;

//动态
typedef struct Contact
{
	PeoInfo* data;//存放数据
	int sz;//记录当前通讯录中存在的人的信息个数
	int capacity;//记录的是通讯录的当前容量
}Contact;

//初始化通讯录
void InitContact(Contact* pc);

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

//显示所有联系人
void ShowContact(Contact* pc);

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

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

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

//销毁通讯录
void DestroyContact(Contact* pc);

三、通讯录各功能的实现

1. 初始化通讯录

void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;  //初始通讯录个人信息为0
	pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3
	pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存
	if (pc->data == NULL)
	{
		perror("calloc");//如果没有开辟成功返回报错信息
		return;
	}
	memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
}

2. 增加联系人

在增加联系人前,需要检查通讯录的容量是否够用,这里单独分装成一个函数,来实现容量的检查以及扩展

void CheckCapacity(Contact* pc) //检查容量大小
{
	if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间
		if (ptr != NULL)
		{
			pc->data = ptr;//开辟成功则把空间赋给data
			pc->capacity += DEFAULT_INC;//让容量自增2个
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");//开辟失败返回报错信息
			return;
		}
	}
}
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);

	pc->sz++;
	printf("增加成功\n");
}

3. 展示所有联系人信息

void ShowContact(Contact* pc)//展示所有联系人信息
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需打印\n");
		return;
	}
	int i = 0;
	//名字	年龄	性别	电话	地址
	printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每个人信息
		printf("%-20s%-5d%-5s%-12s%-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

4.  删除指定联系人

删除联系人需要对通讯录进行查找,所有这里我们也时再次分装一个函数用来查找联系人,后续联系人信息的修改以及查询某个联系人同样需要此函数

int FindByName(Contact* pc, char name[])
{
	assert(pc);
	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)//删除指定联系人
{
	char name[NAME_MAX];
	assert(pc);
	if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	//找到联系人
	printf("输入删除人的名字:");
	scanf("%s", name);
	//找到名字为name的人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("要删除得到人不存在\n");
		return;
	}
	//删除这个人
	int i = 0;
	for (i = ret; i < pc->sz-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

5. 查询指定联系人信息

这里也用了查找函数

void SearchContact(Contact* pc)//查询联系人
{
	assert(pc);
	char name[NAME_MAX];
	printf("输入查找人的名字:");
	scanf("%s", name);
	//找到名字为name的人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	//显示出来
	printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%-20s%-5d%-5s%-12s%-30s\n",
		pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}

6. 修改指定联系人信息

void ModifyContact(Contact* pc)修改指定联系人
{
	assert(pc);
	char name[NAME_MAX];
	printf("输入要修改人的名字:");
	scanf("%s", name);
	//找到名字为name的人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	//修改
	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);
}

7. 销毁通讯录

开辟的内存使用后需要进行释放

void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

四、各模块全部代码

1. 主函数

#define _CRT_SECURE_NO_WARNINGS 
#include "contact.h"
//测试通讯录的基本功能
void menu()
{
	printf("***************************************\n");
	printf("**** 1.add          2.del    **********\n");
	printf("**** 3.search       4.modify **********\n");
	printf("**** 5.show         0.exit     **********\n");
	printf("***************************************\n");
}
enum Option  //列举出通讯录功能
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
};
int main()
{
	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 EXIT:
			DestroyContact(&con);//销毁空间
			printf("退出\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

2. 头文件

#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 20   
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 100
#define DEFAULT_SZ 3
#define DEFAULT_INC 2



//类型的声明
typedef 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;

//动态
typedef struct Contact
{
	PeoInfo* data;//存放数据
	int sz;//记录当前通讯录中存在的人的信息个数
	int capacity;//记录的是通讯录的当前容量
}Contact;

//初始化通讯录
void InitContact(Contact* pc);

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

//显示所有联系人
void ShowContact(Contact* pc);

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

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

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

//销毁通讯录
void DestroyContact(Contact* pc);

3. 功能实现

#define _CRT_SECURE_NO_WARNINGS 
#include "contact.h"
//静态
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//}

//动态
void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;  //初始通讯录个人信息为0
	pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3
	pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存
	if (pc->data == NULL)
	{
		perror("calloc");//如果没有开辟成功返回报错信息
		return;
	}
	memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
}

//静态版本
//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");
//}


void CheckCapacity(Contact* pc) //检查容量大小
{
	if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间
		if (ptr != NULL)
		{
			pc->data = ptr;//开辟成功则把空间赋给data
			pc->capacity += DEFAULT_INC;//让容量自增2个
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");//开辟失败返回报错信息
			return;
		}
	}
}
void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}
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);

	pc->sz++;
	printf("增加成功\n");
}




void ShowContact(Contact* pc)//展示所有联系人信息
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需打印\n");
		return;
	}
	int i = 0;
	//名字	年龄	性别	电话	地址
	printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每个人信息
		printf("%-20s%-5d%-5s%-12s%-30s\n",
			pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}


int FindByName(Contact* pc, char name[])
{
	assert(pc);
	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)//删除指定联系人
{
	char name[NAME_MAX];
	assert(pc);
	if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	//找到联系人
	printf("输入删除人的名字:");
	scanf("%s", name);
	//找到名字为name的人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("要删除得到人不存在\n");
		return;
	}
	//删除这个人
	int i = 0;
	for (i = ret; i < pc->sz-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}


void SearchContact(Contact* pc)//查询指定联系人
{
	assert(pc);
	char name[NAME_MAX];
	printf("输入查找人的名字:");
	scanf("%s", name);
	//找到名字为name的人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	//显示出来
	printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("%-20s%-5d%-5s%-12s%-30s\n",
		pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
}


void ModifyContact(Contact* pc)修改指定联系人
{
	assert(pc);
	char name[NAME_MAX];
	printf("输入要修改人的名字:");
	scanf("%s", name);
	//找到名字为name的人
	int ret = FindByName(pc, name);
	if (ret == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	//修改
	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);
}

五、代码运行展示

1. 添加联系人

2. 展示联系人信息

3. 查找联系人

 4. 修改联系人并展示

5. 删除联系人并展示

6. 退出通讯录 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARM汇编基础指令整合

汇编语言的组成 伪操作 不参与程序的执行&#xff0c;但是用于告诉编译器程序该怎么编译 如&#xff1a; .text .global .end .if .else .endif .data 汇编指令 汇编器将一条汇编指令编译成一条机器码&#xff0c;在内存里一条指令…

JAVA 学习笔记 2年经验

文章目录 基础String、StringBuffer、StringBuilder的区别jvm堆和栈的区别垃圾回收标记阶段清除阶段 异常类型双亲委派机制hashmap和hashtable concurrentHashMap 1.7和1.8的区别java的数据结构排序算法&#xff0c;查找算法堆排序 ThreadLocal单例模式常量池synchronizedsynch…

【力扣周赛】第 364 场周赛⭐(前后缀分解+单调栈DFS技巧)

文章目录 竞赛链接Q1&#xff1a;2864. 最大二进制奇数&#xff08;贪心&#xff09;写法1——手动模拟&#xff08;代码长&#xff0c;运行快&#xff09;写法2——API&#xff08;代码短&#xff0c;运行慢&#xff09; Q2&#xff1a;2865. 美丽塔 I竞赛时代码——枚举山顶 …

C++ 基础_Day01

准备工具Vscode或者Clion或者Dev C或者Vs studio 和 MSYS2 是C跨平台的重要工具链. 文章目录 准备工作安装MSYS2软件 创建文件 一、基本介绍1.1C源文件1.2 代码注释1.3变量与常量1.3.1变量1.3.2 常量1.3.3 二者的区别&#xff1a; 1.4 关键字和标识符 二、数据类型2.1 基本数据…

嵌入式Linux应用开发-第十四章查询方式的按键驱动程序

嵌入式Linux应用开发-第十四章查询方式的按键驱动程序 第十四章 查询方式的按键驱动程序_编写框架14.1 LED驱动回顾14.2 按键驱动编写思路14.3 编程&#xff1a;先写框架14.3.1 把按键的操作抽象出一个button_operations结构体14.3.2 驱动程序的上层&#xff1a;file_operation…

自动驾驶中的感知模型:实现安全与智能驾驶的关键

自动驾驶中的感知模型&#xff1a;实现安全与智能驾驶的关键 文章目录 引言感知模型的作用感知模型的技术安全与挑战结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;全新的PnC培训…

【洛谷】P3378 【模板】堆

原题链接&#xff1a;https://www.luogu.com.cn/problem/P3378 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 一道模板题&#xff0c;主要是熟悉STL中优先队列&#xff08;priority_queue&#xff09;的使用。 堆的STL实现: priority_queue<in…

国庆周《LInux学习第四课》

国庆周《LInux学习第四课》 软件的安装与卸载 图解

无人注意,新安装的 Ubuntu 23.04 不支持安装 32 位应用

导读新安装的 Ubuntu 23.04 不支持安装 32 位应用。 无人注意&#xff0c;新安装的 Ubuntu 23.04 不支持安装 32 位应用 有用户报告&#xff0c;在新安装的 Ubuntu 23.04 上从 Ubuntu 仓库安装的 Steam 客户端是不工作的。在 Ubuntu 23.04 中使用了基于 Flutter 的新安装程序…

故障:无线鼠标键盘有时候出现短暂失灵的情况

无线鼠标连台式机用的&#xff0c;之前一直没问题&#xff0c;最近开始出现短暂失灵的情况。 并不是有延时&#xff0c;因为在失灵期间的那些操作在恢复后不会执行。 有的时候&#xff0c;电脑是在打开或者关闭某些应用&#xff0c;即调用cpu的情况&#xff0c;这个时候出问题…

k8s搭建EFK日志系统

搭建 EFK 日志系统 前面大家介绍了 Kubernetes 集群中的几种日志收集方案&#xff0c;Kubernetes 中比较流行的日志收集解决方案是 Elasticsearch、Fluentd 和 Kibana&#xff08;EFK&#xff09;技术栈&#xff0c;也是官方现在比较推荐的一种方案。 Elasticsearch 是一个实…

Cannot download sources:IDEA源码无法下载

问题 Swagger的相关包&#xff0c;无法看到注释&#xff1b; 在class文件的页面&#xff0c;点击下载源码&#xff0c;源码下载不了&#xff0c;IDEA报下面的错误。 报错 Cannot download sources Sources not found for: io.swagger.core.v3:swagger-annotations:2.2.9 解决…

差分放大器的精髓:放大差模信号 抑制共模信号

参考如图基本的差分放大电路&#xff0c;在R1R2 R3R4的条件下&#xff0c;其输出与输入的关系为 &#xff1a; 具体推导过程参考&#xff1a;差分运算放大器的放大倍数的计算及结论_正在黑化的KS的博客-CSDN博客 由这个式子我们可以发现&#xff0c;差分放大器放大的是同相端与…

凉鞋的 Godot 笔记 103. 检视器 :节点的微观编辑和查看

在上一篇&#xff0c;笔者简单介绍了场景与节点的增删改查&#xff0c;如下所示: 在这一篇&#xff0c;我们接着往下学习。 我们知道在场景窗口&#xff0c;可以对节点进行增删改查。 在 Godot 引擎使用过程中&#xff0c;场景窗口的使用频率是非常高的。 但是场景窗口只能编…

系统集成|第二十一章(笔记)

目录 第二十一章 知识产权与法律法规21.1 知识产权21.2 法律法规 上篇&#xff1a;第二十章、收尾管理 第二十一章 知识产权与法律法规 21.1 知识产权 概述&#xff1a;狭义的知识产权就是传统意义上的知识产权&#xff0c;包括著作权&#xff08;含邻接权&#xff09;&#x…

深度学习——模型选择、欠拟合和过拟合

深度学习——模型选择、欠拟合和过拟合 文章目录 前言一、训练误差和泛化误差1.1. 统计学习理论1.2. 模型复杂性 二、模型选择2.1. 验证集2.2. K折交叉验证 三、欠拟合 or 过拟合3.1. 模型复杂性3.2. 数据集大小 四、多项式回归4.1. 生成数据集4.2. 对模型进行训练和测试4.3. 三…

Egg 封装接口返回信息

中间件封装 代码 const msgArr {"200":成功,"401":token失效 } module.exports (option, app) > {return async function(ctx, next) {try{//成功是返回的信息ctx.emit(code,data,msg)>{console.log(1111,code,data,msg)ctx.body {code,data:dat…

嵌入式Linux应用开发-第十三章APP怎么读取按键值

嵌入式Linux应用开发-第十三章读取按键及按键驱动程序 第十三章 APP怎么读取按键值13.1 妈妈怎么知道孩子醒了13.2 APP读取按键的4种方法13.2.1 查询方式13.2.2 休眠-唤醒方式13.2.3 poll方式13.2.4 异步通知方式13.2.4.1 异步通知的原理&#xff1a;发信号13.2.4.2 应用程序之…

MyBatisPlus(六)字段映射 @TableField

字段注解&#xff08;非主键&#xff09; TableField 用于映射对象的 属性 和表中的 字段 。 当 属性名 和 字段名 差异较大的时候&#xff0c;无法通过默认的映射关系对应起来&#xff0c;就需要指定 属性名 对应 的 字段名。 官网示例 代码实例 package com.example.web.…

clip代码安装实操

CLIP模型及代码地址&#xff1a;GitHub - openai/CLIP: Contrastive Language-Image Pretraining 代码准备环境 先创建一个anaconda虚拟环境&#xff0c;包含python3.7版本&#xff0c;将该环境命名为clip。成功。 &#xff08; pytorch1.7.1 所需 python 版本 >3.6&…