目录
前言
前面我们介绍了如何用C语言实现动态顺序表,现在,我们基于之前写好的代码,编写一个通讯录项目。
目标
1.实现通讯录的增删查改
2.读取和保存通讯录的数据
注意:本篇基于上一篇用C语言实现顺序表,如果对顺序表不了解,请一定要阅读上一篇文章,否则本篇的理解可能会相对吃力。
一. 准备工作
1. 创建必要文件
本次通讯录项目基于上次我们顺序表的实现,所以需要使用到上次我们编写的文件:SeqList.h,SeqList.c,test.c
同时我们还需要创建本次通讯录项目的代码文件:Contact.h,Contact.c
现在,我们手中已经有了五个代码文件,现在我们来整理一下,确定这些代码文件的具体作用:
代码文件 | 作用 |
---|---|
SeqList.h | 顺序表的函数声明 |
SeqList.c | 顺序表的函数实现 |
Contact.h | 通讯录的代码声明 |
Contact.c | 通讯录的函数实现 |
test.c | 主函数和菜单 |
现在,我们明确了各个代码文件的具体作用,这些文件又应该如何包含起来,联系到一起呢?
2. 确定文件包含关系
下面是本次通讯录项目中各个代码文件包含关系图:
为什么这么包含呢?我们下面结合具体代码解释。
3. 设计通讯录结构体
我们将包含联系人信息的结构体命名为PersonInfo,包含了联系人的姓名name,性别gender,年龄age,电话号码tel,地址addr。
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100
//通讯录结构体
typedef struct PersonInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
同样的,为了方便代码书写,我们将结构体进行重命名,同时,为了方便以后我们更改字符串长度,我们使用了#define的方式来确定字符串长度。
注意:由于涉及字符串的处理,需要加上<string.h> 。
既然我们已经确定了联系人信息的结构体,那么我们之前在Seqlist.h中的临时将int类型重命名为SLDataType就不合适了,应该将PersonInfo类型重命名为SLDataType。
//将通讯录结构体类型重命名为SLDataType
typedef PeoInfo SLDataType;
这里就体现出了我们之前编写时对数据类型进行重命名的优势,方便了此处对其进行修改。
4. 重命名顺序表为通讯录
既然我们是一个通讯录项目,那么叫做SeqList也不合适了,我们将其重命名为通讯录Contact
//对结构体SL进行重命名为Contact
//因为没有不会SL的头文件,使用声明+typedef
typedef struct SeqList Contact;
5. 对通讯录结构的理解
通讯录结构体:
数据类型 | 名字 |
---|---|
SLDataType* | arr |
int | size |
int | capacity |
联系人结构体:
数据类型 | 名字/数组名 | 数组长度 |
---|---|---|
char | name | NAME_MAX |
char | gender | GENDER_MAX |
int | age | \ |
char | tel | TEL_MAX |
char | addr | ADDR_MAX |
这里将PersonInfo设置为SLDataType
二. 函数实现
1. 初始化 ContactInit
函数原型式:
void ContactInit(Contact* con);
代码实现:
//通讯录的初始化
void ContactInit(Contact* con)
{
//con就是SL
SLInit(con);
}
由于Contact是由SL重命名而成,所以可以直接调用SL的初始化函数。
2. 销毁 ContactDestroy
函数原型式:
void ContactDestroy(Contact* con);
代码实现:
//通讯录的销毁
void ContactDestroy(Contact* con)
{
//SaveContact(con);//在销毁退出前保存数据
SLDestroy(con);
}
代码解释同上,这里不加赘述。
3. 添加数据 ContactAdd
函数原型式:
void ContactAdd(Contact* con);
代码实现:
//通讯录添加数据
void ContactAdd(Contact* con)
{
//获取用户输入的内容
//姓名+性别+年龄+电话+地址
PeoInfo info;
printf("请输入联系人姓名:");
scanf("%s", info.name);
printf("请输入联系人性别:");
scanf("%s", info.gender);
printf("请输入联系人年龄:");
scanf("%d", &info.age);
printf("请输入联系人电话:");
scanf("%s", info.tel);
printf("请输入联系人地址:");
scanf("%s", info.addr);
//往通讯录中添加联系人数据
SLPushBack(con, info);
}
我们先创建一个联系人结构体,然后对其输入数据,最后将其尾插到数组的结尾。
4. 按姓名查找 FindByName
函数原型式:
int FindByName(Contact* con, char name[]);
代码实现
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;
}
这里实现一个按照姓名查找数据,由于我们的顺序表的数据存储是数组结构,就相当于一个在数组中查找元素,如果找到了,就返回元素下标,如果没找到,就返回EOF(-1)
如果你需要按其它方式查找,也可以写出相应的代码。
5. 删除数据 ContactDel
函数原型式:
void ContactDel(Contact* con);
代码实现:
//通讯录删除数据
void ContactDel(Contact* con)
{
//数据必须先存在,才能删除
//查找
char name[NAME_MAX] = { 0 };
printf("请输入要删除的联系人姓名:");
scanf("%s", name);
int find = FindByName(con, name);
if (find < 0)
{
printf("要删除的联系人不存在!\n");
return;
}
else
{
//找到了该联系人数据,找到了下标 —— 删除指定位置的数据
SLErase(con, find);
printf("删除成功!\n");
}
}
想要删除一个数据,就要先找到这一条数据,找不到,就提示不存在返回,找到了,就调用顺序表的尾删。
6. 修改 ContactModify
函数原型式:
void ContactModify(Contact* con);
代码实现:
//通讯录的修改
void ContactModify(Contact* con)
{
//要修改的联系人数据存在
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人姓名:");
scanf("%s", name);
int find = FindByName(con, name);
if (find < 0)
{
printf("联系人数据不存在!\n");
return;
}
else
{
printf("请输入联系人新的姓名:");
scanf("%s", con->arr[find].name);
printf("请输入联系人新的性别:");
scanf("%s", con->arr[find].gender);
printf("请输入联系人新的年龄:");
scanf("%d", &(con->arr[find].age));
printf("请输入联系人新的电话:");
scanf("%s", con->arr[find].tel);
printf("请输入联系人新的地址:");
scanf("%s", con->arr[find].addr);
printf("修改成功!\n");
}
}
要修改数据同样也需要查找到这一条数据,找不到,就提示不存在返回,找到了,就直接修改数组中对应的数据。
7. 查找 ContactFind
函数原型式:
void ContactFind(Contact* con);
代码实现:
//通讯录的查找
void ContactFind(Contact* con)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找的联系人姓名:");
scanf("%s", name);
int find = FindByName(con, name);
if (find < 0)
{
printf("联系人数据不存在!\n");
return;
}
else
{
//表头: 姓名 性别 年龄 电话 地址
printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%5s %5s %5d %10s %5s\n", \
con->arr[find].name, \
con->arr[find].gender, \
con->arr[find].age, \
con->arr[find].tel, \
con->arr[find].addr);
}
}
要查找数据同样也需要先查找到这一条数据,找不到,就提示不存在返回,找到了,就展示这一条数据。
8. 展示数据ContactShow
函数原型式:
void ContactShow(Contact* con);
代码实现:
//展示通讯录数据
void ContactShow(Contact* con)
{
//表头: 姓名 性别 年龄 电话 地址
printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%5s %5s %5d %10s %5s\n", \
con->arr[i].name, \
con->arr[i].gender, \
con->arr[i].age, \
con->arr[i].tel, \
con->arr[i].addr);
}
}
这里展示数据就是遍历数组中的所有元素,然后将每一条数据打印出来。
9. 保存数据 SaveContact
下面的保存和读取数据涉及文件操作的相关知识。
函数原型式:
void SaveContact(Contact* con);
代码实现:
//保存通讯录数据
void SaveContact(Contact* con)
{
FILE* pf = NULL;
pf = fopen("Contact.dat", "w");
if (pf == NULL)
{
perror("Failed to write to file");
return;
}
//写入数据
fprintf(pf, "%d\n", con->size);//写入有效数据个数
for (int i = 0; i < con->size; i++)//写入通讯录数据
{
fprintf(pf, "%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);
}
printf("数据保存成功!\n");
fclose(pf);
pf = NULL;
}
这里先写入有效的元素个数,在一行一行地写入具体的联系人数据。
为什么要写入有效元素个数呢,直接写入数据不就可以了吗?
也可以,但如果程序退出,再次进入时会初始化通讯录,那么有效元素个数将为0,如果不写入有效元素个数,就需要在读取时计数,判断读取了多少条数据,并相应的进行扩容等操作。
10. 读取数据 ReadContact
函数原型式:
void ReadContact(Contact* con);
代码实现:
//读取通讯录数据
void ReadContact(Contact* con)
{
FILE* pf = NULL;
pf = fopen("Contact.dat", "r");
if (pf == NULL)
{
perror("Failed to read to file");
return;
}
fscanf(pf, "%d", &(con->size));//读取有效数据个数
for (int i = 0; i < con->size; i++)
{
PeoInfo info = { 0 };
fscanf(pf, "\n%s %s %d %s %s", \
info.name, \
info.gender, \
& (info.age), \
info.tel, \
info.addr);
//SLPushBack(con, info);//不能使用尾插
SLCheckCapacity(con);//容量判断
con->arr[i] = info;
}
printf("数据读取成功!\n");
fclose(pf);
pf = NULL;
}
上面我们写入了有效元素个数,我们在下面就只需要读取,然后判断是否需要扩容,最后插入数据。
注意:由于我们先读取有效个数,可能会导致刚读取时有效数据个数大于元素个数的情况,因此需要对SeqList.c中的SLCheckCapacity函数进行修改,否则无法正常扩容。
if (ps->size >= ps->capacity)//为通讯录读取增容创造条件
如果需要在已有的数据后面添加从文件中读取的数据,只需要从有效元素个数后面开始尾插即可。
11. 增容 SLCheckCapacity
此处放置增容函数的声明仅仅是因为之前的函数声明为SL,而现在我们已经重命名为Contact,使用以前的函数声明会报错。
void SLCheckCapacity(Contact* con);
12. 菜单 menu
void menu(void)
{
printf("***************通讯录****************\n");
printf("* *\n");
printf("* 1.增加联系人 *\n");
printf("* 2.删除联系人 *\n");
printf("* 3.修改联系人 *\n");
printf("* 4.查找联系人 *\n");
printf("* 5.展示联系人 *\n");
printf("* 6.读取联系人 *\n");
printf("* 7.保存联系人 *\n");
printf("* 0.退出 *\n");
printf("* *\n");
printf("*************************************\n");
}
菜单仅仅需要逐行打印即可。
13. 主函数 main
int main()
{
int input = 0;
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 6:
ReadContact(&con);
break;
case 7:
SaveContact(&con);
break;
case 0:
printf("退出通讯录……\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
ContactDestroy(&con);
return 0;
}
创建一个通讯录结构体并初始化,然后使用do-while循环和switch…case语句选择,然后调用相应的函数,最后销毁,空间释放,函数返回,程序结束。
三. 参考代码
Contact.h
#pragma once
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100
//通讯录结构体
typedef struct PersonInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//对结构体SL进行重命名为Contact
//因为没有包含SL的头文件,使用声明+typedef
typedef struct SeqList Contact;
//struct SeqList;//声明结构体
//typedef SL Contact;//给结构体改名
//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录的查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);
//保存通讯录数据
void SaveContact(Contact* con);
//读取通讯录数据
void ReadContact(Contact* con);
//顺序表的增容
void SLCheckCapacity(Contact* con);
Contact.c
#include "Contact.h"
#include "SeqList.h"
#include <string.h>
//通讯录的初始化
void ContactInit(Contact* con)
{
//con就是SL
SLInit(con);
}
//通讯录的销毁
void ContactDestroy(Contact* con)
{
//SaveContact(con);//在销毁退出前保存数据
SLDestroy(con);
}
//通讯录添加数据
void ContactAdd(Contact* con)
{
//获取用户输入的内容
//姓名+性别+年龄+电话+地址
PeoInfo info;
printf("请输入联系人姓名:");
scanf("%s", info.name);
printf("请输入联系人性别:");
scanf("%s", info.gender);
printf("请输入联系人年龄:");
scanf("%d", &info.age);
printf("请输入联系人电话:");
scanf("%s", info.tel);
printf("请输入联系人地址:");
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] = { 0 };
printf("请输入要删除的联系人姓名:");
scanf("%s", name);
int find = FindByName(con, name);
if (find < 0)
{
printf("要删除的联系人不存在!\n");
return;
}
else
{
//找到了该联系人数据,找到了下标 —— 删除指定位置的数据
SLErase(con, find);
printf("删除成功!\n");
}
}
//通讯录的修改
void ContactModify(Contact* con)
{
//要修改的联系人数据存在
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人姓名:");
scanf("%s", name);
int find = FindByName(con, name);
if (find < 0)
{
printf("联系人数据不存在!\n");
return;
}
else
{
printf("请输入联系人新的姓名:");
scanf("%s", con->arr[find].name);
printf("请输入联系人新的性别:");
scanf("%s", con->arr[find].gender);
printf("请输入联系人新的年龄:");
scanf("%d", &(con->arr[find].age));
printf("请输入联系人新的电话:");
scanf("%s", con->arr[find].tel);
printf("请输入联系人新的地址:");
scanf("%s", con->arr[find].addr);
printf("修改成功!\n");
}
}
//通讯录的查找
void ContactFind(Contact* con)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找的联系人姓名:");
scanf("%s", name);
int find = FindByName(con, name);
if (find < 0)
{
printf("联系人数据不存在!\n");
return;
}
else
{
//表头: 姓名 性别 年龄 电话 地址
printf("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%5s %5s %5d %10s %5s\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("%5s %5s %5s %10s %5s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%5s %5s %5d %10s %5s\n", \
con->arr[i].name, \
con->arr[i].gender, \
con->arr[i].age, \
con->arr[i].tel, \
con->arr[i].addr);
}
}
//保存通讯录数据
void SaveContact(Contact* con)
{
FILE* pf = NULL;
pf = fopen("Contact.dat", "w");
if (pf == NULL)
{
perror("Failed to write to file");
return;
}
//写入数据
fprintf(pf, "%d\n", con->size);//写入有效数据个数
for (int i = 0; i < con->size; i++)//写入通讯录数据
{
fprintf(pf, "%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);
}
printf("数据保存成功!\n");
fclose(pf);
pf = NULL;
}
//读取通讯录数据
void ReadContact(Contact* con)
{
FILE* pf = NULL;
pf = fopen("Contact.dat", "r");
if (pf == NULL)
{
perror("Failed to read to file");
return;
}
fscanf(pf, "%d", &(con->size));//读取有效数据个数
for (int i = 0; i < con->size; i++)
{
PeoInfo info = { 0 };
fscanf(pf, "\n%s %s %d %s %s", \
info.name, \
info.gender, \
& (info.age), \
info.tel, \
info.addr);
//SLPushBack(con, info);//不能使用尾插
SLCheckCapacity(con);//容量判断
con->arr[i] = info;
}
printf("数据读取成功!\n");
fclose(pf);
pf = NULL;
}
SeqList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
//typedef int SLDataType;
//将通讯录结构体类型重命名为SLDataType
typedef PeoInfo SLDataType;
//动态顺序表
//将结构体SeqList重命名为SL
typedef struct SeqList
{
SLDataType* arr;
int size;
int capacity;
}SL;
//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//头部插入数据
void SLPushFront(SL* ps, SLDataType x);
//尾部插入数据
void SLPushBack(SL* ps, SLDataType x);
//打印顺序表
void SLPrint(SL s);
//头部删除数据
void SLPopFront(SL* ps);
//尾部删除数据
void SLPopBack(SL* ps);
//任意位置前插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
//任意位置删除数据
void SLErase(SL* ps, int pos);
//顺序表的查找
//int SLFind(SL* ps, SLDataType x);
SeqList.c
#include "SeqList.h"
void SLInit(SL* ps)
{
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SLDestroy(SL* ps)
{
if (ps->arr)
{
free(ps->arr);
}
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SLCheckCapacity(SL* ps)
{
//在插入数据前先判断空间够不够
if (ps->size >= ps->capacity)//为通讯录读取增容创造条件
{
//申请空间 -- 增容 --> realloc
//增容一般是两倍或者三倍的增加,过大或者过小,频繁的增容,会使程序的运行效率降低
//注意:判断capacity是否为0
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc failed");
exit(1);
}
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
void SLPushBack(SL* ps, SLDataType x)
{
assert(ps);
在插入数据前先判断空间够不够
//if (ps->size == ps->capacity)
//{
// //申请空间 -- 增容 --> realloc
// //增容一般是两倍或者三倍的增加,过大或者过小,频繁的增容,会使程序的运行效率降低
// //注意:判断capacity是否为0
// int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
// SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
// if (tmp == NULL)
// {
// perror("realloc failed");
// exit(1);
// }
// ps->arr = tmp;
// ps->capacity = newcapacity;
//}
SLCheckCapacity(ps);
//尾插
ps->arr[ps->size++] = x;
//ps->arr[ps->size] = x;
//++(ps->size);
}
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(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 > 0);
//ps->arr[ps->size - 1] = -1;
--(ps->size);
}
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size > 0);
for (int i = 0; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
--(ps->size);
}
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(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;
//}
test.c
#include "SeqList.h"
//void SLtest(void)
//{
// SL sl;
// SLInit(&sl);
//
// for (int i = 0; i < 10; i++)
// {
// SLPushBack(&sl, i);
// SLPrint(sl);
// }
//
// for (int i = 0; i < 10; i++)
// {
// SLPushFront(&sl, i);
// SLPrint(sl);
// }
//
// SLPopFront(&sl);
// SLPrint(sl);
//
// SLPopBack(&sl);
// SLPrint(sl);
//
// SLDestroy(&sl);
//}
//void SLtest2()
//{
// SL sl;
// SLInit(&sl);
//
// for (int i = 0; i < 10; i++)
// {
// SLPushBack(&sl, i);
// }
// SLPrint(sl);
//
// SLErase(&sl, 0);
// SLPrint(sl);
//
// SLInsert(&sl, 1, 10);
// SLPrint(sl);
//
// int ret = 0;
// ret = SLFind(&sl, 5);
// printf("ret=%d\n", ret);
//
// ret = SLFind(&sl, 11);
// printf("ret=%d\n", ret);
//
// SLDestroy(&sl);
//}
//void ContactTest01()
//{
// Contact con;//创建的通讯录对象,实际上就是顺序表对象
// ContactInit(&con);//通讯录的初始化
//
// ContactAdd(&con);//添加数据
// ContactAdd(&con);
// ContactShow(&con);
//
// //ContactDel(&con);
// //ContactShow(&con);
//
// //ContactModify(&con);
// //ContactShow(&con);
//
// ContactFind(&con);
//
// ContactDestroy(&con);//通讯录的销毁
//}
//int main()
//{
// //顺序表的测试
// //SLtest();
// //SLtest2();
//
// //通讯录的测试
// ContactTest01();
//
// return 0;
//}
void menu(void)
{
printf("***************通讯录****************\n");
printf("* *\n");
printf("* 1.增加联系人 *\n");
printf("* 2.删除联系人 *\n");
printf("* 3.修改联系人 *\n");
printf("* 4.查找联系人 *\n");
printf("* 5.展示联系人 *\n");
printf("* 6.读取联系人 *\n");
printf("* 7.保存联系人 *\n");
printf("* 0.退出 *\n");
printf("* *\n");
printf("*************************************\n");
}
int main()
{
int input = 0;
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 6:
ReadContact(&con);
break;
case 7:
SaveContact(&con);
break;
case 0:
printf("退出通讯录……\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
ContactDestroy(&con);
return 0;
}
写在最后
本次我们实现了基于动态顺序表的通讯录项目,实现了通讯录的增删查改等操作 ,并添加了相关的文件操作的功能,加深了我们对于顺序表这一数据结构的了解。
本次展示的代码仅仅是对项目相关函数功能的简单实现,不建议大家直接copy,实现的通讯录也绝非完美,你可以对代码进行增添、修改等操作使其变得更完美,比如在初始化后直接从文件中读取数据,在程序退出前自动将数据保存到文件中等等……
Believe in yourself!