【数据结构】顺序表的应用:基于动态顺序表实现通讯录

📅 2026/7/18 11:44:35
【数据结构】顺序表的应用:基于动态顺序表实现通讯录
目录基于动态顺序表实现通讯录功能要求实现过程定义结构体声明通讯录相关函数通讯录初始化通讯录销毁通讯录添加数据通讯录删除数据展示通讯录数据打印通讯录修改数据通讯录查找数据完整代码基于动态顺序表实现通讯录C语言基础要求结构体、动态内存管理、顺序表、文件操作功能要求1、至少能够存储100人的通讯信息2、能够保存的用户信息姓名、性别、年龄、电话、地址等3、增加联系人信息4、删除指定联系人5、查找指定联系人6、修改指定联系人7、显示指定联系人实现过程和顺序表的实现类似通讯录的实现也需要相应的Contact.h和Contact.c文件定义结构体因为顺序表中不仅可以保存内置类型还可以保存自定义类型所以在Contact.h中定义personInfo结构体用来保存联系人信息并给该类型起别名为PeoInfo为了方便修改可以将结构体中的数组大小定义为常量#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]; // male female int age; char tel[TEL_MAX]; char addr[ADDR_MAX]; }PeoInfo;因为顺序表中存储的数据是自定义类型数据所以需要在SeqList.h中修改。此处修改完成会出现很多报错将SeqList.c中报错的代码暂时注释掉即可typedef struct personInfo SLDataType;声明通讯录相关函数// 实现通讯录相关的方法 要用到顺序表的方法对通讯录进行操作实际上就是对顺序表进行操作 // 给顺序表改个名字叫做 Contact方便查看前置声明 typedef struct SeqList Contact; // 通讯录初始化 void ContactInit(Contact* con); // 形参的名字改成 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 ContactInit(Contact* con) { // 通讯录初始化就是顺序表初始化 // 顺序表初始化已经定义好了直接使用即可 SLInit(con); }测试通讯录初始化函数是否正确void ContactText01() { Contact con; ContactInit(con); } int main() { /*text01();*/ ContactText01(); return 0; }通讯录销毁与通讯录的初始化类似通讯录销毁就是顺序表销毁直接使用即可// 通讯录销毁 void ContactDestroy(Contact* con) { SLDestroy(con); }调试通讯录添加数据要想向通讯录中添加数据先要用户输入数据存储在联系人信息结构体中逐个输入后再使用顺序表添加函数添加到通讯录中// 通讯录添加数据 void ContactAdd(Contact* con) { // 获取用户输入的数据 personInfo info; // 创建一个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); }调试通讯录删除数据想要删除通讯录中指定姓名的联系人数据要先查到该姓名对应的位置所以要先写一个FindByName函数//根据姓名查找并返回下标值 int FindByName(Contact* con, char name[]);//根据姓名查找并返回下标值 int FindByName(Contact* con, char name[]) { for (int i 0; i con-size; i) { if (strcmp(name, con-arr[i].name) 0) { return i; } } return -1; }这个函数通过遍历通讯录中的所有联系人姓名并和要删除的数据比较获取下标值如果该数据不存在就返回一个无效下标值-1。然后完成通讯录数据删除的函数。先定义一个数组用来存放要删除的联系人姓名获取用户输入然后将获取到的要删除的联系人姓名传入FindByName函数根据FindByName函数的返回值做出不同处理如果返回值小于0就输出输入的数据不存在其他情况就根据返回的下标值进行删除调用SLErase函数并输出删除成功告知用户。// 通讯录删除数据 void ContactDel(Contact* con) { char name[NAME_MAX]; printf(请输入要删除的联系人姓名:\n); scanf(%s, name); int find FindByName(con, name); if (find 0) { printf(输入的联系人姓名不存在\n); } else { SLErase(con, find); printf(删除成功\n); } }展示通讯录数据打印// 通讯录显示数据打印 void ContactShow(Contact con) { // 表头:姓名、性别、年龄、电话、地址 printf(%-20s %-10s %-5s %-20s %-100s\n,姓名,性别,年龄,电话,地址); for (int i 0; i con.size; i) { printf(%-20s %-10s %-5d %-20s %-100s\n, con.arr[i].name, con.arr[i].gender, con.arr[i].age, con.arr[i].tel, con.arr[i].addr); } }通讯录修改数据void ContactModify(Contact* con) { char name[NAME_MAX]; printf(请输入要修改的联系人姓名\n); scanf(%s, name); int find FindByName(con, name); if (find 0) { printf(输入的联系人姓名不存在\n); } else { 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); } else { printf(%-20s %-10s %-5s %-20s %s\n, 姓名, 性别, 年龄, 电话, 地址); printf(%-20s %-10s %-5d %-20s %s\n, con-arr[find].name, con-arr[find].gender, con-arr[find].age, con-arr[find].tel, con-arr[find].addr); } }完整代码SeqList.h#define _CRT_SECURE_NO_WARNINGS 1 // 完成顺序表的定义和方法的声明 // 此头文件需在 SeqList.c 和 text.c 中同时包含 #pragma once #includestdio.h #includestdlib.h #includeassert.h #includeContact.h #includestring.h typedef struct personInfo SLDataType; typedef struct SeqList { SLDataType* arr; int size; int capacity; }SL; void SLInit(SL* ps); // 顺序表初始化 void SLDestroy(SL* ps); // 顺序表销毁 void SLPrint(SL s); // 顺序表打印 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);SeqList.c#includeSeqList.h //顺序表初始化 void SLInit(SL* ps) { ps-arr NULL; ps-size ps-capacity 0; } // 顺序表销毁 void SLDestroy(SL* ps) { if (ps-arr) { free(ps-arr); // 此处释放空间 } ps-arr NULL; ps-size ps-capacity 0; } //// 顺序表打印 //void SLPrint(SL s) //{ // for (int i 0; i s.size; i) // { // printf(%d , s.arr[i]); // } // printf(\n); //} // 顺序表检查检查空间是否够用如果不够就增大 void SLCheckCapacity(SL* ps) { if (ps-capacity ps-size) { int newCapacity (ps-capacity 0) ? 4 : 2 * ps-capacity; SLDataType* tmp (SLDataType*)realloc(ps-arr, newCapacity * sizeof(SLDataType)); // 先定义临时变量接收realloc的返回值 if (tmp NULL) // 如果realloc返回值是NULL,就报错并退出程序 { perror(realloc error!); exit(1); } ps-arr tmp; ps-capacity newCapacity; } } // 顺序表增加 // 需要先检测空间是否够用 void SLPushBack(SL* ps,SLDataType x) // 尾部增加 { assert(ps); SLCheckCapacity(ps); 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 SLPopBack(SL* ps) // 尾部删除 { assert(ps); assert(ps-size); // 此处需要检查有效数据个数是否为0 ps-size--; } void SLPopFront(SL* ps) // 头部删除 { assert(ps); assert(ps-size - 1); 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; i) { ps-arr[i] ps-arr[i 1]; } ps-size--; } //// 顺序表查找 //int SLFind(SL* ps, SLDataType x) //{ // for (int i 0; i ps-size; i) // { // if (ps-arr[i] x) // { // return i; // } // } // return -1; //}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]; // male female int age; char tel[TEL_MAX]; char addr[ADDR_MAX]; }PeoInfo; // 实现通讯录相关的方法 要用到顺序表的方法对通讯录进行操作实际上就是对顺序表进行操作 // 给顺序表改个名字叫做 Contact方便查看前置声明 typedef struct SeqList Contact; // 通讯录初始化 void ContactInit(Contact* con); // 形参的名字改成 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); //根据姓名查找并返回下标值 int FindByName(Contact* con, char name[]);Contact.c#includeContact.h #includeSeqList.h typedef struct SeqList Contact; // 通讯录初始化 void ContactInit(Contact* con) { // 通讯录初始化就是顺序表初始化 // 顺序表初始化已经定义好了直接导入即可 SLInit(con); } // 通讯录销毁 void ContactDestroy(Contact* con) { SLDestroy(con); } // 通讯录添加数据 void ContactAdd(Contact* con) { // 获取用户输入的数据 personInfo info; // 创建一个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); } // 通讯录删除数据 void ContactDel(Contact* con) { char name[NAME_MAX]; printf(请输入要删除的联系人姓名:\n); scanf(%s, name); int find FindByName(con, name); if (find 0) { printf(输入的联系人姓名不存在\n); } else { 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); } else { 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); } else { printf(%-20s %-10s %-5s %-20s %s\n, 姓名, 性别, 年龄, 电话, 地址); printf(%-20s %-10s %-5d %-20s %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(%-20s %-10s %-5s %-20s %s\n,姓名,性别,年龄,电话,地址); for (int i 0; i con.size; i) { printf(%-20s %-10s %-5d %-20s %s\n, con.arr[i].name, con.arr[i].gender, 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(name, con-arr[i].name) 0) { return i; } } return -1; }完