目录

1、测试结果

2、整体思路

3、结构体的定义

4、核心函数搭建

5、模块代码解读

(1)、显示菜单

(2)、初始化通讯录

(3)、给通讯录增加容量

(4)、增加联系人

(5)、查找联系人

(6)、删除联系人

(7)、修改联系人

(8)、对通讯录里面的联系人按名字进行排序

(9)、显示通讯录

(10)、保存文件

(11)、加载文件信息

(12)、释放空间

6、代码整体实现

contact.h

contact.c

test.c


哈喽,友友们

今天来给大家分享一个通讯录的实现,包含了指针,结构体,动态内存分配以及文件的读写,文章有点长,完整通讯录代码在文章末尾处,希望大家能耐心看完并且有所收获哦

1、测试结果

这是最初使用此通讯录的结果,文件里面还没有联系人名单。

将此程序退出后,我们会发现在此工程路径下多了一个文本文件,里面记录着之前的联系人信息,当再次使用本程序时,文件里面保存的联系人信息会再加载进来。请看下图:

关于里面联系人的删除,查找,排序,修改就不一一在这里演示啦,不然截图可就太长了 ,有兴趣的友友们可以拿去在自己的编译器上测试一下看看效果哦。那现在就直接进入主题吧~~

2、整体思路

代码的整体风格呢还是和之前写的三子棋与扫雷一样,还是建了3个文件,还是先在contact.c文件里放各个函数的实现,然后在头文件contact.h中放这些函数的声明,这样在test.c文件中就可以直接引用contact.h,用contact.c中的函数啦,这样能保证主函数逻辑清晰,简洁利落,简单易懂。

3、结构体的定义

因为是通讯录,要记录每个人的姓名、性别、年龄、住址、电话号码等,因此我定义了一个联系人结构体,包含一个人的各种信息。

typedef struct PeoInfo
{char name[NAME_MAX];int age;char number[NUMBER_MAX];char adress[ADDR_MAX];char sex[SEX_MAX];
}PeoInfo;

然后为了方便管理通讯录里面的信息,我又建立了一个关于通讯录的结构体。

typedef struct Contact
{PeoInfo* data;//存放数据int capacity;//当前通讯录容量int sz;//实际有效信息数量
}Contact;

4、核心函数搭建

enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SORT,SHOW
};
void menu()
{printf("***************菜单****************\n");printf("****** 1.add        2.del    ******\n");printf("****** 3.search     4.modify ******\n");printf("****** 5.sort       6.show   ******\n");printf("****** 0.exit                ******\n");printf("***********************************\n");}
void test()
{Contact con;InitContact(&con);//初始化通讯录int input = 0;do{menu();printf("请选择->");scanf("%d", &input);switch (input){case ADD://增加联系人AddContact(&con);break;case DEL://删除联系人DeleteContact(&con);break;case SEARCH://查找联系人FindContact(&con);break;case MODIFY://修改联系人ModifyContact(&con);break;case SORT://对通讯录进行排序(按名字)SortContact(&con);break;case SHOW://显示联系人ShowContact(&con);break;case EXIT:SaveContact(&con);DestroyContact(&con);printf("退出通讯录\n");break;default:printf("选择错误,请重新选择!\n");break;}}while (input);
}

这里主要用的是do-while语句和switch语句来将各个函数串联起来,形成一个较为完整的工程。因为操作的对象是通讯录里面的信息,所以定义了一个通讯录类型的变量con。看这段代码应该不难发现基本上每一个函数的参数都是con。里面的涉及到的每一个函数我都会在下面一一讲解的。

5、模块代码解读

(1)、显示菜单

这个太简单了,直接上代码~

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

别急,菜单里面的各种功能都会在后面一一讲解的 。

(2)、初始化通讯录

因为通讯录最初是没有联系人的任何信息的,所以我们需要将它的实际有效信息数量置为0,然后申请一个PeoInfo大小的空间来存放信息,最初也是将data也就是联系人的各种信息置为空。再接着就是为设置此通讯录的容量。如果空间申请失败,则打印错误信息,方便后期的检查与维护。

