C语言实现动态通讯录:增删改查与文件持久化

小满
小满
发布时间:2026-10-16 | 5人浏览过
原创

本文详细介绍如何利用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语言实战项目的资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表