【C语言】实战项目——通讯录
引言
学会创建一个通讯录,对过往知识进行加深和巩固。
文章很长,要耐心学完哦!
✨ 猪巴戒:个人主页✨
所属专栏:《C语言进阶》
🎈跟着猪巴戒,一起学习C语言🎈
目录
引言
实战
建立文件
包含头文件
结构体的使用
通讯录
菜单
主脉络的实现
初始化函数的实现
第一个功能:增加联系人到通讯录
第二个功能:删除联系人的信息
第三个功能:查找指定联系人
第四个功能:修改指定联系人
第五个功能:打印通讯录中信息
第六个功能:排序通讯录中的内容
整体的代码实现
实战
通讯录的功能就是,记录联系人的信息,我们将联系人的信息分为5个部分,分别是姓名、年龄、性别、手机号、地址。
建立文件
我们要将通讯录的功能实现,首先要建立1个头文件,2个源文件。
一个源文件的名字叫contact.c,用来存放实现通讯录功能的函数
另外一个源文件叫test.c,用来实现通讯录的整体脉络
头文件叫做contact.h,用来声明contact.c中的函数,这样在test.c运行的时候就不会报出警告。
contact.h用来声明contact.c中的函数,test.c就要包含contact.h,自己的头文件如下图包含:
#include "contact.h"
包含头文件
既然test.c包含自己的头文件contact.h,为了简洁方便,不妨把我们要使用的库函数的头文件包含在contact.h中.
contact.c也把contact.h头文件包含,就不用再contact.c中再包含多个头文件了。
头文件会将功能函数声明放在里面,供给test.c使用,contact.c用来实现功能函数。
结构体的使用
我们要将联系人的5个信息储存起来,而这5个信息的类型有不一样,所以我们通过结构体将它们组合在一起,
结构体,结构是一些值的集合,这些值被称为成员变量。结构的每个成员可以是不同类型的变量。
结构体的使用包含再两个源文件中,所以我们将结构体的定义和声明放在contact.h头文件中。
typedef,关键字,作用是为一个类型创建一个新的名字。
本来下面结构体的类型是struct PeoInfo,为了将名字简化,用到了typedef关键字。
typedef struct PeoInfo
{char name[100];int age;char sex[10];char tele[12];char addr[30];
}PeoInfo;
#define ,为了更好改变name,sex,tele,addr的最大容量,通过定义宏将参数替换。
MAX 表示最大能容纳的联系人个数
MAX_NAME 表示name最大能容纳的字符个数
MAX_SEX 表示sex最大能容纳的字符个数
MAX_TELE 表示tele最大能容纳的字符个数
MAX_ADDR 表示addr最大能容纳的字符个数
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30typedef struct PeoInfo
{char name[MAX_NAME];int age;char sex[MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInfo;
通讯录
存放在头文件contact.h
通讯录不仅要包含上面的5个信息,5个信息包含在一起就是一个人的信息。创建变量count,可以记录通讯录的实际人数,之后的打印功能,也要使用count来打印。
data是struct PeoInfo类型的数组。上面把struct PeoInfo简化为PeoInfo.
data是储存每个人信息的数组,数组的每个元素代表着一个人的信息。
typedef struct Contact
{PeoInfo data[MAX];int count;//记录当前通讯录中实际人数的个数
}Contact;
菜单
存放在test.c源文件
首先给用户呈现的是菜单,菜单记录着用户可供选择的功能,将功能可视化。
一共包含6个功能
- 增加联系人到通讯录
- 删除联系人的信息
- 查找指定联系人
- 修改指定联系人
- 打印通讯录中信息
- 排序通讯录中的内容
0.退出通讯录
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.c
input,为键盘输入的数字,选择不同的数字代表着不同的功能。
switch语句,分支语句实现input为不同的数字,选择不同的功能,在case 后面实现这六个功能。
创建新的结构体变量要进行初始化,InitContact(&con)就是用来初始化结构体的。
之所以用自定义函数InitContact,是为了简洁和模块化处理。
int main()
{int input = 0;Contact con;//初始化通讯录:模块化初始化InitContact(&con);//只能传地址,进行修改scanf("%d",&input);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 0:printf("退出通讯录\n");break;default:printf("选择错误\n");}} while (input);return 0;
}
初始化函数的实现
存放在源文件contact.c
assert用来检验pc是否为空指针,如果为空指针就会报错。头文件<assert.h>
memset,功能是填充内存块,将num个字节的value填充到起始地址为ptr的位置。
void InitContact(Contact* pc)
{assert(pc);pc->count = 0;memset(pc->data, 0, sizeof(pc->data));
}
test.c要想使用,就要在头文件contact.h中进行声明。
void InitContact(Contact* pc);
第一个功能:增加联系人到通讯录
功能函数的实现都会放在contact.c中。
assert用来检验pc是否为空指针,如果为空指针就会报错。头文件<assert.h>
Contact* pc是传过来的struct Contact 类型的变量的地址,这里是传址调用,可以改变原来结构体的内容。
如果count到了通讯录的最大容量,就不能添加信息了,退出函数,并发出提示。
原始的count是0,每添加一个人的信息,count就要加1。
新的count表示的就是新联系人的下标,通过pc->data[pc->count].name 的方式找到各个信息。
如果count已经达到最大值,那么就直接提示 “通讯录已满,无法添加” ,并结束函数。
函数实现
void AddContact(Contact* pc)
{assert(pc);if (pc->count == MAX){printf("通讯录已满,无法添加\n");return;}printf("请输入名字:》");scanf("%s", pc->data[pc->count].name);printf("请输入年龄:》");scanf("%d", &(pc->data[pc->count].age));printf("请输入性别:>");scanf("%s", pc->data[pc->count].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->count].tele);printf("请输入地址:>");scanf("%s", pc->data[pc->count].addr);pc->count++; printf("增加成功\n");
}
第二个功能:删除联系人的信息
assert用来检验pc是否为空指针,如果为空指针就会报错。头文件<assert.h>
Contact* pc是传过来的struct Contact 类型的变量的地址,这里是传址调用,可以改变原来结构体的内容。
如果count为0,就表示通讯录里面没有内容,也就不能删除。直接提示 "通讯录为空,没有信息可以删除" 然后退出函数。
要删除联系人的信息,首先要查找联系人,之后才能删除。所以要实现查找联系人的功能。
1.查找
2.删除
查找:FindByName函数实现
创建一个字符函数name,向name输入我们要查找的联系人名字,之后用name来进行对比。
首先输入要查找的联系人名字,通过下标 i 对data进行查找,直到找到,返回下标,或者返回-1.
名字是字符数组,用strcmp对进行比较名字,库函数strcmp只有在相等的时候返回0。
strcmp的头文件:<string.h>
删除:DelContact来实现
找到要删除的联系人的下标,我们将它后面联系人的信息覆盖掉要删除的联系人的信息,就可以达到目的,然后对count减一,这样count就可以表示联系人的个数了。
本来最后一位的联系人的信息不用进行操作,本来count是99,下标为99的联系人信息覆盖到下标为98的位置,下标为99的信息不用管,count--之后,count = 98,下标为99的数据就不会被我们使用到。
函数实现
static int FindByName(Contact* pc,char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->count; i++){if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1;
}
void DelContact(Contact* pc)
{char name[MAX_NAME] = { 0 };assert(pc);int i = 0;if (pc->count == 0){printf("通讯录为空,没有信息可以删除\n");return;}printf("请输入要删除人的名字:>");scanf("%s", name);//删除//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//2.删除for (i = pos; i < pc->count; i++){pc->data[i] = pc->data[i + 1];}pc->count--;
}
第三个功能:查找指定联系人
assert用来检验pc是否为空指针,如果为空指针就会报错。头文件<assert.h>
Contact* pc是传过来的struct Contact 类型的变量的地址,这里是传址调用,可以改变原来结构体的内容。
建立字符数组name,输入要查找的联系人的信息。通过FindByName对name进行查找。
FindByName在上个功能实现了,当找到联系人的信息,返回下标。没找到返回-1。
我们用pos来对FindByName的返回值进行回收,如果pos等于-1,提示 "要查找的人不存在"然后
函数实现
void SeachContact(Contact* pc)
{assert(pc);char name[MAX_NAME] = { 0 };printf("请输入需要查找的联系人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}//2.打印printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-5d\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);}
第四个功能:修改指定联系人
assert检验空指针,name用来接收要修改联系人的姓名,通过 FindByName 查找联系人,pos返回查找结果。Contact* pc是传过来的struct Contact 类型的变量的地址,这里是传址调用,可以改变原来结构体的内容。
找到结果会返回下标pos,得到下标用ps->data[pos].name就可以修改内容了。
函数实现
void ModifyContact(Contact* pc)
{assert(pc);char name[MAX_NAME] = { 0 };printf("请输入需要查找的联系人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}printf("要修改人的信息已经找到,接下来进行修改\n");//2.修改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");
}
第五个功能:打印通讯录中信息
assert检验空指针。为了对齐联系人的数据,数据以最大容纳量来进行打印。
%20就是按照20个字符打印,%-20就是左对齐的意思。
函数实现
void ShowContact(const Contact* pc)
{assert(pc);int i = 0;//一个汉字是两个字符printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->count; i++){printf("%-20s\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);}
}
第六个功能:排序通讯录中的内容
assert检验空指针。qsort是快速排列函数。base是要排序的起始地址,pc->data表示首元素地址。num是要比较的元素个数,通讯录有多少个人,就比较多少个元素,num为pc->count。按名字排序,compar要比较的是通讯录的名字,我们实现cmp_peo_by_name函数,到时候把这个函数传过去。
cmp_peo_by_name:比较名字函数,名字是字符串,通过strcmp对字符串进行比较。
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*))
函数实现
int cmp_peo_by_name(const void* e1, const void* e2)
{return strcmp( ((PeoInfo*)e1)->name , ((PeoInfo*)e2)->name );
}
//按照名字来排序
void SortContact(Contact* pc)
{assert(pc);qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name );printf("排序成功\n");
}
整体的代码实现
test.c
#define _CRT_SECURE_NO_WARNINGS#include "contact.h"//
//1.静态的版本
//2.动态的版本
//3.文件的版本
//
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");}
int main()
{int input = 0;Contact con;//初始化通讯录:模块化初始化InitContact(&con);//只能传地址,进行修改do{menu();printf("请选择:》");scanf("%d", &input);switch (input){case 1:AddContact(&con);break;case 2:DelContact(&con);break;case 3:SeachContact(&con);break;case 4:ModifyContact(&con);break;case 5:ShowContact(&con);break;case 6:SortContact(&con);break;case 0:printf("退出通讯录\n");break;default:printf("选择错误\n");}} while (input);return 0;
}
contact.c
#define _CRT_SECURE_NO_WARNINGS#include "contact.h"
void InitContact(Contact* pc)
{assert(pc);pc->count = 0;memset(pc->data, 0, sizeof(pc->data));
}void AddContact(Contact* pc)
{assert(pc);if (pc->count == MAX){printf("通讯录已满,无法添加\n");return;}printf("请输入名字:》");scanf("%s", pc->data[pc->count].name);printf("请输入年龄:》");scanf("%d", &(pc->data[pc->count].age));printf("请输入性别:>");scanf("%s", pc->data[pc->count].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->count].tele);printf("请输入地址:>");scanf("%s", pc->data[pc->count].addr);pc->count++; printf("增加成功\n");
}void ShowContact(const Contact* pc)
{assert(pc);int i = 0;//一个汉字是两个字符printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->count; i++){printf("%-20s\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);}
}static int FindByName(Contact* pc,char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->count; i++){if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1;
}void DelContact(Contact* pc)
{char name[MAX_NAME] = { 0 };assert(pc);int i = 0;if (pc->count == 0){printf("通讯录为空,没有信息可以删除\n");return;}printf("请输入要删除人的名字:>");scanf("%s", name);//删除//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//2.删除for (i = pos; i < pc->count; i++){pc->data[i] = pc->data[i + 1];}pc->count--;
}void SeachContact(Contact* pc)
{assert(pc);char name[MAX_NAME] = { 0 };printf("请输入需要查找的联系人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}//2.打印printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-5d\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)
{assert(pc);char name[MAX_NAME] = { 0 };printf("请输入需要查找的联系人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}printf("要修改人的信息已经找到,接下来进行修改\n");//2.修改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 cmp_peo_by_name(const void* e1, const void* e2)
{return strcmp( ((PeoInfo*)e1)->name , ((PeoInfo*)e2)->name );
}
//按照名字来排序
void SortContact(Contact* pc)
{assert(pc);qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name );printf("排序成功\n");
}
contact.h
#pragma once#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#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[MAX];int count;//记录当前通讯录中实际人数的个数
}Contact;//初始化通讯录
void InitContact(Contact* pc);//增加联系人到通讯录
void AddContact(Contact* pc);//打印通讯录中信息
void ShowContact(const Contact* pc);//删除联系人的信息
void DelContact(Contact* pc);//查找指定联系人
void SeachContact(Contact* pc);//修改指定联系人
void ModifyContact(Contact* pc);//排序通讯录中的内容
//按照名字来排序
void SortContact(Contact* pc);
相关文章:
【C语言】实战项目——通讯录
引言 学会创建一个通讯录,对过往知识进行加深和巩固。 文章很长,要耐心学完哦! ✨ 猪巴戒:个人主页✨ 所属专栏:《C语言进阶》 🎈跟着猪巴戒,一起学习C语言🎈 目录 引言 实战 建…...
05 Rust 结构体
结构体 Rust 中的结构体(Struct)与元组(Tuple)都可以将若干个类型不一定相同的数据捆绑在一起形成整体,但结构体的每个成员和其本身都有一个名字,这样访问它成员的时候就不用记住下标了。 元组常用于非定…...
C语言预处理详解及其指令
预处理详解 1.预定义符号2.#define定义常量基本使用方法举例子如果在define定义的表示符后面加上分号会发生什么?用一下来解释 3. #define定义宏举例例1例2 4. 带有副作用的宏参数例如: 5. 宏替换的规则6. 宏函数的对比宏和函数的一个对比 7. #和##7.1 #运算符7.2 #…...
【数据结构—队列的实现】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、队列 1.1队列的概念及结构 二、队列的实现 2.1头文件的实现—Queue.h 2.2源文件的实现—Queue.c 2.3源文件的测试—test.c 三、测试队列实际数据的展示 3.…...
ASP.NET MVC实战之权限拦截Authorize使用
1,具体的实现方法代码如下 public class CustomAuthorizeAttribute : FilterAttribute, IAuthorizationFilter{/// <summary>/// 如果需要验证权限的时候,就执行进来/// </summary>/// <param name"filterContext"></par…...
java8实战 lambda表达式和函数式接口(上)
前言: 本博客对java8实战第三章的总结,也是上一篇博客行为化参数的延续,介绍一下函数式接口 Lambda表达式 lambda的表达式的结构由:参数,箭头,主体构成。 lambda示例 函数式接口: 先看上一篇…...
深度学习中的13种概率分布
1 概率分布概述 共轭意味着它有共轭分布的关系。 在贝叶斯概率论中,如果后验分布 p(θx)与先验概率分布 p(θ)在同一概率分布族中,则先验和后验称为共轭分布,先验称为似然函数的共轭先验。 多…...
C#基础知识 - 操作数与运算符篇2
C#基础知识 - 操作数与运算符篇 4.2 运算符4.2.1 按操作数个数分类4.2.2 按运算类型分类4.2.3 对运算符 、-- 的使用4.2.4 关系运算符:>、 < 、> 、<、 ! 、4.2.5 逻辑运算符:&& || ! ^ & |4.2.6 位运算符:~ 、^、 &…...
第十五章总结
一.输入/输出流 1.输入流 InputStrema类是字节输入流的抽象类,它是所有字节输入流的父类。 该类中所有方法遇到错误都会引发IOException异常。 read()方法:从输入流中读取数据的下一个字节。返回0~255的int字节值。如果因为已经到达流末尾而没有可用的…...
音频I2S
前言 基于网上资料对相关概念做整理汇总,部分内容引用自文后文章。 学习目标:简单了解相关概念、相关协议。 1 概述 数字音频接口DAI,即Digital Audio Interfaces,顾名思义,DAI表示在板级或板间传输数字音频信…...
小程序中的合法域名的作用及条件有哪些?
小程序的合法域名是指小程序项目中使用的各种接口、资源文件等所在的域名。在小程序开发中,需要将这些域名添加到小程序后台的“开发设置”-“服务器域名”中进行配置,才能够正常使用。 合法域名的作用: 1.作为小程序请求的 API 服务器域名…...
SpringData JPA 整合Springboot
1.导入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0…...
打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion 黑白老照片上色修复
在这个时代,我们习惯于拥有高清、色彩丰富的照片,然而,那些古老的黑白色老照片由于年代的久远,往往会出现模糊、破损等现象。 那么今天要给大家介绍的是,用 Stable Diffusion 来修复老照片。 前段时间 ControlNet 的除了上线了“IP-Adapter”模型以外还增加另一个…...
第十三章总结
一.泛型 1.定义泛型类 泛型机制语法: 类名<T> 其中,T是泛型的名称,代表某一种类型。 【例13.6】创建带泛型的图书类 代码: 结果: 2.泛型的常规用法 (1)定义泛型类时声明多个变量 class MyClass<T1,T2…...
大模型应用_PrivateGPT
https://github.com/imartinez/privateGPT 1 功能 整体功能,想解决什么问题 搭建完整的 RAG 系统,与 FastGPT相比,界面比较简单。但是底层支持比较丰富,可用于知识库的完全本地部署,包含大模型和向量库。适用于保密级…...
[Android] ubuntu虚拟机上搭建 Waydroid 环境
1.安装虚拟机 略 2.安装waydroid Ubuntu/Debian and derivatives For Droidian and Ubuntu Touch, skip directly to the last step Install pre-requisites sudo apt install curl ca-certificates -y Add the official repository curl https://repo.waydro.id | sudo…...
LeedCode刷题---滑动窗口问题(二)
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、将X减到0的最小操作数 题目链接:将 x 减到 0 的最小操作数 题目描述 给你一个整数数组 nums 和一个整数 x 。每一…...
pycharm依赖管理(不要用pip freeze)
在使用python虚拟环境时,可以使用requirements.txt来管理当前项目的依赖。 注意,不要用 pip freeze > requirements.txt 这个命令,因为它会引入很多无关的包。 可以使用 pipreqs ./ --encodingutf-8 ./ 表示当前项目的目录࿰…...
[Kafka 常见面试题]如何保证消息的不重复不丢失
文章目录 Kafka1. Kafka如何保证不丢失消息?生产者数据的不丢失消费者数据的不丢失Kafka集群中的broker的数据不丢失 2. Kafka中的消息是否会丢失和重复消费?1. 消息发送2. 消息消费 3. Kafka 的设计是什么样的呢?4. 数据传输的事务定义有哪三…...
Java中System.setProperty()用法
Java中System.setProperty()用法 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,让我们一起深入了解Java中的System.setProperty()方法,…...
Eclipse 自动生成注解,如果是IDEA可以参考编译器自带模版进行修改
IDEA添加自动注解 左上角选择 File -> Settings -> Editor -> File and Code Templates; 1、添加class文件自动注解: /*** <b>Function: </b> todo* program: ${NAME}* Package: ${PACKAGE_NAME}* author: Jerry* date: ${YEA…...
微信小程序vant安装使用过程中遇到无法构建npm的问题
官网地址,然而如果完全按照这个教程来,实际上是缺少步骤的,需要补充一些步骤(参考https://www.bilibili.com/video/BV1vL41127Er) # 这步init就是补充的 npm init npm i vant/weapp -S --production# 剩下的按照vant的…...
[python]用python获取EXCEL文件内容并保存到DBC
目录 关键词平台说明背景所需库实现过程方法1.1.安装相关库2.代码实现 关键词 python、excel、DBC、openpyxl 平台说明 项目Valuepython版本3.6 背景 在搭建自动化测试平台的时候经常会提取DBC文件中的信息并保存为excel或者其他文件格式,用于自动化测试。本文…...
Spring Boot 如何配置 log4j2
Log4j2 介绍 Spring Boot 中默认使用 Logback 作为日志框架,接下来我们将学习如何在 Spring Boot 中集成与配置 Log4j2。在配置之前,我们需要知道的是 Log4j2 是 Log4j 的升级版,它在 Log4j 的基础上做了诸多改进: 异步日志&…...
如何安装docker
安装Docker的步骤取决于您使用的操作系统。以下是常见操作系统上安装Docker的基本步骤: 对于Linux: 更新软件包索引: sudo apt-get update安装允许apt通过HTTPS使用仓库的包: sudo apt-get install apt-transport-https ca-certificates cur…...
Linux 之 性能优化
uptime $ uptime -p up 1 week, 1 day, 21 hours, 27 minutes$ uptime12:04:11 up 8 days, 21:27, 1 user, load average: 0.54, 0.32, 0.23“12:04:11” 表示当前时间“up 8 days, 21:27,” 表示运行了多长时间“load average: 0.54, 0.32, 0.23”“1 user” 表示 正在登录…...
用Go汇编实现一个快速排序算法
本代码全网首发,使用Go plan9 windows arm64汇编,实现基础版快速排序算法。 未引入随机因子的快速排序的普通Go代码长这样。 func QuickSort(arr []int) {if len(arr) < 1 {return}base, l, r : arr[0], 0, len(arr)-1for i : 1; i < r; {if arr…...
Spring-整合MyBatis
依赖 <dependencies><!--提供数据源--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.9.RELEASE</version></dependency><!--提供sqlSessionFactory…...
sql宽字节注入
magic_quotes_gpc(魔术引号开关) https://www.cnblogs.com/timelesszhuang/p/3726736.html magic_quotes_gpc函数在php中的作用是判断解析用户提交的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以…...
开源 LLM 微调训练指南:如何打造属于自己的 LLM 模型
一、介绍 今天我们来聊一聊关于LLM的微调训练,LLM应该算是目前当之无愧的最有影响力的AI技术。尽管它只是一个语言模型,但它具备理解和生成人类语言的能力,非常厉害!它可以革新各个行业,包括自然语言处理、机器翻译、…...
网站建设关键词/seo网站管理招聘
rt转载于:https://www.cnblogs.com/speedoops/archive/2010/12/14/1906155.html...
做网站卖装备/网页设计页面
有需求请评论或私信 可远程调试 基于PHP的毕设双选管理系统一 介绍 此毕设双选管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为学生,教师,审核员和管理员。系统核心流程为:学生提交选题申请后由教师…...
wordpress 邮箱变更/好的seo公司营销网
一、路由基础Routing protocol 用于路由器动态寻找最优路径,并使路由器都拥有路由表,R/p 决定了数据包的上行路径,eg:RIP IGRP EIGRP OSPF,被动路由协议被分配到接口上并决定数据数据包的传送方式, Router:把一个数据包…...
克隆网站首页做单页站几个文件/seo关键词怎么选
export PS1[\u\h:$PWD] 再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow...
wordpress图片加载快/实训百度搜索引擎的总结
题目要求:根据《福建省电网销售电价表》,居民生活用电按3个梯度收费:月用电量150千瓦时及以下部分,每千瓦时0.4463元,151—400千瓦时部分为0.4663元,401千瓦时以上部分为0.5663元,请编写程序&am…...
php mysql开发网站开发/百度竞价员
Ubuntu20.04 ROS1. 环境配置2. 创建工作空间3. URDF 机器人建模4. 机器人仿真4.1 机器人 URDF 模型优化4.2 Arbotix rviz 功能仿真4.2.1 配置 Arbotix 控制器4.2.2 导航仿真示例4.3 Gazebo 物理仿真环境搭建1. 环境配置 虚拟机 VMware 安装网址: vmap.sjtu.edu.c…...