但是如果不是第一次使用这个程序,则之前记录下来的联系人信息就会在启动该程序时自动加载进来,方便查看和修改。因此我利用文件知识写了一个加载信息的函数LoadContact()(别急

后面也会讲它的具体实现),在初始化时进行加载。

void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;PeoInfo *tmp = (PeoInfo*)malloc(DEFAULT_SZ *sizeof(PeoInfo));if (tmp != NULL){pc->data = tmp;}else{printf("InitContact()::%s\n", strerror(errno));return;}pc->capacity = DEFAULT_SZ;LoadContact(pc);}

(3)、给通讯录增加容量

这个函数就是利用动态内存管理的知识来实现。每次当通讯录pc的容量capacity与实际存放的有效信息数(存放在通讯录中的人数)相等时,我就需要对通讯录进行增容,以便后续联系人的添加。也就是利用realloc()函数更改通讯录的容量(内存)。

int  addcapacity(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){PeoInfo* tmp = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity+ 2));if (tmp != NULL){pc->data = tmp;pc->capacity += 2;//printf("增容成功\n");return 1;}else{printf("addcapacity()::%s\n", strerror(errno));return 0;}}return 1;}

(4)、增加联系人

AddContact()这个函数是用做增添联系人的,调用这个函数就代表要在通讯录里面增加联系人信息,但是每当增添联系人信息时,都需要对通讯录的容量进行一个判断,如果通讯录满了,我就要给它进行增容,因此在AddContact()函数里面的最开始我调用了自己写的一个函数,其功能是判断通讯录是否曾容,是的话就增容,不是的话就暂时不增容,增容成功和判断为不增容都返回1,增容失败则返回0。判断通讯录的容量充足或增容成功之后才可对通讯录进行联系人的添加。

其实添加联系人很简单,就是对通讯录结构体里面的联系人类型data进行赋值,每次增添一个联系人之后通讯录pc的实际有效信息人数sz就要加一。

void AddContact(Contact* pc)
{   assert(pc);int i=addcapacity(pc);if (i){printf("请输入姓名->");scanf("%s", pc->data[pc->sz].name);printf("请输入性别->");scanf("%s", pc->data[pc->sz].sex);printf("请输入年龄->");scanf("%d", &(pc->data[pc->sz].age));printf("请输入住址->");scanf("%s", pc->data[pc->sz].adress);printf("请输入电话->");scanf("%s", pc->data[pc->sz].number);pc->sz++;printf("添加联系人成功!\n");}else{printf("AddContact::%s\n", strerror(errno));}}

(5)、查找联系人

联系人的信息都存放在联系人类型的数组里,查找联系人其实就相当于对数组的一个遍历,当输入要查找的联系人姓名时,就会对此数组进行遍历。找到就返回数组下标,找不到就返回-1。

int FindPeoInfo(char* name, Contact* pc)//查找联系人,返回其下标
{int i = 0;for (i = 0; i < pc->sz; i++){if (*name == *(pc->data[i].name)){return i;}}return -1;
}

(6)、删除联系人

删除联系人其实就是对被删除的联系人进行覆盖,将要删除的联系人后面的联系人信息依次往前移,而删除联系人之前我们需要先找到该联系人对应的数组下标,就需要调用FindPeoInfo()函数,然后再将此元素的下一个元素及后面元素依次向前移进行覆盖。覆盖完成之后,再将通讯录的实际有效信息人数sz减一。

void DeleteContact(Contact* pc)//删除联系人
{char name[NAME_MAX] = "0";int i = 0;printf("请输入要删除的联系人姓名->");scanf("%s", name);//查找联系人int flag=FindPeoInfo(name,pc);if (flag != -1){for (i = flag; i < pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功!\n");}else{printf("没有找到您需要删除的人!\n");}
}

(7)、修改联系人

修改联系人就是将原来赋值的联系人类型data数组中的元素再次赋值,达到更改的一个效果。同样的,在进行修改之前仍然要先调用FindPeoInfo()来查找要修改的联系人。

void ModifyContact(Contact* pc)//修改联系人
{char name[NAME_MAX] = "0";printf("请输入要修改的联系人姓名->");scanf("%s", name);int flag = FindPeoInfo(name, pc);if (flag == -1){printf("查无此人\n");return;}else{int input = 0;do{/*char rename[NAME_MAX] = "0";int reage = 0;char resex[] = "0";char readdress[] = "0";char*/printf("1.姓名  2.年龄  3.性别  4.住址  5.电话  0.退出\n");printf("请输入要修改的选项(按0退出修改)->");scanf("%d", &input);switch (input){case 1:printf("请输入改正后的姓名->");scanf("%s", pc->data[flag].name);break;case 2:printf("请输入改正后的年龄->");scanf("%d", &(pc->data[flag].age));break;case 3:printf("请输入改正后的性别->");scanf("%s", pc->data[flag].sex);break;case 4:printf("请输入改正后的住址->");scanf("%s", pc->data[flag].adress);break;case 5:printf("请输入改正后的电话->");scanf("%s", pc->data[flag].number);break;case 0:break;default:printf("输入错误,请重新输入!\n");break;}} while(input);printf("修改成功!\n");}}

(8)、对通讯录里面的联系人按名字进行排序

这个也很简单,就是调用qsort()函数对结构体类型中的那字符串name进行排序。就不过多赘述啦,直接看代码~

//对联系人进行排序(按名字)
int compare_Peo(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), compare_Peo);printf("排序成功\n");ShowContact(pc);
}

