精通C语言:打造高效便捷的通讯录管理系统
欢迎大家来到贝蒂大讲堂
养成好习惯,先赞后看哦~
所属专栏:C语言项目
贝蒂的主页:Betty‘s blog
引言:
在我们大致学习完C语言之后,我们就可以利用目前所学的知识去做一些有意思的项目,而今天贝蒂就带大家完成一个通讯录的简易实现,
本章你可能需要的知识:
1. 通讯录要求
- 通讯录包括每个人的姓名,性别,年龄,电话与地址。
- 玩家可以自由选择通讯录的进出。
- 玩家可以自由增删查改通讯录中的数据。
2. 多文件管理
为了方便代码的管理和保证通讯录实现逻辑的清晰性,我们将采用多文件管理的模式。
创建头文件contact.c,包含所有头文件(其他源文件只需引用它即可),以及所有通讯录功能的展现。
创建源文件contact.c,负责通讯录所有功能的具体代码实现。
创建源文件text.c,负责展现通讯录实现的总体逻辑。
3. 通讯录的准备
3.1 预处理信息
为了方便我们后续更换通讯的信息,我们可以利用宏来定义通讯录的具体信息的大小。
#define MAX 100//最大人数
#define MAX_NAME 20//名字最大长度
#define MAX_SEX 5//性别最大长度
#define MAX_TELE 12//电话最大长度
#define MAX_ADDR 30//地址最大长度
3.2 结构体定义
每个人的通讯录都要包含姓名,性别,年龄,电话与地址等信息,这时就需要我们创建一个结构体来方便管理。
typedef struct PeoInfo
{
char name[MAX_NAME];//名字
int age;//年龄
char sex[MAX_SEX];//性别
char tele[MAX_TELE];//电话
char addr[MAX_ADDR];//地址
}PeoInfo;
而我们需要用这个结构体创建一个大小为100的数组,并且我们还需要知道当前通讯录的大小才能进行增删查改的操作,这两者息息相关,为了简化代码和增加代码的可读性,我们可以将这两者重新定义一个结构体。
typedef struct contact
{
PeoInfo data[MAX];//一百个人的数据
int sz;//通讯录的大小
}contact;
4. 简易菜单
void menu()
{
printf("***********************************\n");
printf("** 1.add 2.delete **\n");
printf("** 3.search 4.modify **\n");
printf("** 5.display 6.sort **\n");
printf("** 0.exit **\n");
printf("***********************************\n");
}
画面展示:
5. 通讯录具体功能
5.1 初始化
我们首先对通讯录进行初始化。
void InitContact(contact* pc)//初始化
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
5.2 展示联系人
当用户选择5时自动展示通讯录中的用户,并且展示用户过程中需要进行对齐,便于用户观看。
void DisplayContact(contact* pc)//打印信息
{
assert(pc);
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪",
"性别", "电话", "地址");//默认右对齐,修改为左对齐
//中间也要留下足够的空间
for (int i = 0; i < pc->sz; i++)
{
printf("%-15s\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);
}
}
5.3 添加联系人
用户选择1可以自由添加联系人,如果通讯录已满,则提醒用户通讯录已满,请先清理通讯录。
(1) 检查通讯录是否已满
如果通讯录满了返回0,未满则返回1。
int CheckContact(contact*pc)//检查大小
{
assert(pc);
if (pc->sz == 100)
{
return 0;
}
return 1;
}
(2) 添加
当通讯录未满时,用户可以输入数据添加新用户。
void AddContact(contact* pc)//增加联系人
{
assert(pc);
int ret = CheckContact(pc);//检查是否满了
if (ret == 0)
{
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);
printf("用户添加成功!\n");
pc->sz++;
}
5.4 删除联系人
用户可以选择2清理通讯录,删除指定联系人。
(1) 寻找下标
在删除指定练习人时我们需通过其姓名寻找该联系人的下标。找到返回其下标,否则返回-1、
int FindName(contact* pc, char name[])
{
assert(pc&&name);
for (int pos = 0; pos < pc->sz; pos++)
{
if (strcmp(pc->data[pos].name, name) == 0)
{
return pos;
}
}
return -1;
}
(2) 删除
通过寻找到的下标,我们可以利用后面的数据依次覆盖来达到删除的目的。
注意:我们不能覆盖最后一个数据否则就会发生数组越界,这时我们只需减去通讯录此时的大小就好了。
void DeleteContact(contact* pc)//删除联系人
{
assert(pc);
assert(pc->sz >= 0);
char name[MAX_NAME];
printf("请输入需要删除人的姓名:> ");
scanf("%s", name);
int pos = FindName(pc, name);
if (pos == -1)
{
printf("通讯录中并没有这个人!!\n");
return;
}
for (int i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];//覆盖
}
printf("删除成功\n");
pc->sz--;
}
删除前:
删除后 :
5.5 查找联系人
通过选择3查找指定联系人,没有找到则提醒用户没有该用户,查找到就打印其信息。
void SearchContact(contact* pc)//查找联系人
{
assert(pc);
char name[MAX_NAME];
printf("请输入需要查找人的姓名:> ");
scanf("%s", name);
int pos = FindName(pc, name);
if (pos == -1)
{
printf("通讯录中并没有这个人!!\n");
return;
}
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪",
"性别", "电话", "地址");
printf("%-15s\t%-5d\t%-5s\t%-12s\t%-30s", pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
5.6 修改联系人
我们可以通过选择4修改指定联系人的信息。
void ModifyContact(contact* pc)//修改联系人
{
assert(pc);
char name[MAX_NAME];
printf("请输入需要修改人的姓名:> ");
scanf("%s", name);
int pos = FindName(pc, name);
if (pos == -1)
{
printf("通讯录中并没有这个人!!\n");
return;
}
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");
}
修改前:
修改后:
5.7 排序联系人
我们可以选择6对通讯录进行排序,可以按照姓名,年纪,性别,电话,地址排序。
int cmp1(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
int cmp2(const void* p1, const void* p2)
{
return ((PeoInfo*)p1)->age- ((PeoInfo*)p2)->age;
}
int cmp3(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->sex, ((PeoInfo*)p2)->sex);
}
int cmp4(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->tele, ((PeoInfo*)p2)->tele);
}
int cmp5(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}
void SortByName(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp1);
}
void SortByAge(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp2);
}
void SortBySex(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp3);
}
void SortByTele(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortByAddr(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortContact(contact* pc)//排序联系人
{
assert(pc);
printf("请选择如何排序:> ");
char input[20];
scanf("%s", input);
if (strcmp(input, "姓名")==0)
{
SortByName(pc);//按姓名排序
}
else if (strcmp(input, "年龄") == 0)
{
SortByAge(pc);//按年龄排序
}
else if (strcmp(input, "性别") == 0)
{
SortBySex(pc);//按性别排序
}
else if (strcmp(input, "电话") == 0)
{
SortByTele(pc);//按电话排序
}
else if (strcmp(input, "地址") == 0)
{
SortByAddr(pc);//按地址排序
}
else
{
printf("输入非法,请重新输入\n");
}
}
6. 改进通讯录
6.1 动态内存开辟
上述通讯录有一个致命的缺点——通讯录大小固定,为了解决这个问题我可以使用我们前面学过的动态内存开辟。
(1) 新增变量
为了方便我们知道此时的容量大小,我们将在结构体中加入新的变量。
typedef struct contact
{
PeoInfo *data;//动态开辟的数据
int sz;//通讯录的大小
int capacity;//通讯录的容量
}contact;
(2) 初始化
void InitContact(contact* pc)//初始化
{
assert(pc);
pc->sz = 0;
pc->data = (PeoInfo*)calloc(2, sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact:");
return;
}
pc->capacity = 2;
/*memset(pc->data, 0, sizeof(pc->data));*/
}
(3) 增容
当通讯录用户数量满时增加内存空间。
void CheckCapacity(contact* pc)//增容
{
if (pc->sz == pc->capacity)
{
PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
if (tmp != NULL)
{
pc->data = tmp;
}
else
{
perror("CheckCapacity:");
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
6.2 文件保存
我们发现每当我们关闭程序时我们写入的数据会被清空,我们要想保存上次写入的数据就应该使用文件操作。
(1) 加载数据
每次初始化时就要将上次文件的数据导入进来。
void LoadContact(contact* pc)//加载上次数据
{
PeoInfo tmp = { 0 };
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
return;
}
//读取文件,存放到通讯录
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
//返回值为0就是遇见文件末尾
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
fclose(pf);
pf = NULL;
}
(2) 保存数据
当程序正常结束时保存数据。
void SaveContact(contact* pc)//保存数据
{
FILE* pfWrite = fopen("contact.txt", "wb");
if (pfWrite == NULL)
{
perror("fopen:");
return;
}
//写通讯录中数据到文件中
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pfWrite);
}
fclose(pfWrite);
pfWrite = NULL;
printf("保存成功\n");
}
7. 通讯录逻辑的搭建
- 用户通过数字选择功能。
- 每次选择完之后返回菜单。
- 选择退出之后保存数据,程序结束。
enum Option
//利用枚举增加代码的可读性
{
EXIT,//0
ADD,
DEL,
SEARCH,
MODIFY,
DISPLAY,
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:
DeleteContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case DISPLAY:
DisplayContact(&con);
break;
case SORT:
SortContact(&con);
break;
case EXIT:
SaveContact(&con);//退出保存数据
DestroyContact(&con);
break;
default:
printf("非法输入,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
8. 完整代码
8.1 contact.h
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#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;
typedef struct contact
{
PeoInfo *data;//动态开辟的数据
int sz;//通讯录的大小
int capacity;//通讯录的容量
}contact;
void InitContact(contact* pc);//初始化
void DisplayContact(contact* pc);//打印信息
void AddContact(contact* pc);//增加联系人
void DeleteContact(contact* pc);//删除联系人
void SearchContact(contact* pc);//查找联系人
void ModifyContact(contact* pc);//修改联系人
void SortContact(contact* pc);//排序联系人
void SaveContact(contact* pc);//保存数据
void DestroyContact(contact* pc);//销毁内存
8.2 contact.c
#include"contact.h"
void CheckCapacity(contact* pc)//增容
{
if (pc->sz == pc->capacity)
{
PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
if (tmp != NULL)
{
pc->data = tmp;
}
else
{
perror("CheckCapacity:");
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
void LoadContact(contact* pc)//加载上次数据
{
PeoInfo tmp = { 0 };
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
return;
}
//读取文件,存放到通讯录
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
//返回值为0就是遇见文件末尾
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
fclose(pf);
pf = NULL;
}
void InitContact(contact* pc)//初始化
{
assert(pc);
pc->sz = 0;
pc->data = (PeoInfo*)calloc(2, sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact:");
return;
}
pc->capacity = 2;
LoadContact(pc);
/*memset(pc->data, 0, sizeof(pc->data));*/
}
void DisplayContact(contact* pc)//打印信息
{
assert(pc);
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪",
"性别", "电话", "地址");//默认右对齐,修改为左对齐
//中间也要留下足够的空间
for (int i = 0; i < pc->sz; i++)
{
printf("%-15s\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);
}
}
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);
printf("用户添加成功!\n");
pc->sz++;
}
int FindName(contact* pc, char name[])
{
assert(pc&&name);
for (int pos = 0; pos < pc->sz; pos++)
{
if (strcmp(pc->data[pos].name, name) == 0)
{
return pos;
}
}
return -1;
}
void DeleteContact(contact* pc)//删除联系人
{
assert(pc);
assert(pc->sz >= 0);
char name[MAX_NAME];
printf("请输入需要删除人的姓名:> ");
scanf("%s", name);
int pos = FindName(pc, name);
if (pos == -1)
{
printf("通讯录中并没有这个人!!\n");
return;
}
for (int i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];//覆盖
}
printf("删除成功\n");
pc->sz--;
}
void SearchContact(contact* pc)//查找联系人
{
assert(pc);
char name[MAX_NAME];
printf("请输入需要查找人的姓名:> ");
scanf("%s", name);
int pos = FindName(pc, name);
if (pos == -1)
{
printf("通讯录中并没有这个人!!\n");
return;
}
printf("%-15s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "年纪",
"性别", "电话", "地址");
printf("%-15s\t%-5d\t%-5s\t%-12s\t%-30s", 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];
printf("请输入需要修改人的姓名:> ");
scanf("%s", name);
int pos = FindName(pc, name);
if (pos == -1)
{
printf("通讯录中并没有这个人!!\n");
return;
}
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 cmp1(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
int cmp2(const void* p1, const void* p2)
{
return ((PeoInfo*)p1)->age- ((PeoInfo*)p2)->age;
}
int cmp3(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->sex, ((PeoInfo*)p2)->sex);
}
int cmp4(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->tele, ((PeoInfo*)p2)->tele);
}
int cmp5(const void* p1, const void* p2)
{
return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}
void SortByName(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp1);
}
void SortByAge(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp2);
}
void SortBySex(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp3);
}
void SortByTele(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortByAddr(contact* pc)
{
qsort(pc, pc->sz, sizeof(PeoInfo), cmp4);
}
void SortContact(contact* pc)//排序联系人
{
assert(pc);
printf("请选择如何排序:> ");
char input[20] = { 0 };
scanf("%s", input);
if (strcmp(input, "姓名")==0)
{
SortByName(pc);//按姓名排序
}
else if (strcmp(input, "年龄") == 0)
{
SortByAge(pc);//按年龄排序
}
else if (strcmp(input, "性别") == 0)
{
SortBySex(pc);//按性别排序
}
else if (strcmp(input, "电话") == 0)
{
SortByTele(pc);//按电话排序
}
else if (strcmp(input, "地址") == 0)
{
SortByAddr(pc);//按地址排序
}
else
{
printf("输入非法,请重新输入\n");
}
}
void DestroyContact(contact* pc)
{
free(pc->data);
pc->data= NULL;
pc->capacity = 0;
pc->sz = 0;
printf("销毁成功\n");
}
void SaveContact(contact* pc)//保存数据
{
FILE* pfWrite = fopen("contact.txt", "wb");
if (pfWrite == NULL)
{
perror("fopen:");
return;
}
//写通讯录中数据到文件中
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(&(pc->data[i]), sizeof(PeoInfo), 1, pfWrite);
}
fclose(pfWrite);
pfWrite = NULL;
printf("保存成功\n");
}
8.3 text.c
#include"contact.h"
enum Option
//利用枚举增加代码的可读性
{
EXIT,//0
ADD,
DEL,
SEARCH,
MODIFY,
DISPLAY,
SORT
};
void menu()
{
printf("***********************************\n");
printf("** 1.add 2.delete **\n");
printf("** 3.search 4.modify **\n");
printf("** 5.display 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:
DeleteContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case DISPLAY:
DisplayContact(&con);
break;
case SORT:
SortContact(&con);
break;
case EXIT:
SaveContact(&con);//退出保存数据
DestroyContact(&con);
break;
default:
printf("非法输入,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
精通C语言:打造高效便捷的通讯录管理系统的更多相关文章
- go语言打造个人博客系统(一)
go语言打造个人博客系统(一) 为什么选择go语言? 听说go语言是在几年前,但真正深入了解他却是在2017年,因为当时作为讲师 ,需要准备go语言的课程,结果稍一接触立刻就喜欢上这门语言了,作为 ...
- 打造高效前端工作环境 - tmux
打造高效前端工作环境 - tmux 前言 现在前端开发可不容易啊,先打开个VIM,然后再打开个lite-server,一不小心写个ES2015还要打开个gulp来做预编译,如果能把这么多个窗口放在一 ...
- 利用R语言打造量化分析平台
利用R语言打造量化分析平台 具体利用quantmod包实现对股票的量化分析 1.#1.API读取在线行情2.#加载quantmod包3.if(!require(quantmod)){4. instal ...
- Go语言打造以太坊智能合约测试框架(level3)
传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...
- Go语言打造以太坊智能合约测试框架(level1)
传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...
- go语言打造个人博客系统(二)
go语言打造个人博客系统(二) 在上篇文章go语言打造个人博客系统(一)中,我们了解了go语言的优点和go语言的数据库操作,本次我们会完成博客系统的后端开发. 博客系统后端接口开发 路由测试 ht ...
- c语言实现通讯录管理系统(c课程设计)
工具:Visual C++6.0 说明: 本系统基于C语言实现班级通讯录管理系统,为大一时学习C语言刚入门所做的课程设计.功能包括增.删.查.改等,非常适合初学者练手.通讯录包括的个人信息有姓名.学号 ...
- 《微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记1)WePY开发环境的安装
WePY的安装或更新都通过npm进行,全局安装或更新WePY命令行工具,使用以下命令: npm install wepy-cli -g 稍等片刻,成功安装后,即可创建WePY项目. 注意:如果npm安 ...
- 微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记4)支持React.js语法的Taro框架
Taro本身实现的情况类似于mpvue,mpvue的未来展望中也包含了支付宝小程序,现在的版本中,也可以使用不同的构建命令来构建出百度小程序的支持,如第10章所示,但是现在Taro先于mpvue实现了 ...
- # Pycharm打造高效Python IDE
Pycharm打造高效Python IDE 建议以scientific mode运行,在科学计算时,可以方便追踪变量变化,并且会提示函数的用法,比普通模式下的提示更加智能,一般在文件中引入了numpy ...
随机推荐
- 使用React简短代码动态生成栅格布局
使用React简短代码动态生成栅格布局 作为 TerminalMACS 的一个子进程模块 - React Web管理端,使用Ant Design Pro作为框架. 本文应用到的知识 1.样式文件les ...
- SV 自定义数据类型
概述 自定义类型 枚举类型 定义枚举值 自定义枚举类型 枚举类型之间进行赋值是可以的 枚举类型可以赋值给整型,整型不能直接赋值给枚举类型 枚举类型 + 1 ==> 会进行隐式的转换,枚举类型转换 ...
- VSCODE配置tasks.json
1.新建配置任务tasks.json 选择gcc.exe 可以在其中按需修改 { "version": "2.0.0", "tasks": ...
- 电机控制和Linux驱动开发哪个方向更好呢?
电机控制和Linux驱动开发哪个方向更好呢? 先说结论:任何一个领域,就像世间的五行,阴阳结合,虚实结合,利弊结合.对于哪个更好,不能一概而论,最重要的是要搞清楚,你更适合哪个? 1.共鸣 当我看到这 ...
- Security的一些配置
package com.example.demo.config; import com.example.demo.Service.UserDetailsServiceImpl; import com. ...
- WebApi的输出结果重写 OnActionExecuted
public override void OnActionExecuted(ActionExecutedContext context) { if (context.Exception != null ...
- [转帖]Web技术(六):QUIC 是如何解决TCP 性能瓶颈的?
文章目录 一.QUIC 如何解决TCP的队头阻塞问题? 1.1 TCP 为何会有队头阻塞问题 1.2 QUIC 如何解决队头阻塞问题 1.3 QUIC 没有队头阻塞的多路复用 二.QUIC 如何优化T ...
- [转帖]Clickhouse单机及集群部署详解
https://www.cnblogs.com/ya-qiang/p/13540016.html 一.ClickHouse简介 ClickHouse是近年来备受关注的开源列式数据库,主要用于数据分析( ...
- [转帖]关于linux:NUMA架构下的内存延迟区别测试
https://lequ7.com/guan-yu-linuxnuma-jia-gou-xia-de-nei-cun-yan-chi-qu-bie-ce-shi.html 当初的服务器物理机CPU个别 ...
- JRC Flink流作业调优指南
# 作者:京东物流 康琪 本文综合Apache Flink原理与京东实时计算平台(JRC)的背景,详细讲述了大规模Flink流作业的调优方法.通过阅读本文,读者可了解Flink流作业的通用调优措施,并 ...