1.通讯录的实现逻辑
对于通讯录,我们做的无非就是初始化,销毁。添加联系人数据,修改联系人数据,删除联系人数据,查找联系人数据,展示联系人数据;
这个不就和我们的顺序表的逻辑如出一辙吗,顺序表实现的功能不就是数据的初始化,修改,删除(头删和尾删),添加(头插和尾插),顺序表的打印,这些我们是可以直接进行使用的;
我们的顺序表是整形的数据的删除,插入等等,那么我们的通讯录不是对整形数据进行相关的操作了,而是对联系人的信息进行相应的操作,我们把联系人及其相关的信息放到一个结构体里面,我们联系人的信息包括姓名性别年龄,电话以及地址这5项信息;
2.通讯录实现
(1)一些前期的准备
我们要在顺序表的基础上进行相应的操作,所以我们的解决方案在原来的seqlist.c---seqlist.h----test.c这三个基础上加上contact.c---contact.h这两个表示的是通讯录的源文件和头文件;
我们在通讯录的同文件里面定义结构体以及相关的函数的声明:
这里我们使用宏定义结构体里面数组(名字性别电话),方便我们对数组的大小进行相应的修改;
我们同时要把顺序表的头文件里面的int修改为我们联系人对应的结构体类型的数据,这个时候要包含通讯录对应的头文件;
通讯录的头文件要使用应该是对于顺序表进行初始化(实际上是对通讯录进行初始化),我们对顺序表进行初始化contactinit(sl* sl1),这个里面的sl就是我们的顺序表重定义之后的名字,sl1是形参,但是我们明明是要对通讯录进行初始化,参数确是顺序表这让人很难理解,我们于是写作contactinit(contact* con)这样就会很直观,但是两个头文件之间不能重复的包含,我们进行前置声明重定义:
因为我们的顺序表头文件里面的数据类型不是int ,我们的测试文件插入数据应该注释掉;顺序表的源文件里面打印整形数据,查找整形数据应该也注释掉,否则会报错
(2)通讯录的初始化和销毁
(3)添加联系人数据
我们定义一个结构体类型的变量:info把添加的信息写入到对应的成员里面去;
最后我们调用尾插函数插入到通讯录里面(也可以是头插函数);
(4)删除联系人数据
我们首先要判断删除的联系人是否存在,存在才能删除,不存在无法进行相应的操作;
我们后续进修改联系人数据的时候,也要进行判断我们想要修改的联系人是否存在,我们可以根据姓名进行判断是否存在,这个时候我们行定义一个函数fingbyname,因为是输入的联系人姓名和我们的通讯录里面的联系人姓名这两个字符串进行比较看是否相同,我们需要遍历整个通讯录,使用strcmp函数将我们输入的姓名和通讯录里面的姓名,进行比较,存在就返回0,不存在函数就返回-1;
我们最后是调用顺序表里面的slerase函数实现在指定的位置进行删除的操作,我们要传入通讯录和指定位置的下标;
(5)修改联系人数据
和删除的逻辑一样,先进行判断修改的联系人是否存在,调用findbyname函数根据返回值进行判断,最后输入新的联系人的相关的信息;
(6)查找联系人数据
和删除的逻辑一样,先进行判断查找的联系人是否存在,调用findbyname函数根据返回值进行判断,最后输出新的联系人的相关的信息;我们不使用展示是因为展示的是全部的,查找的时候只会展示我们想要查找的联系人的相关的信息,这个和展示的代码基本相同,只需要把数组对应的下标修改为我们的findbyname函数的返回值了;
(7)展示联系人数据
先打印表头栏目,在把我们的联系人的信息对应表头打印出来;
(8)项目的完善
作为一个项目,我们不能停留在测试功能上面,我们打印菜单栏,让用户可以自己选择相应的的功能进行实现,我们把所有的可以实现的功能放在菜单栏里面供用户进行选择:
我们的函数都已经实现了,所以设置switch循环的时候,直接调用就可以了;
3.完整代码
(1)seqlist.h
#pragma once
#include"contact.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef perinfo sldatatype;
typedef struct seqlist
{
sldatatype* arr;
int size;
int capacity;
}sl;
//顺序表的初始化
void slinit(sl* ps);
//顺序表的销毁
void sldestory(sl* ps);
//顺序表的尾部插入数据
void slpushback(sl* ps, sldatatype x);
//顺序表的数组元素的打印
void slprint(sl s);
//顺序表的头部插入数据
void slpushfront(sl* ps, sldatatype x);
//顺序表的尾删
void slpopback(sl* ps);
//顺序表的头删
void slpopfront(sl* ps);
//顺序表的打印
void slprint(sl s);
//顺序表的指定插入
void slinsert(sl* ps, int pos, sldatatype x);
//顺序表的指定删除
void slerase(sl* ps, int pos);
//顺序表的数据的查找
int slfind(sl* ps, sldatatype x);
(2)seqlist.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"seqlist.h"
void check(sl* ps)
{
if (ps->size == ps->capacity)
{
//我们插入数据,需要增大空间,动态内存开辟空间
int newcapacity = ps->arr == 0 ? 4 : 2 * ps->capacity;
sldatatype* temp = realloc(ps->arr, newcapacity * 2 * sizeof(sldatatype));
if (temp == NULL)
{
perror("realloc");
exit(1);//直接退出,不再继续执行
}
ps->arr = temp;
ps->capacity = newcapacity;
}
}
//顺序表的初始化
void slinit(sl* ps)
{
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
//顺序表的销毁
void sldestory(sl* ps)
{
if (ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//顺序表的尾部插入数据
void slpushback(sl* ps, sldatatype x)
{
//对传进来的指针进行断言
assert(ps);
//判断数组大小和空间的容量是否相同
check(ps);
ps->arr[ps->size] = x;
ps->size++;
}
//顺序表的头部插入数据
void slpushfront(sl* ps, sldatatype x)
{
assert(ps);
check(ps);
for (int i = ps->size; i > 0; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
ps->size++;
}
//顺序表的打印
//void slprint(sl s)
//{
// for (int i = 0; i < s.size; i++)
// {
// printf("%d ", s.arr[i]);
// }
// printf("\n");
//}
//顺序表的尾删
void slpopback(sl* ps)
{
assert(ps);
assert(ps->size);//如果我们顺序表本来就没有数据,我们进行减减就会变为-1了,显然不对,进行断言
ps->size--;//渐渐就减少了范围,直接把最后的元素删除,就相当于最后一个元素不属于顺序表了
}
//顺序表的头删
void slpopfront(sl* ps)
{
assert(ps);
assert(ps->size);
for (int i = 0; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];//最后是arr[size-2]=arr[size-1];
}
ps->size--;
}
//顺序表的指定位置之前插入
void slinsert(sl* ps, int pos, sldatatype x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
check(ps);
for (int i = ps->size; i > pos; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
//顺序表的指定删除
void slerase(sl* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size-1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//顺序表的数据的查找
//int slfind(sl* ps, sldatatype x)
//{
// assert(ps);
// for (int i = 0; i < ps->size; i++)
// {
// //找到了
// if (ps->arr[i] == x)
// {
// return i;
// }
// }
// //没有找到
// return -1;//无效的下标
//}
(3)contact.h
#pragma once
#define name_max 20
#define gender_max 10
#define tel_max 20
#define addr_max 20
typedef struct personinfo
{
char name[name_max];
char gender[gender_max];
int age;
char tel[tel_max];
char addr[addr_max];
}perinfo;
typedef struct seqlist contact;
//通讯录初始化
void contactinit(contact* con);
//通讯录销毁
void contactdestory(contact* con);
//通讯录添加联系人数据
void contactadd(contact* con);
//通讯录删除联系人数据
void contactdel(contact* con);
//通讯录修改联系人数据
void contactmodify(contact* con);
//通讯录查找联系人数据
void contactfind(contact* con);
//通讯录展示联系人数据
void contactshow(contact* con);
(4)contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
#include"seqlist.h"
void contactinit(contact* con)
{
slinit(con);
}
void contactdestory(contact* con)
{
sldestory(con);
}
void contactadd(contact* con)
{
perinfo info;
printf("请输入联系人的姓名:\n");
scanf("%s", info.name);
printf("请输入联系人的性别:\n");
scanf("%s", info.gender);
printf("请输入联系人的年龄:\n");
scanf("%d", &info.age);
printf("请输入联系人的电话:\n");
scanf("%s", info.tel);
printf("请输入联系人的地址:\n");
scanf("%s", info.addr);
slpushback(con, info);
}
int findbyname(contact* con, char name[])
{
for (int i = 0; i < con->size; i++)
{
if (0 == strcmp(con->arr[i].name, name))
{
//说明找到了
return i;
}
}
return -1;
}
void contactdel(contact* con)
{
char name[name_max];
printf("请输入要删除的联系人的姓名:\n");
scanf("%s", name);
int find = findbyname(con, name);
if (find < 0)
{
printf("要删除的联系人的数据不存在\n");
return;
}
//删除的联系人的数据存在
slerase(con, find);
printf("删除成功 !\n");
}
void contactmodify(contact* con)
{
char name[name_max];
printf("请输入要修改的联系人的姓名:\n");
scanf("%s", name);
int find = findbyname(con, name);
if (find < 0)
{
printf("要修改的联系人的数据不存在\n");
return;
}
printf("请输入新的联系人的姓名:\n");
scanf("%s", con->arr[find].name);
printf("请输入新的联系人的性别:\n");
scanf("%s", con->arr[find].gender);
printf("请输入新的联系人的年龄:\n");
scanf("%d", &con->arr[find].age);
printf("请输入新的联系人的电话:\n");
scanf("%s", con->arr[find].tel);
printf("请输入新的联系人的地址:\n");
scanf("%s", con->arr[find].addr);
printf("修改成功\n");
}
void contactfind(contact* con)
{
char name[name_max];
printf("请输入要查找的联系人的姓名:\n");
scanf("%s", name);
int find = findbyname(con, name);
if (find < 0)
{
printf("要查找的联系人的数据不存在\n");
return;
}
printf("查找成功\n");
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%s %s %d %s %s\n",
con->arr[find].name,
con->arr[find].gender,
con->arr[find].age,
con->arr[find].tel,
con->arr[find].addr);
}
}
void contactshow(contact* con)
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%s %s %d %s %s\n",
con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].addr);
}
}
(5)test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"seqlist.h"
//void sltest01()
//{
// sl sl1;
//
// //顺序表的初始化
// slinit(&sl1);
//
// //顺序表的尾部插入数据
// slpushback(&sl1, 8);
// slpushback(&sl1, 9);
// slpushback(&sl1, 10);
// slpushback(&sl1, 11);
//
// //尾部插入之后打印
// slprint(sl1);
//
// //顺序表的头部插入数据
// slpushfront(&sl1, 5);
// slpushfront(&sl1, 6);
//
// //头部插入之后打印
// slprint(sl1);
//
// //顺序表的尾删
// slpopback(&sl1);
// slprint(sl1);
//
// //顺序表的头删
// slpopfront(&sl1);
// slprint(sl1);
//
// //顺序表的指定位置之前插入
// slinsert(&sl1, 1, 0);
// slprint(sl1);
//
// //顺序表的指定删除
// slerase(&sl1, 1);
// slprint(sl1);
//
// //顺序表的数据的查找
// int ret = slfind(&sl1, 100);
// if (ret < 0)
// {
// printf("没有找到\n");
// }
// else
// {
// printf("找到了,下标是%d\n", ret);
// }
// //顺序表的销毁
// sldestory(&sl1);
//}
//void contacttest01()
//{
// contact con;
// contactinit(&con);
//
// contactadd(&con);
// contactadd(&con);
// contactshow(&con);
//
// contactdel(&con);
// contactshow(&con);
//
// contactmodify(&con);
// contactshow(&con);
//
// contactfind(&con);
//
//
// contactdestory(&con);
//}
void menu()
{
printf("*************通讯录*************\n");
printf("*****1、添加用户 2、删除用户****\n");
printf("*****3、修改用户 4、查找用户****\n");
printf("*****5. 展示用户 0.退出通讯录***\n");
printf("********************************\n");
}
int main()
{
//顺序表的功能测试函数
//sltest01();
/*contacttest01();*/
int input = -1;
contact con;
contactinit(&con);
do
{
menu();
printf("请选择");
scanf("%d", &input);
switch (input)
{
case 1:
contactadd(&con);
break;
case 2:
contactdel(&con);
break;
case 3:
contactmodify(&con);
break;
case 4:
contactfind(&con);
break;
case 5:
contactshow(&con);
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
contactdestory(&con);
return 0;
}