顺序表是通讯录的底层结构。
通讯录是将顺序表的类型替换成结构体类型来储存用户数据,通过运用顺序表结构来实现的。
用户数据结构:
- typedef struct PersonInfo
- {
- char name[12];
- char sex[10];
- int age;
- char tel[11];
- char addr[100];
- }PeoInfo;
将通讯录的所有功能都一一列出来,让用户一目了然。
Contact.c:
- void menu()
- {
- printf("*******************************************\n");
- printf("******* 1.添加联系人 2.查找联系人 ******\n");
- printf("******* 1.修改联系人 2.删除联系人 ******\n");
- printf("******* 1.查看通讯录 0.退出通讯录 ******\n");
- printf("*******************************************\n");
- }
测试结果如下:
Contact.c:
- int op = -1;
- do {
- menu();
- printf("请选择您的操作:\n");
- scanf("%d", &op);
- switch (op)
- {
- case 1:
- //添加联系人
- break;
- case 2:
- //查找联系人
- break;
- case 3:
- //修改联系人
- break;
- case 4:
- //删除联系人
- break;
- case 5:
- //查看通讯录
- break;
- case 0:
- //退出通讯录
- printf("通讯录退出中.....\n");
- break;
-
- }
- } while(op);
测试结果如下:
Contact.c:
- typedef struct PersonInfo
- {
- char name[NAME_MAX];//使用宏便于后期修改代码
- char sex[SEX_MAX];
- int age;
- char tel[TEL_MAX];
- char addr[ADDR_MAX];
- }PeoInfo;
Contact.h:
- //初始化通讯录
- void InitContact(contact* con);//实际初始化的是顺序表
- //销毁通讯录数据
- void DestroyContact(contact* con);
Contact.c:
- void InitContact(contact* con)
- {
- SLInit(con);
- }
- void DestroyContact(contact* con)
- {
- SLDestory(con);
- }
Contact.h:
void AddContact(contact* con);
Contact.c:
- void AddContact(contact* con)
- {
- SLCheckCapacity(con);
- printf("请输入联系人姓名:\n");
- scanf("%s", con->arr[con->size].name);
- printf("请输入联系人性别:\n");
- scanf("%s", con->arr[con->size].sex);
- printf("请输入联系人年龄:\n");
- scanf("%d", &con->arr[con->size].age);
- printf("请输入联系人电话:\n");
- scanf("%s", con->arr[con->size].tel);
- printf("请输入联系人住址:\n");
- scanf("%s", con->arr[con->size].addr);
- con->size++;
- }
测试结果如下:
Contact.h:
void ShowContact(contact* con);
Contact.c:
- void ShowContact(contact* con) {
- printf("%-20s\t%-5s\t%-4s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
- for (int i = 0; i < con->size; i++)
- {
- printf("%s %s %d %s %s\n",
- con->arr[i].name,
- con->arr[i].sex,
- con->arr[i].age,
- con->arr[i].tel,
- con->arr[i].addr
- );
- }
- }
测试结果如下:
Contact.h:
void FindContact(contact* con);
Contact.c:
- //查找通讯录数据
- int FindByName(contact* con, char name[])//根据需求设计查找的方式
- {
- for (int i = 0; i < con->size; i++)
- {
- if (strcmp(con->arr[i].name, name) == 0)
- {
- return i;
- }
- }
- return -1;
- }
- void FindContact(contact* con)
- {
- char name[NAME_MAX];
- printf("请输入要查找人的名字:\n");
- scanf("%s", name);
- int FindIndex = FindByName(con, name);
- if (FindIndex < 0)
- {
- printf("联系人不存在!\n");
- return;
- }
- printf(%-20s\t%-5s\t%-4s\t%-12s\t%-20s\n, "姓名", "性别", "年龄", "电话", "住址");
- printf(%-20s\t%-5s\t%-4s\t%-12s\t%-20s\n,
- con->arr[FindIndex].name,
- con->arr[FindIndex].sex,
- con->arr[FindIndex].age,
- con->arr[FindIndex].tel,
- con->arr[FindIndex].addr
- );
- }
测试结果如下:
Contact.h:
void DelContact(contact* con);
Contact.c:
- void DelContact(contact* con)
- {
- //删除之前一定要查找
- printf("请输入要删除的联系人的姓名:\n");
- char name[NAME_MAX];
- scanf("%s", name);
- int ret = FindByName(con, name);
- //找不到,不能执行删除
- if (ret < 0)
- {
- printf("要删除的联系人不存在!\n");
- return;
- }
- //执行删除操作
- SLErase(con, ret);
- }
测试结果如下:
Contact.h:
void ModifyContact(contact* con);
Contact.c:
- void ModifyContact(contact* con)
- {
- //修改之前进行查找
- char name[NAME_MAX];
- printf("请输入要修改联系人的姓名:\n");
- scanf("%s",name);
- int findIndex = FindByName(con, name);
- //没有找到,不能执行修改操作
- if (findIndex < 0)
- {
- printf("要修改的联系人不存在!\n");
- return;
- }
- //找到了,执行修改操作
- printf("请输入姓名:\n");
- scanf("%s", con->arr[findIndex].name);
- printf("请输入年龄:\n");
- scanf("%d", &con->arr[findIndex].age);
- printf("请输入性别:\n");
- scanf("%s", con->arr[findIndex].sex);
- printf("请输入电话:\n");
- scanf("%s", con->arr[findIndex].tel);
- printf("请输入地址:\n");
- scanf("%s", con->arr[findIndex].addr);
- printf("修改联系人成功!\n");
- }
- //找到了,执行修改操作
测试结果如下:
上面我们已经实现的通讯录的基本功能,但是我们会发现程序一旦结束,通讯录里储存的数据便会丢失。对于这种情况我们该如何解决呢?
答:将通讯录数据以二进制多大的方式储存到文件里
Contact.h:
void SaveContact(contact* con)
Contact.c:
- void SaveContact(contact* con) {
- FILE* pf = fopen("contact.txt", "wb");
- if (pf == NULL) {
- perror("fopen error!\n");
- return;
- }
- //将通讯录数据写⼊⽂件
- for (int i = 0; i < con->size; i++)
- {
- fwrite(&(con->arr[i]), sizeof(Info), 1, pf);
- }
- printf("通讯录数据保存成功!\n");
- fclose(pf);
- }
测试结果如下:
Contact.h:
void LoadContact(contact* con);
Contact.c:
- void LoadContact(contact* con) {
- FILE* pf = fopen("contact.txt", "rb");
- if (pf == NULL) {
- perror("fopen error!\n");
- return;
- }
- //循环读取⽂件数据
- Info info = { 0 };
- while (fread(&info, sizeof(Info), 1, pf))
- {
- SLCheckCapacity(con);
- con->arr[con->size] = info;
- con->size++;
- }
- //printf("%s %s\n", info.name, info.tel);
- printf("历史数据导入通讯录成功!\n");
- fclose(pf);
-
- }
测试结果如下:
这样我们就不用担心数据丢失了!
SeqList.h:
- #pragma once
- #include
- #include
- #include
- #include
- #include"Contact.h"
- typedef Info SLDataType;
- typedef struct SeqList
- {
- SLDataType* arr;
- int capacity;
- int size;
- }SL;
- //初始化和打印
- void SLInit(SL* ps);
- void SLPrint(SL* ps);
- //扩容
- void SLCheckCapacity(SL* ps);
- //头插和尾插
- void SLPushBack(SL* ps, SLDataType x);
- void SLPushFront(SL* ps, SLDataType x);
- //头删和尾删
- void SLPopBack(SL* ps);
- void SLPopFront(SL* ps);
- //在指定位置插入数据
- void SLInsert(SL* ps, int pos, SLDataType x);
- //在指定位置删除
- void SLErase(SL* ps, int pos);
- //查找数据
- //int SLFind(SL* ps, SLDataType x);
- //销毁
- void SLDestory(SL* ps);
SeqList.c:
- #define _CRT_SECURE_NO_WARNINGS 1
- #include "SeqList.h"
- void SLInit(SL* ps)
- {
- ps->arr = NULL;
- ps->size = ps->capacity = 0;
- }
- //void SLPrint(SL* ps)
- //{
- // for (int i = 0; i < ps->size; i++)
- // {
- // printf("%d ", ps->arr[i]);
- // }
- // printf("\n");
- //}
- //检查内存空间,扩容
- void SLCheckCapacity(SL* ps)
- {
- int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
- SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));
- if (tmp == NULL)
- {
- perror("realloc fall!");
- exit(1);
- }
- ps->arr = tmp;
- ps->capacity = newcapacity;
- }
- //尾插
- void SLPushBack(SL* ps,SLDataType x)
- {
- assert(ps);
- //空间不够,扩容
- SLCheckCapacity(ps);
-
- //空间足够,直接插入
- ps->arr[ps->size++] = x;
- }
- //头插
- 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 SLPopBack(SL* ps) {
- assert(ps);
- //判断顺序表是否为空
- assert(ps->size);
- //不为空
- 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];
-
- }
- ps->size--;
- }
- //在指定位置插入数据
- void SLInsert(SL* ps, int pos, SLDataType x)
- {
- assert(ps && (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 && (pos >= 0 && pos <= ps->size));
- //判断顺序表是否为空
- assert(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;
- //}
- void SLDestory(SL* ps)
- {
- assert(ps);
- if (ps->arr)
- {
- free(ps->arr);
- }
- ps->arr = NULL;
- ps->capacity = ps->size = 0;
- }
Contact.h:
- #pragma once
- #include
- #define NAME_MAX 100
- #define SEX_MAX 10
- #define TEL_MAX 20
- #define ADDR_MAX 100
- //⽤户数据
- typedef struct PersonInfo
- {
- char name[NAME_MAX];
- char sex[SEX_MAX];
- int age;
- char tel[TEL_MAX];
- char addr[ADDR_MAX];
- }Info;
- //前置声明 防止头文件嵌套调用
- typedef struct SeqList contact;
-
- //初始化通讯录
- void InitContact(contact* con);//实际初始化的是顺序表
- //销毁通讯录数据
- void DestroyContact(contact* con);
- //添加通讯录数据
- void AddContact(contact* con);
- //展⽰通讯录数据
- void ShowContact(contact* con);
- //删除通讯录数据
- void DelContact(contact* con);
- //查找通讯录数据
- void FindContact(contact* con);
- //修改通讯录数据
- void ModifyContact(contact* con);
- //保存数据
- void SaveContact(contact* con);
- //读取数据
- void LoadContact(contact* con);
Contact.c:
- #include"SeqList.h"
- void InitContact(contact* con)
- {
- SLInit(con);
- }
- void DestroyContact(contact* con)
- {
- SLDestory(con);
- }
- //添加联系人
- void AddContact(contact* con)
- {
- SLCheckCapacity(con);
- printf("请输入联系人姓名:\n");
- scanf("%s", con->arr[con->size].name);
- printf("请输入联系人性别:\n");
- scanf("%s", con->arr[con->size].sex);
- printf("请输入联系人年龄:\n");
- scanf("%d", &con->arr[con->size].age);
- printf("请输入联系人电话:\n");
- scanf("%s", con->arr[con->size].tel);
- printf("请输入联系人住址:\n");
- scanf("%s", con->arr[con->size].addr);
- con->size++;
- }
- //展⽰通讯录数据
- void ShowContact(contact* con) {
- printf("%-20s\t%-5s\t%-4s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
- for (int i = 0; i < con->size; i++)
- {
- printf("%-20s\t%-5s\t%-4d\t%-12s\t%-20s\n",
- con->arr[i].name,
- con->arr[i].sex,
- con->arr[i].age,
- con->arr[i].tel,
- con->arr[i].addr
- );
- }
- }
- //查找通讯录数据
- int FindByName(contact* con, char name[])//根据需求设计查找的方式
- {
- for (int i = 0; i < con->size; i++)
- {
- if (strcmp(con->arr[i].name, name) == 0)
- {
- return i;
- }
- }
- return -1;
- }
- void FindContact(contact* con)
- {
- char name[NAME_MAX];
- printf("请输入要查找人的名字:\n");
- scanf("%s", name);
- int FindIndex = FindByName(con, name);
- if (FindIndex < 0)
- {
- printf("联系人不存在!\n");
- return;
- }
- printf("%-20s\t%-5s\t%-4s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址");
- printf("%-20s\t%-5s\t%-4d\t%-12s\t%-20s\n",
- con->arr[FindIndex].name,
- con->arr[FindIndex].sex,
- con->arr[FindIndex].age,
- con->arr[FindIndex].tel,
- con->arr[FindIndex].addr
- );
- }
- //删除通讯录数据
- void DelContact(contact* con)
- {
- //删除之前一定要查找
- printf("请输入要删除的联系人的姓名:\n");
- char name[NAME_MAX];
- scanf("%s", name);
- int ret = FindByName(con, name);
- //找不到,不能执行删除
- if (ret < 0)
- {
- printf("要删除的联系人不存在!\n");
- return;
- }
- //执行删除操作
- SLErase(con, ret);
- }
- //修改通讯录数据
- void ModifyContact(contact* con)
- {
- //修改之前进行查找
- char name[NAME_MAX];
- printf("请输入要修改联系人的姓名:\n");
- scanf("%s",name);
- int findIndex = FindByName(con, name);
- //没有找到,不能执行修改操作
- if (findIndex < 0)
- {
- printf("要修改的联系人不存在!\n");
- return;
- }
- //找到了,执行修改操作
- printf("请输入姓名:\n");
- scanf("%s", con->arr[findIndex].name);
- printf("请输入年龄:\n");
- scanf("%d", &con->arr[findIndex].age);
- printf("请输入性别:\n");
- scanf("%s", con->arr[findIndex].sex);
- printf("请输入电话:\n");
- scanf("%s", con->arr[findIndex].tel);
- printf("请输入地址:\n");
- scanf("%s", con->arr[findIndex].addr);
- printf("修改联系人成功!\n");
- }
- //保存数据
- void SaveContact(contact* con) {
- FILE* pf = fopen("contact.txt", "wb");
- if (pf == NULL) {
- perror("fopen error!\n");
- return;
- }
- //将通讯录数据写⼊⽂件
- for (int i = 0; i < con->size; i++)
- {
- fwrite(&(con->arr[i]), sizeof(Info), 1, pf);
- }
- printf("通讯录数据保存成功!\n");
- fclose(pf);
- pf = NULL;
- }
- //读取数据
- void LoadContact(contact* con) {
- FILE* pf = fopen("contact.txt", "rb");
- if (pf == NULL) {
- perror("fopen error!\n");
- return;
- }
- //循环读取⽂件数据
- Info info = { 0 };
- while (fread(&info, sizeof(Info), 1, pf))
- {
- SLCheckCapacity(con);
- con->arr[con->size] = info;
- con->size++;
- }
- //printf("%s %s\n", info.name, info.tel);
- printf("历史数据导入通讯录成功!\n");
- fclose(pf);
- pf = NULL;
- }
ConTest.c
- #include"SeqList.h"
- void menu()
- {
- printf("*******************************************\n");
- printf("******* 1.添加联系人 2.查找联系人 ******\n");
- printf("******* 3.修改联系人 4.删除联系人 ******\n");
- printf("******* 5.查看通讯录 0.退出通讯录 ******\n");
- printf("*******************************************\n");
- }
- int main()
- {
- int op = -1;
- contact con;
- //通讯录初始化
- InitContact(&con);
- LoadContact(&con);
- do {
-
- menu();
- printf("请选择您的操作:\n");
- scanf("%d", &op);
- switch (op)
- {
- case 1:
- //添加联系人
- AddContact(&con);
- break;
- case 2:
- //查找联系人
- FindContact(&con);
- break;
- case 3:
- //修改联系人
- ModifyContact(&con);
- break;
- case 4:
- //删除联系人
- DelContact(&con);
- printf("联系人删除成功!\n");
- break;
- case 5:
- //查看通讯录
- ShowContact(&con);
- break;
- break;
- case 0:
- //退出通讯录
- printf("通讯录退出中.....\n");
- break;
- }
- } while (op);
- SaveContact(&con);
- DestroyContact(&con);
- return 0;
- }
对于顺序表代码的实现在上一篇中有讲解,如果有的小伙伴有兴趣,可以去看一看。链接在下方:http://t.csdnimg.cn/wpM1t
本文为作者学习后的总结,如果有什么不恰当的地方,欢迎大佬指正!!!