(9)、显示通讯录

这个函数的实现就是先判断通讯录的实际有效信息人数是否为0,如果为0的话,说明通讯录里面没有人,如果不为0,则对联系人类型的data数组进行遍历,一一打印。

void ShowContact(Contact* pc)//显示通讯录
{assert(pc);if (pc->sz == 0){printf("通讯录里无联系人!\n");}else{int i = 0;printf("%-7s\t%-7s\t%-6s\t%-20s\t%-15s\n", "姓名", "性别", "年龄", "住址", "电话");for (i = 0; i < pc->sz; i++){printf("%-7s\t%-7s\t%-6d\t%-20s\t%-15s\n",pc->data[i].name, pc->data[i].sex, pc->data[i].age,pc->data[i].adress, pc->data[i].number);}}
}

(10)、保存文件

这个函数的功能就是将此次对通讯录里面信息的修改以二进制的形式写入文件,保存到此工程的路径下,方便下次启动此程序时查看。

//保存文件
void SaveContact(Contact* pc)
{FILE* fp = fopen("contact1.txt", "wb");if (fp == NULL){printf("SaveContact::open for writting:%s", strerror(errno));return;}//写入文件int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, fp);}//关闭文件fclose(fp);fp = NULL;
}

(11)、加载文件信息

当启动此程序时,我们要先对通讯录进行初始化(这一步在上面有讲过),然后再将之前保存的联系人信息加载进来,这样方便此次用此程序对之前的联系人信息进行修改查看。读文件信息时也相当于是添加联系人了,因此在读入之前也需要判断通讯录容量,看是否需要对其增容。

void LoadContact(Contact* pc)
{//打开文件FILE* pf = fopen("contact1.txt", "rb");if (pf == NULL){printf("LoadContact::open for reading:%s\n", strerror(errno));return;}//读文件PeoInfo tmp = { 0 };while (fread(&tmp, sizeof(PeoInfo), 1, pf)){addcapacity(pc);pc->data[pc->sz] = tmp;pc->sz++;}//关闭文件fclose(pf);pf = NULL;
}

(12)、释放空间

因为通讯录中的联系人类型的数组的空间是动态申请的,所以结束此程序时我们先用SaveContact()函数将其联系人信息保存下来,然后再将此空间释放,将指向此空间的指针置为NULL,以免被非法访问。

void DestroyContact(Contact* pc)//销毁
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}

6、代码整体实现

