之前的博客里我们实现了静态的通讯录。|ू・ω・` )
静态通讯录,适合初学者的手把手一条龙讲解_陈大大陈的博客-CSDN博客
这个版本的通讯录无法实现容量的动态增加,也无法保存我们输入的信息。(•́へ•́╬)
静态通讯录,是直接开辟100块空间内存来供使用,但是这样就会导致问题:如果人太少,要存入的联系人只有10个,造成空间浪费,又或者人太多,需要存进200个人,内存中可存储的空间又会不够。ᕙ༼ ͝°益° ༽ᕗ
每当我们关闭通讯录时,信息随之消失,我们需要再次输入信息,这是非常麻烦且不合理的。
我们今天就来实现可以实现保存信息功能的动态通讯录。
首先是将静态通讯录改写成动态通讯录。
目录
静态通讯录源码
动态通讯录
初始化
动态扩容
信息的输入
数据的删除
动态通讯录源码
可保存信息的动态通讯录
可保存的动态通讯录源码
静态通讯录源码
//contact.h部分
#pragma once
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
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 sz;
}Contact;
void InitContact(Contact* pc);
void AddContact(Contact* pc);
void DelContact(Contact* pc);
void SortContact(Contact* pc);
int SearchContact(Contact* pc);
void ModifyContact(Contact* pc);
void ShowContact(Contact* pc);
int FindByName(Contact* pc, char name[]);
//contact.c
#include"contact.h"
void InitContact(Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
void AddContact(Contact* pc)
{
if (pc->sz == 100)
{
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 DelContact(Contact* pc)
{
char name[MAX_NAME];
if (pc->sz == 0)
{
printf("通讯录已满\n");
return;
}
printf("输入要删除的人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
for (int i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
break;
}
}
return -1;
}
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
int SearchContact(Contact* pc)
{
char name[12] = { 0 };
printf("请输入要查找的人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("此人信息不存在\n");
}
printf("此人信息如下:\n");
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);
return pos;
}
void ShowContact(Contact* pc)
{
int i = 0;
printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-10s %-4d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
void ModifyContact(Contact* pc)
{
printf("输入要修改的人的名字:>");
char name[12] = { 0 };
scanf("%s", name);
int pos = FindByName(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");
}
void SortContact(Contact* pc)
{
qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
}
//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("'********** 0.exit ********\n");
printf("'****************************************\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
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 SORT:
SortContact(&con);
break;
case EXIT:
printf("退出");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
动态通讯录
实现上述的动态增容功能。
要写动态的通讯录,我们可以在结构体中再定义一个表示最大容量的变量。
当通讯录中有效信息的个数和容量相等时,我们就将其扩容,增大分配的内存空间来保存更多信息。并让指针data指向这一空间。
typedef struct Contact
{
PeoInfo *data;
int sz;
int capacity;
}Contact;
初始化
不再是简单的将开辟的空间置为0。
我们定义两个数字DEFAULT_SZ和INC_SZ,分别是通讯录一开始的空间和每次扩容时增长的空间。
#define DEFAULT_SZ 3
#define INC_SZ 2
初始化时,首先开辟大小为 sizeof(PeoInfo) * DEFAULT_SZ的空间。
如果开辟失败就报错,反之则将sz置为0,将容量变为 上面说的DEFAULT_SZ。
void InitContact(Contact* pc)
{
pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SZ);
if (pc->data == NULL)
{
printf("通讯录初始化失败:%s\n",strerror(errno));
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
动态扩容
当有效数字个数和容量相等时,我们就将其扩容,每次增加INC_SZ*sizeof(PeoInfo)的空间。
扩容成功之后不要忘记将新空间的地址赋给data,这是我踩坑的地方,大家不要也掉进去啊哈哈哈。
扩容成功,容量加2,返回1,失败则返回0,这两个返回值一会我们会用到。
int CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
PeoInfo *ptr = (PeoInfo*)realloc(pc->data,sizeof(PeoInfo) * (pc->capacity + INC_SZ));
if (ptr == NULL)
{
printf("CheckCapacity:%s\n",strerror(errno));
return 0;
}
pc->data = ptr;
pc->capacity += 2;
printf("扩容成功,当前容量%d\n",pc->capacity);
return 1;
}
}
信息的输入
void AddContact(Contact* pc)
{
if (CheckCapacity(pc) == 0)
{
printf("空间不够,扩容失败\n");
return;
}
else
{
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");
}
}
我们用到刚才的返回值,为1时则输入新数据,否则就报错之后返回。
数据的删除
void DestoryContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
printf("释放内存...\n");
}
这一块没什么好说的,大家记得free之后将data置为空指针就好。
动态通讯录源码
//contact.h
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#define DEFAULT_SZ 3
#define INC_SZ 2
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
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 AddContact(Contact* pc);
void DelContact(Contact* pc);
void SortContact(Contact* pc);
int SearchContact(Contact* pc);
void ModifyContact(Contact* pc);
void ShowContact(Contact* pc);
int FindByName(Contact* pc, char name[]);
void DestoryContact(Contact* pc);
//contact.c
#include"contact.h"
void InitContact(Contact* pc)
{
pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SZ);
if (pc->data == NULL)
{
printf("通讯录初始化失败:%s\n",strerror(errno));
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
int CheckCapacity(Contact* pc)
{
if (pc->sz >= pc->capacity)
{
PeoInfo *ptr = (PeoInfo*)realloc(pc->data,sizeof(PeoInfo) * (pc->capacity + INC_SZ));
if (ptr == NULL)
{
printf("CheckCapacity:%s\n",strerror(errno));
return 0;
}
pc->data = ptr;
pc->capacity += 2;
printf("扩容成功,当前容量%d\n",pc->capacity);
return 1;
}
}
void DestoryContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
printf("释放内存...\n");
}
void AddContact(Contact* pc)
{
if (CheckCapacity(pc) == 0)
{
printf("空间不够,扩容失败\n");
return;
}
else
{
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 DelContact(Contact* pc)
{
char name[MAX_NAME];
if (pc->sz == 0)
{
printf("通讯录已满\n");
return;
}
printf("输入要删除的人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
for (int i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
break;
}
}
return -1;
}
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
int SearchContact(Contact* pc)
{
char name[12] = { 0 };
printf("请输入要查找的人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("此人信息不存在\n");
}
printf("此人信息如下:\n");
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);
return pos;
}
void ShowContact(Contact* pc)
{
int i = 0;
printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-10s %-4d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
void ModifyContact(Contact* pc)
{
printf("输入要修改的人的名字:>");
char name[12] = { 0 };
scanf("%s", name);
int pos = FindByName(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");
}
void SortContact(Contact* pc)
{
qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
}
#pragma once
//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("'********** 0.exit ********\n");
printf("'****************************************\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
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 SORT:
SortContact(&con);
break;
case EXIT:
DestoryContact(&con);
printf("通讯录销毁成功\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
可保存信息的动态通讯录
这一块的功能涉及到了文件的操作,不了解的朋友们可以看看这篇博客。
写程序必会的C语言文件操作(上)附手绘图详解_陈大大陈的博客-CSDN博客
保存功能的实现
我们用二进制只写的方式来创建一个叫Contact.dat的文件来存放信息。
用二进制输出 函数fwrite将pc->data里的 信息写到文件流里,每次写一个大小为sizeof(struct PeoInfo)的数据。
void SaveContact(Contact* pc)
{
FILE* pf = fopen("Contact.dat", "wb");
if (pf == NULL)
{
perror("Condata:fopen:");
return;
}
for (int i = 0; i < pc->sz; i++)
{
fwrite(pc->data+i, sizeof(struct PeoInfo), 1, pf);
}
fclose(pf);
pf = NULL;
printf("保存成功...\n");
}
运行一次,发现 Contact.dat文件里面出现很多乱码,不过不用担心,这是二进制的表示形式,计算机能读懂就行了!(*^▽^*)
读取功能的实现
我们成功将信息写到了文件里,那怎么确保下次打开文件时能读取信息呢?
当然是反其道而行之,用fread函数来将文件中的信息读取到内存里。
我们定义一个tmp来记录被读取的信息,一次读一个,然后将每一次读取到的值赋给data对应的位置。让sz++。
void LoadContact(Contact* pc)
{
//打开文件
FILE*pf=fopen("Contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact:fopen");
return;
}
//读文件
PeoInfo tmp;
while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
如图,我们之前输入了9个数据成功保存,再次运行代码发现扩容成功。
展示信息,数据成功保存,保存功能完美实现!(✪ω✪)文章来源:https://www.toymoban.com/news/detail-416486.html
可保存的动态通讯录源码
//contact.h
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#define DEFAULT_SZ 3
#define INC_SZ 2
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
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 AddContact(Contact* pc);
void DelContact(Contact* pc);
void SortContact(Contact* pc);
int SearchContact(Contact* pc);
void ModifyContact(Contact* pc);
void ShowContact(Contact* pc);
int FindByName(Contact* pc, char name[]);
void DestoryContact(Contact* pc);
void SaveContact(Contact* pc);
void LoadContact(Contact* pc);
//contact.c
#include"contact.h"
void InitContact(Contact* pc)
{
pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * DEFAULT_SZ);
if (pc->data == NULL)
{
printf("通讯录初始化失败:%s\n",strerror(errno));
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
int CheckCapacity(Contact* pc)
{
if (pc->sz >= pc->capacity)
{
PeoInfo *ptr = (PeoInfo*)realloc(pc->data,sizeof(PeoInfo) * (pc->capacity + INC_SZ));
if (ptr == NULL)
{
printf("CheckCapacity:%s\n",strerror(errno));
return 0;
}
pc->data = ptr;
pc->capacity += 2;
printf("扩容成功,当前容量%d\n",pc->capacity);
return 1;
}
}
void DestoryContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
printf("释放内存...\n");
}
void AddContact(Contact* pc)
{
if (CheckCapacity(pc) == 0)
{
printf("空间不够,扩容失败\n");
return;
}
else
{
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 DelContact(Contact* pc)
{
char name[MAX_NAME];
if (pc->sz == 0)
{
printf("通讯录已满\n");
return;
}
printf("输入要删除的人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
for (int i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
break;
}
}
return -1;
}
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
int SearchContact(Contact* pc)
{
char name[12] = { 0 };
printf("请输入要查找的人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("此人信息不存在\n");
}
printf("此人信息如下:\n");
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);
return pos;
}
void ShowContact(Contact* pc)
{
int i = 0;
printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-10s %-4d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
void ModifyContact(Contact* pc)
{
printf("输入要修改的人的名字:>");
char name[12] = { 0 };
scanf("%s", name);
int pos = FindByName(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");
}
void SortContact(Contact* pc)
{
qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
}
void SaveContact(Contact* pc)
{
FILE* pf = fopen("Contact.dat", "wb");
if (pf == NULL)
{
perror("Condata:fopen:");
return;
}
for (int i = 0; i < pc->sz; i++)
{
fwrite(pc->data+i, sizeof(struct PeoInfo), 1, pf);
}
fclose(pf);
pf = NULL;
printf("保存成功...\n");
}
void LoadContact(Contact* pc)
{
//打开文件
FILE*pf=fopen("Contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact:fopen");
return;
}
//读文件
PeoInfo tmp;
while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
#pragma once
//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("'********** 0.exit ********\n");
printf("'****************************************\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
int main()
{
int input = 0;
Contact con;
InitContact(&con);
LoadContact(&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 SORT:
SortContact(&con);
break;
case EXIT:
SaveContact(&con);
DestoryContact(&con);
printf("通讯录销毁成功\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
这篇博客旨在总结我自己阶段性的学习,要是能帮助到大家,那可真是三生有幸!😀如果觉得我写的不错的话还请点个赞和关注哦~我会持续输出编程的知识的!🌞🌞🌞 文章来源地址https://www.toymoban.com/news/detail-416486.html
到了这里,关于【创作赢红包】循序渐进的全版本通讯录详解,可保存信息的动态通讯录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!