
个人主页 : 流年如梦
文章目录
- 一.基于动态顺序表实现通讯录
- 二.整体结构
- 三.通讯录的实现
-
- [3.1SeqList.h --> 顺序表声明](#3.1SeqList.h --> 顺序表声明)
- [3.2contact.h --> 通讯录声明](#3.2contact.h --> 通讯录声明)
- 3.3核心功能(增、删、查、改、显示等)
-
- 3.3.1初始化+加载历史数据
- [3.3.2添加联系人 --> "增"](#3.3.2添加联系人 --> "增")
- [3.3.3删除联系人 --> "删"](#3.3.3删除联系人 --> "删")
- [3.3.4按姓名查找 --> "查"](#3.3.4按姓名查找 --> "查")
- [3.3.5修改联系人 --> "改"](#3.3.5修改联系人 --> "改")
- [3.3.6显示所有联系人 -- > "显示"](#3.3.6显示所有联系人 -- > "显示")
- 3.3.7退出时保存文件+销毁
- [3.4test.c --> 主函数](#3.4test.c --> 主函数)
- 3.5最终运行结果(截图)
- 🎯总结
- ⚠️易错点
Ladies and gentlemen,此次我们将要通过我们之前所学的知识一起来学习如何实现简单通讯录,简单实现通讯录将会涉及到的知识点分别有:结构体、动态内存管理、顺序表、文件操作
一.基于动态顺序表实现通讯录
1.1通讯录主要功能要求
- 存储至少100人信息
- 姓名、性别、年龄、电话、地址
- 要有增、删、查、改、显示(核心功能)
- 程序退出数据不会丢失(文件需要保存下来)
二.整体结构
分别有:
SeqList.h/c--> 动态顺序表底层contact.h/c--> 通讯录业务逻辑test.c--> 测试菜单
三.通讯录的实现
3.1SeqList.h --> 顺序表声明
SeqList.c顺序表的实现在这里👉顺序表
如下所示:
c
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"contact.h"
typedef struct PersonInfo SQDataType;
typedef struct SeqList
{
SQDataType* a;
int size;
int capacity;
}SLT;
//基础接口
void SeqListInit(SLT* psl);
void SeqListDesTroy(SLT* psl);
void SeqListPushBack(SLT* psl, SQDataType x);
void SeqListErase(SLT* psl, size_t pos);
int SeqListFind(SLT* psl, SQDataType x);
3.2contact.h --> 通讯录声明
代码参考:
c
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
typedef struct SeqList contact;
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//通讯录接口
void InitContact(contact* con);
void AddContact(contact* con);
void DelContact(contact* con);
void ShowContact(contact* con);
void FindContact(contact* con);
void ModifyContact(contact* con);
void DestroyContact(contact* con);
3.3核心功能(增、删、查、改、显示等)
3.3.1初始化+加载历史数据
c
void LoadContact(contact* con)
{
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return;
}
PeoInfo info;
while (fread(&info, sizeof(PeoInfo), 1, pf))
{
SeqListPushBack(con, info);
}
fclose(pf);
}
void InitContact(contact* con)
{
SeqListInit(con);
LoadContact(con);
}
3.3.2添加联系人 --> "增"
c
void AddContact(contact* con)
{
PeoInfo info;
printf("请输入姓名:");
scanf("%s", info.name);
printf("请输入性别:");
scanf("%s", info.sex);
printf("请输入年龄:");
scanf("%d", &info.age);
printf("请输入电话:");
scanf("%s", info.tel);
printf("请输入地址:");
scanf("%s", info.addr);
SeqListPushBack(con, info);
printf("添加成功!\n");
}
3.3.3删除联系人 --> "删"
c
void DelContact(contact* con)
{
char name[NAME_MAX];
printf("请输入要删除的姓名:");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos == -1)
{
printf("用户不存在\n");
return;
}
SeqListErase(con, pos);
printf("删除成功!\n");
}
3.3.4按姓名查找 --> "查"
c
int FindByName(contact* con, char name[])
{
for (int i = 0; i < con->size; i++)
{
if (strcmp(con->a[i].name, name) == 0)
return i;
}
return -1;
}
3.3.5修改联系人 --> "改"
c
void ModifyContact(contact* con)
{
char name[NAME_MAX];
printf("请输入要修改的姓名:");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos == -1)
{
printf("用户不存在\n");
return;
}
printf("请输入新姓名:");
scanf("%s", con->a[pos].name);
printf("请输入新性别:");
scanf("%s", con->a[pos].sex);
printf("请输入新年龄:");
scanf("%d", &con->a[pos].age);
printf("请输入新电话:");
scanf("%s", con->a[pos].tel);
printf("请输入新地址:");
scanf("%s", con->a[pos].addr);
printf("修改成功!\n");
}
3.3.6显示所有联系人 -- > "显示"
c
void ShowContact(contact* con)
{
printf("%-10s %-4s %-4s %-15s %-20s\n","姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%-10s %-4s %-4d %-15s %-20s\n",
con->a[i].name,
con->a[i].sex,
con->a[i].age,
con->a[i].tel,
con->a[i].addr);
}
}
3.3.7退出时保存文件+销毁
c
void SaveContact(contact* con)
{
FILE* pf = fopen("contact.txt", "wb");
for (int i = 0; i < con->size; i++)
{
fwrite(con->a + i, sizeof(PeoInfo), 1, pf);
}
fclose(pf);
printf("保存成功!\n");
}
void DestroyContact(contact* con)
{
SaveContact(con);
SeqListDesTroy(con);
}
3.4test.c --> 主函数
代码如下:
c
void menu()
{
contact con;
InitContact(&con);
int op = 0;
do
{
printf("1.添加 2.删除 3.查找 4.修改 5.显示 0.退出\n");
scanf("%d", &op);
switch (op)
{
case 1: AddContact(&con); break;
case 2: DelContact(&con); break;
case 3: FindContact(&con); break;
case 4: ModifyContact(&con); break;
case 5: ShowContact(&con); break;
case 0: DestroyContact(&con); break;
default: printf("输入错误\n");
}
} while (op != 0);
}
3.5最终运行结果(截图)

🎯总结
- 动态顺序表可以快速实现增删查改的项目
- 通讯录 = 顺序表 + 结构体 + 文件操作
- 文件读写用
fread/fwrite二进制方式,数据可持久化 - 顺序表支持随机访问 ,但插入删除低效
- 空间浪费、扩容开销是顺序表的硬伤
⚠️易错点
- 文件打开忘记判断空指针
- 增容忘记判断、导致越界
- 删除或插入不判断
pos合法性- 字符串比较不用
strcmp- 文件名写错导致数据加载或保存失败
👀 关注 我们一路同行,从入门到大师,慢慢沉淀、稳步成长
❤️ 点赞 鼓励原创,让优质内容被更多人看见
⭐ 收藏 收好核心知识点与实战技巧,需要时随时查阅
💬 评论 分享你的疑问或踩坑经历,一起交流避坑、共同进步