C语言实现动态通讯录:增删改查与文件持久化
本文详细介绍如何利用C语言开发一个具备增、删、改、查、排序功能的动态通讯录系统。核心内容包括使用结构体定义数据模型、通过 malloc 和 realloc 实现动态容量扩展,以及利用文件 I/O 完成数据的保存与加载,解决程序重启后数据丢失的问题。
设计目标与数据结构
该通讯录系统旨在管理联系人的基本信息,包括姓名、年龄、性别、电话和住址。为了实现灵活的数据存储,我们采用动态数组的方式,根据用户添加的联系人数自动调整内存空间。
第1步:定义基础数据结构
首先定义 PeoInfo 结构体存储单个联系人的信息,并定义 Contact 结构体作为通讯录容器,记录数据指针、当前元素个数及当前最大容量。
#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define DEFAULT 3
#define NAME_MAX 20
#define SEX_MAX 10
#define TELE_MAX 12
#define ADDR_MAX 50
//描述联系人的信息
struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
//通讯录-动态增长版本
struct Contact
{
struct PeoInfo* data;
int sz;//通讯录中当前有效元素个数
int capacity;//通讯录的当前最大容量
};
第2步:构建主菜单与运行逻辑
在 test.c 中建立主循环,通过枚举值映射功能选项。程序启动时初始化通讯录,用户选择操作后调用对应函数,退出前保存数据并释放内存。
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
printf("#####################################\n");
printf("##### 1. add 2. del #####\n");
printf("##### 3. search 4. modify #####\n");
printf("##### 5. show 6. sort #####\n");
printf("##### 0. exit #####\n");
printf("#####################################\n");
}
enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT };
int main()
{
int input = 0;
struct Contact con;
InitContact(&con);
do {
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input) {
case ADD: AddContact(&con); break;
case DEL: DelContact(&con); break;
case SEARCH: SearchContact(&con); break;
case MODIFY: ModifyContact(&con); break;
case SHOW: ShowContact(&con); break;
case SORT: SortContact(&con); break;
case EXIT:
SaveContact(&con);
DestroyContact(&con);
printf("退出\n");
break;
default: printf("选择错误\n"); break;
}
} while (input);
return 0;
}
核心功能实现:增删改查与排序
所有业务逻辑封装在 contact.c 中,并通过断言检查参数有效性。
第3步:实现容量检测与动态增容
在添加联系人前,必须检查当前容量。若有效元素数量等于容量,则使用 realloc 扩容,通常每次增加固定大小(如2个单位)。
void CheckCapacity(struct Contact* pc)
{
assert(pc);
if (pc->sz == pc->capacity) {
struct PeoInfo* ptr = realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo));
if (ptr != NULL) {
pc->data = ptr;
pc->capacity += 2;
printf("增容成功\n");
} else {
perror("AddContact::realloc");
return;
}
}
}
第4步:增加、删除与修改联系人
- 增加 (
AddContact): 先检查容量,随后依次读取用户输入的姓名、年龄等信息,存入data[sz]并递增sz。 - 删除 (
DelContact): 通过名字查找联系人位置。若找到,将该位置后的所有元素向前移动一位覆盖,最后递减sz。 - 修改 (
ModifyContact): 查找定位后,直接覆盖该位置的字段内容。
第5步:查找与显示联系人
查找基于线性搜索,返回索引或 -1。显示功能遍历所有有效元素,按列对齐打印表格信息。
//查找指定联系人
int FindContactByName(const struct Contact* pc, const char* name)
{
assert(pc && name);
for (int i = 0; i < pc->sz; i++) {
if (strcmp(pc->data[i].name, name) == 0) {
return i;
}
}
return -1;
}
第6步:排序通讯录
利用 C 标准库的 qsort 函数,提供比较回调函数(如按名字 strcmp 或按年龄相减),实现对通讯录的整体排序。
void SortContact(struct Contact* pc)
{
assert(pc);
int input = 0;
if (pc->sz == 0) { printf("通讯录为空,无法排序\n"); return; }
printf("按名字排序请输入1,年龄排序请输入2:>");
scanf("%d", &input);
if (input == 1) {
qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp_by_name);
} else {
qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp_by_age);
}
}
数据持久化:保存与加载
为了保证程序重启后联系人数据不丢失,需将内存中的数据序列化到本地文件,或在启动时反序列化回内存。
第7步:保存通讯录到文件
以二进制写入模式打开 contact.txt,遍历所有有效联系人,使用 fwrite 逐条写入。
void SaveContact(struct Contact* pc)
{
assert(pc);
FILE* pfWrite = fopen("contact.txt", "wb");
if (NULL == pfWrite) {
perror("open file for writting");
return;
}
for (int i = 0; i < pc->sz; i++) {
fwrite(pc->data+i, sizeof(struct PeoInfo), 1, pfWrite);
}
fclose(pfWrite);
pfWrite = NULL;
}
第8步:从文件加载数据
初始化通讯录时调用此函数。以只读二进制模式打开文件,循环使用 fread 读取数据。每次读取前务必先调用 CheckCapacity 确保安全写入,防止越界。
void LoadContact(struct Contact* pc)
{
assert(pc);
struct PeoInfo tmp = { 0 };
FILE* pfRead = fopen("contact.txt", "rb");
if (NULL == pfRead) {
perror("open file for reading");
return;
}
while (fread(&tmp, sizeof(struct PeoInfo), 1, pfRead)) {
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
fclose(pfRead);
pfRead = NULL;
}
测试结果与验证
程序运行界面展示了主菜单的逻辑流转,用户可以顺畅地进行各项操作。
添加新联系人后,系统提示成功,此时内存中的有效计数增加。
执行删除操作,输入指定姓名,系统定位并移除对应的数据结构单元。
查找功能准确定位联系人并展示详细信息,格式对齐清晰。
修改功能允许更新现有联系人的任意字段,输入新值后即时生效。
排序功能支持按姓名或年龄升序排列,底层依赖快速排序算法。
完整的通讯录视图显示了当前内存中所有存储的有效条目。
当再次运行程序时,可以看到之前添加并保存的联系人已被自动加载。由于默认初始容量为3,而文件中存有4位联系人,系统在初始化阶段自动触发了增容机制,证明了动态内存管理与文件IO模块协同工作正常。
以上就是C语言实现简单通讯录功能的详细内容,更多关于C语言实战项目的资料请关注本站其它相关文章!本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













