【数据结构】顺序表的应用:基于动态顺序表实现通讯录
2026/7/18 11:44:29 网站建设 项目流程

目录

基于动态顺序表实现通讯录

功能要求

实现过程

定义结构体

声明通讯录相关函数

通讯录初始化

通讯录销毁

通讯录添加数据

通讯录删除数据

展示通讯录数据(打印)

通讯录修改数据

通讯录查找数据

完整代码


基于动态顺序表实现通讯录

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 #include<stdio.h> #include<stdlib.h> #include<assert.h> #include"Contact.h" #include<string.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

#include"SeqList.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

#include"Contact.h" #include"SeqList.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; }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询