contact.h

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
//#define MAX_SIZE 10
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 30
#define NUMBER_MAX 12
#define DEFAULT_SZ 3typedef struct PeoInfo
{char name[NAME_MAX];int age;char number[NUMBER_MAX];char adress[ADDR_MAX];char sex[SEX_MAX];
}PeoInfo;typedef struct Contact
{PeoInfo* data;//存放数据int capacity;//当前通讯录容量int sz;//实际有效信息数量
}Contact;void InitContact(Contact* pc);//初始化通讯录
void AddContact(Contact* pc);//增加联系人
void ShowContact(Contact* pc);//显示通讯录
void DeleteContact(Contact* pc);//删除联系人
int FindPeoInfo(char* name, Contact* pc);//查找联系人,返回其下标
void FindContact(Contact* pc);//查找联系人
void ModifyContact(Contact* pc);//修改联系人
void SortContact(Contact* pc);//对联系人进行排序(按名字)
int addcapacity(Contact* pc);//增容
void DestroyContact(Contact* pc);//销毁通讯录
void LoadContact(Contact* pc);//加载通讯录
void SaveContact(Contact* pc);//保存通讯录

contact.c

#include"contact.h"//初始化通讯录
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;PeoInfo *tmp = (PeoInfo*)malloc(DEFAULT_SZ *sizeof(PeoInfo));if (tmp != NULL){pc->data = tmp;}else{printf("InitContact()::%s\n", strerror(errno));return;}pc->capacity = DEFAULT_SZ;LoadContact(pc);}
//判断是否增容
int  addcapacity(Contact* pc)
{assert(pc);if (pc->sz == pc->capacity){PeoInfo* tmp = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity+ 2));if (tmp != NULL){pc->data = tmp;pc->capacity += 2;//printf("增容成功\n");return 1;}else{printf("addcapacity()::%s\n", strerror(errno));return 0;}}return 1;}
//加载文件
void LoadContact(Contact* pc)
{//打开文件FILE* pf = fopen("contact1.txt", "rb");if (pf == NULL){printf("LoadContact::open for reading:%s\n", strerror(errno));return;}//读文件PeoInfo tmp = { 0 };while (fread(&tmp, sizeof(PeoInfo), 1, pf)){addcapacity(pc);pc->data[pc->sz] = tmp;pc->sz++;}//关闭文件fclose(pf);pf = NULL;
}//增加联系人
void AddContact(Contact* pc)
{   assert(pc);int i=addcapacity(pc);if (i){printf("请输入姓名->");scanf("%s", pc->data[pc->sz].name);printf("请输入性别->");scanf("%s", pc->data[pc->sz].sex);printf("请输入年龄->");scanf("%d", &(pc->data[pc->sz].age));printf("请输入住址->");scanf("%s", pc->data[pc->sz].adress);printf("请输入电话->");scanf("%s", pc->data[pc->sz].number);pc->sz++;printf("添加联系人成功!\n");}else{printf("AddContact::%s\n", strerror(errno));}}
void ShowContact(Contact* pc)//显示通讯录
{assert(pc);if (pc->sz == 0){printf("通讯录里无联系人!\n");}else{int i = 0;printf("%-7s\t%-7s\t%-6s\t%-20s\t%-15s\n", "姓名", "性别", "年龄", "住址", "电话");for (i = 0; i < pc->sz; i++){printf("%-7s\t%-7s\t%-6d\t%-20s\t%-15s\n",pc->data[i].name, pc->data[i].sex, pc->data[i].age,pc->data[i].adress, pc->data[i].number);}}
}
int FindPeoInfo(char* name, Contact* pc)//查找联系人,返回其下标
{int i = 0;for (i = 0; i < pc->sz; i++){if (*name == *(pc->data[i].name)){return i;}}return -1;
}void DeleteContact(Contact* pc)//删除联系人
{char name[NAME_MAX] = "0";int i = 0;printf("请输入要删除的联系人姓名->");scanf("%s", name);//查找联系人int flag=FindPeoInfo(name,pc);if (flag != -1){for (i = flag; i < pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功!\n");}else{printf("没有找到您需要删除的人!\n");}
}
void FindContact(Contact* pc)//查找联系人
{char name[NAME_MAX] = "0";printf("请输入要查找的联系人姓名->");scanf("%s", name);int flag = FindPeoInfo(name, pc);if (flag != -1){printf("%-7s\t%-7s\t%-6s\t%-20s\t%-15s\n", "姓名", "性别", "年龄", "住址", "电话");printf("%-7s\t%-7s\t%-6d\t%-20s\t%-15s\n",pc->data[flag].name, pc->data[flag].sex, pc->data[flag].age,pc->data[flag].adress, pc->data[flag].number);}else{printf("查无此人!\n");}
}void ModifyContact(Contact* pc)//修改联系人
{char name[NAME_MAX] = "0";printf("请输入要修改的联系人姓名->");scanf("%s", name);int flag = FindPeoInfo(name, pc);if (flag == -1){printf("查无此人\n");return;}else{int input = 0;do{/*char rename[NAME_MAX] = "0";int reage = 0;char resex[] = "0";char readdress[] = "0";char*/printf("1.姓名  2.年龄  3.性别  4.住址  5.电话  0.退出\n");printf("请输入要修改的选项(按0退出修改)->");scanf("%d", &input);switch (input){case 1:printf("请输入改正后的姓名->");scanf("%s", pc->data[flag].name);break;case 2:printf("请输入改正后的年龄->");scanf("%d", &(pc->data[flag].age));break;case 3:printf("请输入改正后的性别->");scanf("%s", pc->data[flag].sex);break;case 4:printf("请输入改正后的住址->");scanf("%s", pc->data[flag].adress);break;case 5:printf("请输入改正后的电话->");scanf("%s", pc->data[flag].number);break;case 0:break;default:printf("输入错误,请重新输入!\n");break;}} while(input);printf("修改成功!\n");}}//对联系人进行排序(按名字)
int compare_Peo(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{qsort(pc->data, pc->sz, sizeof(pc->data[0]), compare_Peo);printf("排序成功\n");ShowContact(pc);
}
void DestroyContact(Contact* pc)//空间销毁
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}
//保存文件
void SaveContact(Contact* pc)
{FILE* fp = fopen("contact1.txt", "wb");if (fp == NULL){printf("SaveContact::open for writting:%s", strerror(errno));return;}//写入文件int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, fp);}//关闭文件fclose(fp);fp = NULL;
}

test.c

#include"contact.h"
enum Option
{EXIT,ADD,DEL,SEARCH,MODIFY,SORT,SHOW
};
void menu()
{printf("***************菜单****************\n");printf("****** 1.add        2.del    ******\n");printf("****** 3.search     4.modify ******\n");printf("****** 5.sort       6.show   ******\n");printf("****** 0.exit                ******\n");printf("***********************************\n");}
void test()
{Contact con;InitContact(&con);//初始化通讯录int input = 0;do{menu();printf("请选择->");scanf("%d", &input);switch (input){case ADD://增加联系人AddContact(&con);break;case DEL://删除联系人DeleteContact(&con);break;case SEARCH://查找联系人FindContact(&con);break;case MODIFY://修改联系人ModifyContact(&con);break;case SORT://对通讯录进行排序(按名字)SortContact(&con);break;case SHOW://显示联系人ShowContact(&con);break;case EXIT:SaveContact(&con);DestroyContact(&con);printf("退出通讯录\n");break;default:printf("选择错误,请重新选择!\n");break;}}while (input);
}int main()
{test();return 0;
}

分享就到这里啦,怎么样,是不是很简单呢,有疑问或者看不懂的友友们可以问我哦,如果发现哪

里写的有问题或者可以改进的也可以提出来,评论区或私聊都可以,我是很希望收到大家的建议的哦

C语言实现通讯录(含文件保存)相关推荐

  1. C语言实现通讯录(使用文件保存信息)

    这两天把动态内存还有文件函数这部分的课听了一下,也跟着把通讯录升级了一下 存储元素不再是固定的了,当存储的元素等于上限时内存就动态增长 每次退出信息又会销毁,可以用fwrite 和 fread让它保存 ...

  2. Python 基于tkinter模块的GUI可视化学生成绩管理系统实现(含文件保存)

    学生成绩管理系统 1. 标准模块导入 2.完整代码 3.文件保存模块 作者:潇 版本:1.0 面向对象,带日志,带异常处理的,带密码加密 第一次执行会生成数据库和csv文件,以后添加的数据会自动保存到 ...

  3. C语言实现动态通讯录(附带文件保存)

    ✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!!

  4. 【C语言】通讯录(文件版)

    这里写目录标题 一.通讯录说明 二.效果展示 三.代码展示 一.通讯录说明 通讯录拥有增.删.查.改等功能. 本文主要介绍通讯录文件版本,以动态版本的方式开辟空间. 文件版本功能:通讯录退出后,之前保 ...

  5. c语言管理系统信息以文件保存,求大神给一份能用的c语言的学籍管理系统:且能进行文件保存...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #pragma comment(lib,"libmysql.lib") void showmenu ...

  6. 【240行拿下】基于C语言 实现通讯录管理系统 带文件保存及读取功能

    一 首言         学校布置的小作业希望对你有帮助,完整代码在文章结尾为方便阅读代码基本都有注释.代码是在满足老师要求下,尽量减少功能和代码方便同学理解的思想上完成的 (完成7个功能,功能性代码 ...

  7. C语言文件操作+通讯录实现文件操作

    文章目录 前言 一.为什么使用文件 二.什么是文件 三.文件的打开和关闭 四.文件的顺序读写 五.文件的随机读写 六.文本文件和二进制文件 七.文件读取结束的判定 八.文件缓冲区 前言 电脑文件,也可 ...

  8. C语言实现通讯录【二】(动态内存开辟,文件数据存储)

    C语言实现通讯录[二] 在C语言实现通讯录[一]的基础上进行优化,主要实现两大模块: 动态内存开辟 文件数据存储 动态内存开辟: 考虑到通讯录的大小无法固定,在C语言实现通讯录[一]版本上定义一个足够 ...

  9. Dymola使用C语言间接调用含第三方库Python文件流程

    Dymola函数中调用python 一.语言配置介绍 Dymola:Dymola 2022 trail version C/C++与python见上一篇:调用python文件(含第三方库)时的C/C+ ...

最新文章

  1. Logistic regression--转
  2. 中国蚁剑 代码解压出错:【object Object】解决方法
  3. CVPR2021开源项目,带你傲游宇宙!
  4. zepto tap “点透”研究
  5. 那些年,我们一起追的女孩。
  6. 系统进程网络流量监控软件
  7. 创业之前必须要做的八个测试
  8. SSM框架下打卡签到增加积分功能的实现
  9. 宁波大学计算机非全,宁波大学考研:全日制和非全日制的6大区别,很多人不知道...
  10. MPA海洋捕食者算法学习笔记
  11. uniapp绘制分享海报
  12. 新建STM32F427IIH标准库工程
  13. Blender_7_倒角
  14. Android适配全面屏
  15. SYSTEM_INFO
  16. 模拟退火算法(Simulated Annealing,SA)的全面讲解及python实现
  17. 面向对象设计的3个基本特征和5个原则
  18. 如何用键盘打开设备管理器里计算机的属性,技巧:在Windows10系统中使用键盘打开设备管理器的三种方法...
  19. K-Means(K-均值)、k-median聚类算法机器学习
  20. tpl怎么口_解决tplogin.cn打开是电信登录页面的办法是什么?

热门文章

  1. Open3D 曲面重建
  2. 模糊查询银行卡号mysql_mysql like查询字符串示例语句
  3. php ftp 时间不对,ftp时间差8小时引起的?
  4. LeetCode/LintCode 题解丨一周爆刷字符串:旋转字符数组
  5. 费雪信息 (Fisher information)
  6. unity沙子堆积_unity游戏动态体积雾沙尘暴管理渲染插件Dynamic Fogamp;Mist 6.5 - 素材巷...
  7. 产品三维可视化展示之服装3d立体展示
  8. 浏览器隐私模式真的可以保证我们的隐私不被透露吗?
  9. 计算机毕业设计php+vue基于微信小程序的房屋租赁小程序
  10. 抓取APP中的素材步骤之一