大家先赞后看,养成好习惯
你们的点赞和关注还有收藏就是我的动力!!!
目录
前言
一、通讯录文件的创建和联系人结构体定义
1.1 文件创建
1.2 联系人结构体定义
二、通讯录的功能实现
2.1通讯录初始化
2.2通讯录销毁
2.3添加联系人
2.4删除联系人
2.5查找联系人(包含显现联系人)
2.6修改通讯录
2.7展示通讯录
2.8菜单的创建 (与扫雷、猜数字相似)
三、使用通讯录储存联系人
四、结合文件操作来储存信息
五、代码展示
5.1通讯录头文件
5.2通讯录源文件
总结
前言
“通讯录”是基于顺序表的基础上实现的项目,要熟悉顺序表才比较容易看懂和完成通讯录项目。在这个博客里面不会来介绍之前的东西,之前没看懂的可以到这【数据结构之“顺序表”】-CSDN博客
一、通讯录文件的创建和联系人结构体定义
1.1 文件创建
加上之前顺序表的两个文件一共是五个文件。
test.c是实现联系人储存的文件,contact.c是通讯录的源文件,contact.h是通讯录的头文件,seqlist.c和seqlist.h是之前的顺序表的源文件和头文件。(源文件是功能实现的代码,头文件是用来包含一些头文件和定义一些东西)
1.2 联系人结构体定义
我们这里的联系人信息包含:姓名、性别、年龄 、电话、地址
typedef struct PersonInfo//通讯录
{
char name[Max_name];//姓名
char gender[Max_gender];//性别
int age;//年龄
char tel[Max_tel];//电话
char addr[Max_addr];//地址
}PeoInfo;//命名为PeoInfo
二、通讯录的功能实现
2.1通讯录初始化
我们就调用一下顺序表的初始化就可以了,因为在顺序表的arr中存放每一个结构体(也就是联系人的信息)就是PersonInfo。
//通讯录初始化
void contactInit(contact * con)
{
//这里的con就是sl也就是一个结构体指针初始化为NULL
//我们直接调用顺序表的初始化
SLInit(con);//初始化
}
2.2通讯录销毁
销毁也同初始化,直接调用顺序表的销毁。
//通讯录销毁
void contactDestroy(contact* con)
{
SLDestroy(con);//销毁
}
2.3添加联系人
也就是给结构体里面的人赋初值,然后调用一下顺序表的插入函数(头插、尾插都行)。
//添加通讯录联系人
void contactAdd(contact* con)
{
PeoInfo info;//同SL sl;定义一个结构体,方便使用
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);
SLPushFront(con,info);//头插联系人
printf("添加联系人成功!\n");
}
2.4删除联系人
删除联系人有很多方法,可以通过姓名、性别、年龄 、电话、地址 五种方法随便选择一种。
我这里演示的是通过姓名来删除联系人,剩下的几种大家可以自行尝试!!。
想法我们要遍历每一个结构体里面的info.name然后判断与要被删除的联系人姓名,然后返回下标进行了(顺序表本质就是一个数组,可以通过下标来找到),调用查找联系人返回下标函数,我们比较的是字符使用要用strcmp函数,然后调用一下顺序表指定位置的删除就可以了。
//查找联系人,并返回下标
int contactFindName(contact* con,char name[Max_name])
{
//还可以通过其他来返回下标,地址,电话都行,要看传来的参数是什么。
for (int i = 0;i < con->size;i++)
{
if (0 == strcmp(con->arr[i].name, name))//strcmp字符串比较函数
{
//找到了
return i;
}
}
//没找到
return -1;
}
//删除联系人
void contactDel(contact* con)
{
//删除前要检查删除的数据是否存在
//就要先查找数据
char name[Max_name];
printf("请输入你要删除的联系人姓名:\n");
scanf("%s", name);
int pos = contactFindName(con, name);
if (pos < 0)
{
printf("删除的联系人不存在!\n");
return;
}
SLErase(con,pos);//pos是删除元素的下标
printf("删除成功!\n");
}
2.5查找联系人(包含显现联系人)
查找联系人和删除联系人很像,只比删除联系人少了删除数据。
//查找通讯录联系人
void contactFind(contact* con)
{
char name[Max_name];
printf("请输入查找的联系人姓名:\n");
scanf("%s", name);
int pos = contactFindName(con, name);
if (pos < 0)
{
printf("查找的联系人不存在,查找失败!\n");
return;
}
printf("查找成功\n");
printf("姓名 性别 年龄 电话 地址\n");
printf("%-5s %2s %3d %5s %5s\n", con->arr[pos].name,
con->arr[pos].gender,
con->arr[pos].age,
con->arr[pos].tel,
con->arr[pos].addr);
}
2.6修改通讯录
本质上和删除差不多,还是通过返回下标来重新修改联系人
//修改通讯录联系人
void contactModify(contact* con)
{
char name[Max_name];
printf("请输入要修改的联系人名字:\n");
scanf("%s", name);
int pos = contactFindName(con,name);
if (pos < 0)
{
printf("修改的联系人不存在,修改失败!\n");
return;
}
PeoInfo info;
printf("请输入修改后联系人姓名:\n");
scanf("%s", con->arr[pos].name);
printf("请输入修改后联系人性别:\n");
scanf("%s", con->arr[pos].gender);
printf("请输入修改后联系人年龄:\n");
scanf("%d", &con->arr[pos].age);
printf("请输入修改后联系人电话:\n");
scanf("%s", con->arr[pos].tel);
printf("请输入修改后联系人地址:\n");
scanf("%s", con->arr[pos].addr);
printf("修改成功!\n");
}
2.7展示通讯录
通过循环来打印联系人信息,这时就要用到顺序表里面的有效个数(size)来作为循环的判断条件。
//展示通讯录联系人
void contactShow(contact* con)
{
for (int i = 0;i < con->size;i++)//呈现所有的信息
{
printf("姓名 性别 年龄 电话 地址\n");
printf("%-5s %2s %3d %5s %5s\n", con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].addr);
}
printf("呈现完毕!\n");
}
2.8菜单的创建 (与扫雷、猜数字相似)
void menu()//菜单 目录
{
printf("***********通讯录**********\n");
printf("**1.添加用户***2.删除用户**\n");
printf("**3.查找用户***4.修改用户**\n");
printf("**5.显示用户***0.退出程序**\n");
}
三、使用通讯录储存联系人
#define _CRT_SECURE_NO_WARNINGS
//用来测试代码
#include"Seqlist.h"
int main()
{
contact con;
contactInit(&con);//初始化
int input = -1;
do
{
menu();
printf("请你选择操作:\n");
scanf("%d", &input);
switch (input)
{
case 1:
contactAdd(&con);
break;
case 2:
contactDel(&con);
break;
case 3:
contactFind(&con);
break;
case 4:
contactModify(&con);
break;
case 5:
contactShow(&con);
break;
default:
printf("输入操作错误,重新输入!\n");
break;//default 后面break 可写可不写
}
}
while (input);//input 等价于 input!=0
contactDestroy(&con);//销毁
return 0;
}
这是主函数(切忌俩个头文件互相包含)
我来演示一下
联系人 姓名:恐龙、性别:男、年龄:18、电话:666666、地址:侏罗纪公园。
拼音不好见谅!!!!
四、结合文件操作来储存信息
这里就不细讲了文件操作,可以看之前的喉咙疼的恐龙又来给大家介绍”芝士了“ 那就是文件操作-CSDN博客
//读取数据到contact.txt文件中
void contactLoad(contact* con)
{
FILE* pf = fopen("contact.txt","rb");//二进制读
if (pf = NULL)
{
perror("fopen error:");
return;
}
PeoInfo info;
while (fread(&info, sizeof(info), 1, pf))
{
SLPushFront(con, info);
}
fclose(pf);//关闭
pf = NULL;//防止出现空指针
printf("历史数据读取成功!\n");
}
//写数据到contact.txt文件中
void contactSave(contact* con)
{
FILE* pf = fopen("contact.txt","wb");
if (pf == NULL)
{
perror("fopen error!");
return;
}
for (int sz = 0;sz < con->size;sz++)
{
fwrite(con->arr+sz, sizeof(PeoInfo), 1, pf);//con->arr[sz]不行,这里要地址,&con->arr[sz].
}
fclose(pf);//关闭
pf = NULL;//防止出现空指针
printf("通讯录数据保存成功!\n");
}
五、代码展示
5.1通讯录头文件
contact.h
#pragma once
#define Max_name 20
#define Max_gender 10
#define Max_tel 15
#define Max_addr 20
typedef struct Seqlist contact;//前置声明,因为不可以相互包含头文件,会报错。
//总结通讯录项目的原理:基于顺序表,在顺序表的数组中存放每一个结构体(也就是联系人的信息)
typedef struct PersonInfo//通讯录
{
char name[Max_name];//姓名
char gender[Max_gender];//性别
int age;//年龄
char tel[Max_tel];//电话
char addr[Max_addr];//地址
}PeoInfo;
//通讯录初始化
void contactInit(contact* con);
//通讯录的销毁
void contactDestroy(contact* con);
//添加通讯录联系人
void contactAdd(contact* con);
//删除通讯录联系人
void contactDel(contact* con);
//查找通讯录联系人
void contactFind(contact* con);
//修改通讯录联系人
void contactModify(contact* con);
//展示通讯录联系人
void contactShow(contact* con);
5.2通讯录源文件
contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
#include"Seqlist.h"
//读取数据到contact.txt文件中
void contactLoad(contact* con)
{
FILE* pf = fopen("contact.txt","rb");//二进制读
if (pf = NULL)
{
perror("fopen error:");
return;
}
PeoInfo info;
while (fread(&info, sizeof(info), 1, pf))
{
SLPushFront(con, info);
}
fclose(pf);//关闭
pf = NULL;//防止出现空指针
printf("历史数据读取成功!\n");
}
//写数据到contact.txt文件中
void contactSave(contact* con)
{
FILE* pf = fopen("contact.txt","wb");
if (pf == NULL)
{
perror("fopen error!");
return;
}
for (int sz = 0;sz < con->size;sz++)
{
fwrite(con->arr+sz, sizeof(PeoInfo), 1, pf);//con->arr[sz]不行,这里要地址,&con->arr[sz].
}
fclose(pf);//关闭
pf = NULL;//防止出现空指针
printf("通讯录数据保存成功!\n");
}
//通讯录初始化
void contactInit(contact * con)
{
//这里的con就是sl也就是一个结构体指针初始化为NULL
//我们直接调用顺序表的初始化
SLInit(con);//初始化
}
//通讯录销毁
void contactDestroy(contact* con)
{
SLDestroy(con);//销毁
}
//添加通讯录联系人
void contactAdd(contact* con)
{
PeoInfo info;//同SL sl;定义一个结构体,方便使用
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);
SLPushFront(con,info);//头插联系人
printf("添加联系人成功!\n");
}
//查找联系人,并返回下标
int contactFindName(contact* con,char name[Max_name])
{
//还可以通过其他来返回下标,地址,电话都行,要看传来的参数是什么。
for (int i = 0;i < con->size;i++)
{
if (0 == strcmp(con->arr[i].name, name))//strcmp字符串比较函数
{
//找到了
return i;
}
}
//没找到
return -1;
}
//删除联系人
void contactDel(contact* con)
{
//删除前要检查删除的数据是否存在
//就要先查找数据
char name[Max_name];
printf("请输入你要删除的联系人姓名:\n");
scanf("%s", name);
int pos = contactFindName(con, name);
if (pos < 0)
{
printf("删除的联系人不存在!\n");
return;
}
SLErase(con,pos);//pos是删除元素的下标
printf("删除成功!\n");
}
//查找通讯录联系人
void contactFind(contact* con)//err
{
char name[Max_name];
printf("请输入查找的联系人姓名:\n");
scanf("%s", name);
int pos = contactFindName(con, name);
if (pos < 0)
{
printf("查找的联系人不存在,查找失败!\n");
return;
}
printf("查找成功\n");
printf("姓名 性别 年龄 电话 地址\n");
printf("%-5s %2s %3d %5s %5s\n", con->arr[pos].name,
con->arr[pos].gender,
con->arr[pos].age,
con->arr[pos].tel,
con->arr[pos].addr);
}
//修改通讯录联系人
void contactModify(contact* con)
{
char name[Max_name];
printf("请输入要修改的联系人名字:\n");
scanf("%s", name);
int pos = contactFindName(con,name);
if (pos < 0)
{
printf("修改的联系人不存在,修改失败!\n");
return;
}
PeoInfo info;
printf("请输入修改后联系人姓名:\n");
scanf("%s", con->arr[pos].name);
printf("请输入修改后联系人性别:\n");
scanf("%s", con->arr[pos].gender);
printf("请输入修改后联系人年龄:\n");
scanf("%d", &con->arr[pos].age);
printf("请输入修改后联系人电话:\n");
scanf("%s", con->arr[pos].tel);
printf("请输入修改后联系人地址:\n");
scanf("%s", con->arr[pos].addr);
printf("修改成功!\n");
}
//展示通讯录联系人
void contactShow(contact* con)
{
for (int i = 0;i < con->size;i++)//呈现所有的信息
{
printf("姓名 性别 年龄 电话 地址\n");
printf("%-5s %2s %3d %5s %5s\n", con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].addr);
}
printf("呈现完毕!\n");
}
总结
通讯录这个项目你只要完全了解了顺序表解决不困难,要理解通讯录结构体每一个联系人就是顺序表中的arr动态数组里面的一个成员。我们还可以把这些联系人的信息以文件的形式储存起来,这就要运用到我们之前学习过的文件操作。本人感觉顺序表和通讯录会比链表复杂,后面还会为大家介绍单链表和双链表,大家敬请期待吧!!