异世界历险之数据结构世界(通讯录)
异世界历险之数据结构世界(通讯录)
前言
异世界公历25年3月21日,冒险者小Y走进了草丛,(一阵强劲的音乐)野生的通讯录跳出来了,小Y开始战斗吧!!!
通讯录介绍
通讯录是名字,性别,年龄,地址,电话号码等数据集合,与顺序表的功能不谋而合.
通讯录实现
具体实现方法可以参考顺序表:异世界历险之数据结构世界(顺序表城)
ps:图片中SORT是5,SHOW是6(作者笔误)
1.前置准备
**逻辑解释:
在实现通讯录之前,我们需要定义联系人信息的结构体,并使用宏定义来设置各个字段的最大长度。此外,我们还需要定义通讯录的结构体,包括动态数组、容量和大小等属性。
Contact.h
#pragma once
#define NAME_MAX 6
#define GENDER_MAX 4
#define TEL_MAX 20
#define ADDR_MAX 20//宏定义利于区分和修改
struct personInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
};//定义联系人类型,和 int,char等类型类似
typedef struct personInfo peoInfo;//简化类型
struct Contact
{
peoInfo* data;
int capacity;
int size;
};//与顺序表类似,但储存数据类型不同(一个int,一个peoInfo)
typedef struct Contact Contact;
enum OPPTION
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
SHOW
};//枚举类型使代码可读性提高
test.c
# include"Contact.h"
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");
}
int main()
{
int input = 0;
do
{
void menu();
printf("输入你的选择\n");
scanf("%d", &input);
switch(input)
{
case ADD:
break;
case DEL:
break;
case SEARCH:
break;
case MODIFY:
break;
case SORT:
break;
case SHOW:
break;
case EXIT:
break;
default :
printf("输入错误,重新输入!!!\n");
break;
}
} while (input);
}//基础界面和操作选择
PS:读者要牢记自定义类型peoInfo和int,char等系统自带类型无异这一前提.
2定义与初始化
逻辑解释:
初始化通讯录的逻辑是将动态数组置为空,并将容量和大小初始化为0。
//初始化函数
void ContactInit(Contact* ps)
{ assert(ps);
ps-> data = NULL;
ps->capacity = ps->size = 0;
}
3.添加联系人
**逻辑解释:
添加联系人之前,需要检查动态数组的容量是否足够。如果容量不足,则需要动态扩容。扩容的策略是将容量翻倍,以确保有足够的空间存储新的联系人。
//空间检查函数
void CheckCapacity(Contact*ps)
{
assert(ps);
if (ps->capacity ==ps->size)
{
int newcapacity = 0;
newcapacity = ps->capacity == 0 ? 8 : 2 * ps->capacity;//三目操作符
peoInfo* str = (peoInfo*)malloc(sizeof(peoInfo) * newcapacity);
if (str == NULL)
{
perror("malloc fail !!!");
exit(1);
}
ps->data = str;
ps->capacity = newcapacity;//模式化处理
}
}
//添加函数
void ContactAdd(Contact* ps)
{
assert(ps);
CheckCapacity(ps);//先判断空间大小,再进行添加
printf("输入名字:\n");
scanf("%s", ps->data[ps->size].name);
printf("输入性别:\n");
scanf("%s", ps->data[ps->size].gender);
printf("输入年龄:\n");
scanf("%d", &ps->data[ps->size].age);
printf("输入电话号码:\n");
scanf("%s", ps->data[ps->size].tel);
printf("输入地址:\n");
scanf("%s", ps->data[ps->size].addr);
ps->size++;
}
PS:除年龄外其余的元素都没有取地址,是因为字符串首元素就是地址。
效果展示:
4.删除联系人
逻辑解释:
删除联系人需要先通过名字查找目标联系人。如果找到,则将目标联系人之后的所有联系人向前移动一位,覆盖目标联系人,然后减少通讯录的大小。
//查找函数
int ContactFind(Contact* ps, char name[])
{
for (int i = 0; i < ps->size; i++)
{
if (strcmp(ps->data[i].name,name)==0)//字符串只能strcmp函数比较
{
return i;
}
}
return -1;
}
//删除函数
void ContactDel(Contact* ps)
{
if (ps->size == 0)
{
printf("联系人为空,无法删除!!!\n");
return;
}
printf("请输入删除人员名字:\n");//使用名字查找
char name[NAME_MAX];
scanf("%s", name);
int pos = ContactFind(ps,name);//查找函数
if (pos == -1)
{
printf("删除的人不存在!!!\n");
}
else
{
for (int i = pos; i < ps ->size-1; i++)
{
ps->data[i] = ps->data[i + 1];
}//前进一位,覆盖要删除对象
ps->size--;
printf("删除成功!!!\n");
}
}
效果展示:
5.查找联系人
逻辑解释:
查找联系人通过名字进行匹配。如果找到,则打印该联系人的详细信息;否则提示未找到。
//查找函数
void ContactSearch(Contact* ps)
{
if (ps->size == 0)
{
printf("联系人为空,无法查找!!!\n");
return;
}
printf("请输入要查找的名字:\n");
char name[NAME_MAX];
scanf("%s", name);
int pos = ContactFind(ps, name);
if (pos == -1)
{
printf("没有该联系人!!!\n");
}
else
{
printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
ps->data[pos].name,
ps->data[pos].gender,
ps->data[pos].age,
ps->data[pos].tel,
ps->data[pos].addr
);
}
}
效果展示:
6.修改联系人
逻辑解释:
修改联系人信息需要先通过名字查找目标联系人。如果找到,则更新该联系人的所有信息。
//修改函数
void ContactModify(Contact* ps)
{
if (ps->size == 0)
{
printf("联系人为空,无法修改!!!\n");
return;
}
printf("请输入要修改的名字:\n");
char name[NAME_MAX];
scanf("%s", name);
int pos = ContactFind(ps, name);
if (pos == -1)
{
printf("没有该联系人\n");
return;
}
else
{
printf("开始修改…………\n");
printf("请输入名字:\n");
scanf("%s", ps->data[pos].name);
printf("请输入年龄:\n");
scanf("%d", &ps->data[pos].age);
printf("请输入性别:\n");
scanf("%s", ps->data[pos].gender);
printf("请输入电话:\n");
scanf("%s", ps->data[pos].tel);
printf("请输入地址:\n");
scanf("%s", ps->data[pos].addr);
printf("成功输入联系人!!!\n");
}
}
效果展示:
7.排序联系人
逻辑解释:
排序功能使用快速排序算法,可以根据名字或年龄对联系人进行排序。
//比较
void cmp_name(const void* str1,const void* str2)
{
return strcmp(((peoInfo*)str1)->name, ((peoInfo*)str2)->name);
}
void cmp_age(const void* str1, void* str2)
{
return ((peoInfo*)str1)->age - ((peoInfo*)str2)->age;
}
//排序函数
void ContactSort(Contact* ps)
{
assert(ps);
if (ps->size == 0)
{
printf("联系人为空,无法排序!!!\n");
return;
}
qsort(ps->data, ps->size, sizeof(peoInfo), cmp_name);//快速排序(name)
printf("排序成功!!!\n");
//qsort(ps, ps->size, sizeof(peoInfo), cmp_age);//快速排序(age)
//………………
}
效果展示:
8.展开联系人列表
逻辑解释:
展示所有联系人的信息,按照名字、性别、年龄、电话和地址的顺序打印。
//展示函数
void ContactShow(Contact* ps)
{
assert(ps);
printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
for (int i = 0; i < ps->size; i++)
{
printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
ps->data[i].name,
ps->data[i].gender,
ps->data[i].age,
ps->data[i].tel,
ps->data[i].addr
);
}
}
9.销毁联系人
逻辑解释:
销毁功能释放动态数组的内存,并将通讯录重置为空。
void ContactDestory(Contact* ps)
{
if (ps->data)
{
free(ps->data);
}
ps->data = NULL;
ps->capacity = ps->size = 0;
}
总结(代码展示)
Contact.h
#pragma once
# include<stdio.h>
# include<assert.h>
# include<stdlib.h>
# include<string.h>
#define NAME_MAX 10
#define GENDER_MAX 8
#define TEL_MAX 20
#define ADDR_MAX 20//宏定义利于区分和修改
struct personInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
};//定义联系人类型,和 int,char等类型类似
typedef struct personInfo peoInfo;//简化类型
struct Contact
{
peoInfo* data;
int capacity;
int size;
};//与顺序表类似,但储存数据类型不同(一个int,一个peoInfo)
typedef struct Contact Contact;
enum OPPTION
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
SHOW
};//枚举类型使代码可读性提高
//初始化
void ContactInit(Contact* ps);
//添加
void ContactAdd(Contact* ps);
//删除
void ContactDel(Contact* ps);
//修改
void ContactSearch(Contact* ps);
//查找
void ContactSearch(Contact* ps);
//排序
void ContactSort(Contact* ps);
//展示
void ContactShow(Contact* ps);
//销毁
void ContactDestory(Contact* ps);
Contact.c
#include"Contact.h"
//初始化函数
void ContactInit(Contact* ps)
{
assert(ps);
ps-> data = NULL;
ps->capacity = ps->size = 0;
}
//空间检查函数
void CheckCapacity(Contact*ps)
{
assert(ps);
if (ps->capacity ==ps->size)
{
int newcapacity = 0;
newcapacity = ps->capacity == 0 ? 8 : 2 * ps->capacity;//三目操作符
peoInfo* str = (peoInfo*)malloc(sizeof(peoInfo) * newcapacity);
if (str == NULL)
{
perror("malloc fail !!!");
exit(1);
}
ps->data = str;
ps->capacity = newcapacity;//模式化处理
}
}
//寻找函数
int ContactFind(Contact* ps, char name[])
{
for (int i = 0; i < ps->size; i++)
{
if (strcmp(ps->data[i].name,name)==0)//字符串只能strcmp函数比较
{
return i;
}
}
return -1;
}
//排序
void cmp_name(const void* str1,const void* str2)
{
return strcmp(((peoInfo*)str1)->name, ((peoInfo*)str2)->name);
}
void cmp_age(const void* str1, void* str2)
{
return ((peoInfo*)str1)->age - ((peoInfo*)str2)->age;
}
//添加函数
void ContactAdd(Contact* ps)
{
assert(ps);
CheckCapacity(ps);
printf("输入名字:\n");
scanf("%s", ps->data[ps->size].name);
printf("输入性别:\n");
scanf("%s", ps->data[ps->size].gender);
printf("输入年龄:\n");
scanf("%d", &ps->data[ps->size].age);
printf("输入电话号码:\n");
scanf("%s", ps->data[ps->size].tel);
printf("输入地址:\n");
scanf("%s", ps->data[ps->size].addr);
ps->size++;
}
//展示函数
void ContactShow(Contact* ps)
{
assert(ps);
printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
for (int i = 0; i < ps->size; i++)
{
printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
ps->data[i].name,
ps->data[i].gender,
ps->data[i].age,
ps->data[i].tel,
ps->data[i].addr
);
}
}
//删除函数
void ContactDel(Contact* ps)
{
if (ps->size == 0)
{
printf("联系人为空,无法删除!!!\n");
return;
}
printf("请输入删除人员名字:\n");//使用名字查找
char name[NAME_MAX];
scanf("%s", name);
int pos = ContactFind(ps,name);
if (pos == -1)
{
printf("删除的人不存在!!!\n");
}
else
{
for (int i = pos; i < ps ->size-1; i++)
{
ps->data[i] = ps->data[i + 1];
}
ps->size--;
printf("删除成功!!!\n");
}
}
//查找函数
void ContactSearch(Contact* ps)
{
if (ps->size == 0)
{
printf("联系人为空,无法查找!!!\n");
return;
}
printf("请输入要查找的名字:\n");
char name[NAME_MAX];
scanf("%s", name);
int pos = ContactFind(ps, name);
if (pos == -1)
{
printf("没有该联系人!!!\n");
}
else
{
printf("%-6s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
printf("%-6s\t%-4s\t%-5d\t%-12s\t%-30s\n",
ps->data[pos].name,
ps->data[pos].gender,
ps->data[pos].age,
ps->data[pos].tel,
ps->data[pos].addr
);
}
}
//修改函数
void ContactModify(Contact* ps)
{
if (ps->size == 0)
{
printf("联系人为空,无法修改!!!\n");
return;
}
printf("请输入要修改的名字:\n");
char name[NAME_MAX];
scanf("%s", name);
int pos = ContactFind(ps, name);
if (pos == -1)
{
printf("没有该联系人\n");
return;
}
else
{
printf("开始修改…………\n");
printf("请输入名字:\n");
scanf("%s", ps->data[pos].name);
printf("请输入年龄:\n");
scanf("%d", &ps->data[pos].age);
printf("请输入性别:\n");
scanf("%s", ps->data[pos].gender);
printf("请输入电话:\n");
scanf("%s", ps->data[pos].tel);
printf("请输入地址:\n");
scanf("%s", ps->data[pos].addr);
printf("成功输入联系人!!!\n");
}
}
//排序函数
void ContactSort(Contact* ps)
{
assert(ps);
if (ps->size == 0)
{
printf("联系人为空,无法排序!!!\n");
return;
}
qsort(ps->data, ps->size, sizeof(peoInfo), cmp_name);//快速排序(name)
printf("排序成功!!!\n");
//qsort(ps, ps->size, sizeof(peoInfo), cmp_age);//快速排序(age)
//………………
}
//销毁
void ContactDestory(Contact* ps)
{
if (ps->data)
{
free(ps->data);
}
ps->data = NULL;
ps->capacity = ps->size = 0;
}
test.c
# include"Contact.h"
void menu()
{
printf("**************************\n");
printf("******1.ADD 2.DEL******\n");
printf("******3.SEARCH 4.MODIFY***\n");
printf("******6.SORT 6.SHOW*****\n");
printf("**********0.EXIT**********\n");
printf("**************************\n");
}
int main()
{
int input = 0;
Contact plist;
ContactInit(&plist);
do
{
menu();
printf("输入你的选择:\n");
scanf("%d", &input);
switch(input)
{
case ADD:
ContactAdd(&plist);
break;
case DEL:
ContactDel(&plist);
break;
case SEARCH:
ContactSearch(&plist);
break;
case MODIFY:
ContactModify(&plist);
break;
case SORT:
ContactSort(&plist);
break;
case SHOW:
ContactShow(&plist);
break;
case EXIT:
printf("退出程序……\n");
ContactDestory(&plist);
break;
default :
printf("输入错误,重新输入!!!\n");
break;
}
} while (input);
}
通讯录的实现基于顺序表的原理,通过动态数组存储联系人信息,并提供了添加、删除、查找、修改、排序和展示等功能。这些功能的实现依赖于动态内存管理和字符串操作等基础技术。
后记
经过艰苦卓绝的战斗,通讯录残血了,小Y扔出了精灵球,(精灵球摇了几下–叮的一声),小Y成功捕获了通讯录!!!