手把手教你用C语言实现通讯录管理系统

简介: 手把手教你用C语言实现通讯录管理系统

一、引言

在日常生活中,我们经常需要管理大量的联系人信息,如姓名、性别、年龄、电话和地址等。为了方便地管理和查询这些信息,我们可以使用C语言编写一个通讯录管理系统。本文将带领大家一步步实现这个系统。

二、需求分析

1.项目概述

通讯录管理系统是一款用于存储、管理和操作联系人信息的程序。该系统允许用户添加、删除、修改、查找和展示联系人,并将数据持久化到文件中,以便在程序重新启动时可以恢复数据。

2.功能需求

添加联系人:允许用户添加新的联系人信息

删除联系人:根据用户输入的联系人姓名,删除对应的联系人信息。

修改联系人:允许用户修改已添加的联系人信息。

查询联系人:根据用户输入的联系人姓名,查询对应的联系人信息。

显示联系人:显示所有已添加的联系人信息。

加载数据:在程序启动时,系统需要从指定的文件中读取联系人数据,并恢复通讯录的状态。

保存数据: 在程序关闭前,系统需要将当前通讯录数据持久化到文件中,以便在下次启动程序时可以恢复数据。

3.数据结构设计

为了存储联系人信息,我们定义一个结构体如下:

typedef struct personInfo
{
  char name[NAME_MAX];//姓名
  char gender[GENDER_MAX];//性别
  int age;//年龄
  char tel[TEL_MAX];//电话号码
  char address[ADDRESS_MAX];//地址
}Per;

三、功能设计

1.初始化通讯录

初始化通讯录管理系统,准备接收用户操作。

//初始化
void ContactInit(Con* p)
{
  p->arr = NULL;
  p->size = p->capacity = 0;
}

2. 添加联系人

提示用户输入联系人的姓名、性别、年龄、电话和地址。
提示用户添加成功。

//检查容量
void checkcapacity(Con* p)
{
  if (p->size == p->capacity)
  {
    int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
    DataType* tmp = (DataType*)realloc(p->arr, newcapacity * sizeof(DataType));
    if (tmp == NULL)
    {
      perror("realloc fail");
      exit(1);
    }
    //空间申请成功
    p->arr = tmp;
    p->capacity = newcapacity;
  }
}
//顺序表尾插
void SLPushBack(Con* p, DataType x)
{
  assert(p);
  checkcapacity(p);
  p->arr[p->size++] = x;
}
//添加数据
void ContactAdd(Con* p)
{
  Per 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.address);
  SLPushBack(p, info);
  printf("添加成功!\n");
}

3. 删除联系人

提示用户输入要删除联系人的姓名。
在通讯录文件中查找对应的联系人。
如果找到,删除该联系人的信息,并提示用户删除成功。
如果未找到,提示用户联系人不存在。

//查找数据
int FindByName(Con* p, char name[])
{
  for (int i = 0; i < p->size; i++)
  {
    if (strcmp(p->arr[i].name, name) == 0)
      return i;//找到了
  }
  return -1;//没有找到
}
//删除数据
void ContactDel(Con* p)
{
  //前提是数据必须存在才能删除---查找数据是否存在
  char name[NAME_MAX];
  printf("请输入要删除的联系人姓名:\n");
  scanf("%s", name);
  int find = FindByName(p, name);
  if (find < 0)
  {
    printf("要删除的联系人不存在!\n");
    return;
  }
  SLErase(p, find);
  printf("删除成功!\n");
}

4. 修改联系人

提示用户输入要修改联系人的姓名。
在通讯录文件中查找对应的联系人。
如果找到,允许用户修改联系人的信息,并提示用户修改成功。
如果未找到,提示用户联系人不存在。

//查找数据
/*
int FindByName(Con* p, char name[])
{
  for (int i = 0; i < p->size; i++)
  {
    if (strcmp(p->arr[i].name, name) == 0)
      return i;//找到了
  }
  return -1;//没有找到
}
*/
//通讯录的修改
void ContactMod(Con* p)
{
  //前提是数据必须存在才能修改---查找数据是否存在
  char name[NAME_MAX];
  printf("请输入要修改的联系人姓名:\n");
  scanf("%s", name);
  int find = FindByName(p, name);
  if (find < 0)
  {
    printf("要修改的联系人不存在!\n");
    return;
  }
  //直接修改
  printf("请输入修改后的姓名:\n");
  scanf("%s", p->arr[find].name);
  printf("请输入修改后的性别:\n");
  scanf("%s", p->arr[find].gender);
  printf("请输入修改后的年龄:\n");
  scanf("%d", &p->arr[find].age);
  printf("请输入修改后的电话:\n");
  scanf("%s", p->arr[find].tel);
  printf("请输入修改后的地址:\n");
  scanf("%s", p->arr[find].address);
  printf("修改成功!\n");
}

5. 查询联系人

提示用户输入要查询联系人的姓名。
在通讯录中查找对应的联系人。
如果找到,显示该联系人的详细信息。
如果未找到,提示用户联系人不存在。

//查找数据
/*
int FindByName(Con* p, char name[])
{
  for (int i = 0; i < p->size; i++)
  {
    if (strcmp(p->arr[i].name, name) == 0)
      return i;//找到了
  }
  return -1;//没有找到
}
*/
void ContactFind(Con* p)
{
  char name[NAME_MAX];
  printf("请输入要查找的联系人姓名:\n");
  scanf("%s", name);
  int find = FindByName(p, name);
  if (find < 0)
  {
    printf("要查找的联系人不存在!\n");
    return;
  }
  printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
  printf("%s\t%s\t%d\t%s\t%s\t\n",
    p->arr[find].name,
    p->arr[find].gender,
    p->arr[find].age,
    p->arr[find].tel,
    p->arr[find].address
  );
}

6. 展示所有联系人

读取通讯录中的所有联系人信息。
在屏幕上以表格形式展示所有联系人信息。

//展示通讯录
void ContactShow(Con* p)
{
  //表头:姓名  性别  年龄  电话  地址    
  printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
  for (int i = 0; i < p->size; i++)
  {
    printf("%s\t%s\t%d\t%s\t%s\t\n",
      p->arr[i].name,
      p->arr[i].gender,
      p->arr[i].age,
      p->arr[i].tel,
      p->arr[i].address
    );
  }
}

7. 保存文件

在程序退出前,保存所有更改到通讯录文件。

//将数据保存到文件中
void SaveContact(Con* p) {
  FILE* pf = fopen("contact.txt", "wb");
  if (pf == NULL) {
    perror("fopen error!\n");
    return;
  }
  //将通讯录数据写入文件
  for (int i = 0; i < p->size; i++)
  {
    fwrite(p->arr + i, sizeof(Per), 1, pf);
  }
  printf("通讯录数据保存成功!\n");
}

8. 加载数据

程序启动时,自动加载通讯录文件中的历史数据。
如果文件不存在或为空,则初始化一个空的通讯录。

//从文件读取历史数据
void LoadContact(Con* p) {
  FILE* pf = fopen("contact.txt", "rb");
  if (pf == NULL) {
    perror("fopen error!\n");
    return;
  }
  //循环读取文件数据
  Per info;
  printf("正在导入历史数据...\n");
  Sleep(1000);
  while (fread(&info, sizeof(Per), 1, pf))
  {
    SLPushBack(p, info);
  }
  printf("历史数据导入通讯录成功!\n");
  system("pause");
  system("cls");
}

四、完整代码

1.Contact.h

#pragma once
#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDRESS_MAX 100
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<windows.h>
//定义结构体存储个人信息(自定义类型)
typedef struct personInfo
{
  char name[NAME_MAX];
  char gender[GENDER_MAX];
  int age;
  char tel[TEL_MAX];
  char address[ADDRESS_MAX];
}Per;
typedef Per DataType;//这里类型为自定义类型Per
//通讯录:底层为顺序表
typedef struct Contact
{
  DataType* arr;
  int size;//有效数据个数
  int capacity;//容量
}Con;
 
//初始化通讯录
void ContactInit(Con* p);
//销毁通讯录
void ContactDestory(Con* p);
//展示通讯录
void ContactShow(Con* p);
//添加数据
void ContactAdd(Con* p);
//删除数据
void ContactDel(Con* p);
//通讯录的修改
void ContactMod(Con* p);
//通讯录的查找
void ContactFind(Con* p);
//从文件读取历史数据
void LoadContact(Con* p);
//将数据保存到文件中
void SaveContact(Con* p);

2.Contact.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
//初始化
void ContactInit(Con* p)
{
  p->arr = NULL;
  p->size = p->capacity = 0;
}
//销毁
void ContactDestory(Con* p)
{
  if (p->arr)
  {
    free(p->arr);
  }
  p->arr = NULL;
  p->size = p->capacity = 0;
}
//检查容量
void checkcapacity(Con* p)
{
  if (p->size == p->capacity)
  {
    int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
    DataType* tmp = (DataType*)realloc(p->arr, newcapacity * sizeof(DataType));
    if (tmp == NULL)
    {
      perror("realloc fail");
      exit(1);
    }
    //空间申请成功
    p->arr = tmp;
    p->capacity = newcapacity;
  }
}
//顺序表尾插
void SLPushBack(Con* p, DataType x)
{
  assert(p);
  checkcapacity(p);
  p->arr[p->size++] = x;
}
//删除指定位置的数据
void SLErase(Con* p, int pos)
{
  assert(p);
  assert(pos >= 0 && pos < p->size);
  for (int i = pos; i <= p->size - 2; i++)
  {
    p->arr[i] = p->arr[i + 1];
  }
  p->size--;
}
//添加数据
void ContactAdd(Con* p)
{
  Per 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.address);
  SLPushBack(p, info);
  printf("添加成功!\n");
}
//查找数据
int FindByName(Con* p, char name[])
{
  for (int i = 0; i < p->size; i++)
  {
    if (strcmp(p->arr[i].name, name) == 0)
      return i;//找到了
  }
  return -1;//没有找到
}
//删除数据
void ContactDel(Con* p)
{
  //前提是数据必须存在才能删除---查找数据是否存在
  char name[NAME_MAX];
  printf("请输入要删除的联系人姓名:\n");
  scanf("%s", name);
  int find = FindByName(p, name);
  if (find < 0)
  {
    printf("要删除的联系人不存在!\n");
    return;
  }
  SLErase(p, find);
  printf("删除成功!\n");
}
//展示通讯录
void ContactShow(Con* p)
{
  //表头:姓名  性别  年龄  电话  地址    
  printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
  for (int i = 0; i < p->size; i++)
  {
    printf("%s\t%s\t%d\t%s\t%s\t\n",
      p->arr[i].name,
      p->arr[i].gender,
      p->arr[i].age,
      p->arr[i].tel,
      p->arr[i].address
    );
  }
}
//通讯录的修改
void ContactMod(Con* p)
{
  //前提是数据必须存在才能修改---查找数据是否存在
  char name[NAME_MAX];
  printf("请输入要修改的联系人姓名:\n");
  scanf("%s", name);
  int find = FindByName(p, name);
  if (find < 0)
  {
    printf("要修改的联系人不存在!\n");
    return;
  }
  //直接修改
  printf("请输入修改后的姓名:\n");
  scanf("%s", p->arr[find].name);
  printf("请输入修改后的性别:\n");
  scanf("%s", p->arr[find].gender);
  printf("请输入修改后的年龄:\n");
  scanf("%d", &p->arr[find].age);
  printf("请输入修改后的电话:\n");
  scanf("%s", p->arr[find].tel);
  printf("请输入修改后的地址:\n");
  scanf("%s", p->arr[find].address);
  printf("修改成功!\n");
}
//通讯录的查找
void ContactFind(Con* p)
{
  char name[NAME_MAX];
  printf("请输入要查找的联系人姓名:\n");
  scanf("%s", name);
  int find = FindByName(p, name);
  if (find < 0)
  {
    printf("要查找的联系人不存在!\n");
    return;
  }
  printf("%s\t%s\t%s\t%s\t\t%s\t\n", "姓名", "性别", "年龄", "电话", "地址");
  printf("%s\t%s\t%d\t%s\t%s\t\n",
    p->arr[find].name,
    p->arr[find].gender,
    p->arr[find].age,
    p->arr[find].tel,
    p->arr[find].address
  );
}
//从文件读取历史数据
void LoadContact(Con* p) {
  FILE* pf = fopen("contact.txt", "rb");
  if (pf == NULL) {
    perror("fopen error!\n");
    return;
  }
  //循环读取文件数据
  Per info;
  printf("正在导入历史数据...\n");
  Sleep(1000);
  while (fread(&info, sizeof(Per), 1, pf))
  {
    SLPushBack(p, info);
  }
  printf("历史数据导入通讯录成功!\n");
  system("pause");
  system("cls");
}
//将数据保存到文件中
void SaveContact(Con* p) {
  FILE* pf = fopen("contact.txt", "wb");
  if (pf == NULL) {
    perror("fopen error!\n");
    return;
  }
  //将通讯录数据写入文件
  for (int i = 0; i < p->size; i++)
  {
    fwrite(p->arr + i, sizeof(Per), 1, pf);
  }
  printf("通讯录数据保存成功!\n");
}

3.main.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
void menu()
{
  printf("***************通讯录***************\n");
  printf("****1.添加联系人    2.删除联系人****\n");
  printf("****3.修改联系人    4.查找联系人****\n");
  printf("****5.展示联系人    0.退出并保存****\n");
  printf("************************************\n");
 
}
int main()
{
  Con con;//创建
  ContactInit(&con);//初始化
  LoadContact(&con);//导入历史数据
  int option = -1;
  int(*pfunc[6])(Con * p) = { 0,ContactAdd,ContactDel,ContactMod,ContactFind,ContactShow }; //转移表
  do
  {
    menu();
    printf("请选择你的操作:\n");
    scanf("%d", &option);
    //转移表开始
    if (option >= 1 && option <= 6)//根据对应的option执行不同操作
    {
      (*pfunc[option])(&con);
    }
    else if (option == 0)
    {
      printf("退出通讯录!\n");
    }
    else
    {
      printf("输入有误,请重新选择!\n");
    }
    system("pause");
    system("cls");//转移表末尾
    //我用的是转移表写,也可以正常使用switch-case语句,使用switch语句就把转移表那段注释掉
    /*switch (option)
    {
    case 1:
      ContactAdd(&con);
      system("pause");
      system("cls");
      break;
    case 2:
      ContactDel(&con);
      system("pause");
      system("cls");
      break;
    case 3:
      ContactMod(&con);
      system("pause");
      system("cls");
      break;
    case 4:
      ContactFind(&con);
      system("pause");
      system("cls");
      break;
    case 5:
      ContactShow(&con);
      system("pause");
      system("cls");
      break;
    case 0:
      printf("退出通讯录!\n");
      break;
    default:
      printf("输入有误,请重新选择!\n");
      system("pause");
      system("cls");
      break;
    }*/
 
  } while (option != 0);
  SaveContact(&con);//保存数据到文件
  ContactDestory(&con);//销毁
  return 0;
}

五、测试运行

菜单界面

添加联系人

展示联系人

六、总结

本文通过一个简单的通讯录管理系统,介绍了C语言在文件操作、结构体、函数等方面的应用。通过学习本文,读者可以掌握C语言编程的基本技巧,为以后的项目开发奠定基础。当然,这个通讯录管理系统还有许多可以优化的地方,比如增加联系人信息的排序、分页显示等功能,感兴趣的读者可以继续完善。


相关文章
|
14天前
|
程序员 C语言 开发者
pymalloc 和系统的 malloc 有什么区别
pymalloc 和系统的 malloc 有什么区别
|
10天前
|
程序员 C语言 开发者
pymalloc 和系统的 malloc 有什么区别?
pymalloc 和系统的 malloc 有什么区别?
|
1月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
19 2
|
1月前
|
存储 编译器 C语言
【C语言】学生管理系统:完整模拟与实现(一)
【C语言】学生管理系统:完整模拟与实现
|
1月前
|
测试技术 C语言
【C语言】学生管理系统:完整模拟与实现(三)
【C语言】学生管理系统:完整模拟与实现
|
1月前
|
C语言
【C语言】学生管理系统:完整模拟与实现(二)
【C语言】学生管理系统:完整模拟与实现
|
3月前
|
存储 C语言
【C语言】C语言-宾馆客房管理系统(源码+论文)【独一无二】
【C语言】C语言-宾馆客房管理系统(源码+论文)【独一无二】
【C语言】C语言-宾馆客房管理系统(源码+论文)【独一无二】
|
3月前
|
存储 C语言
学生管理系统(C语言简单实现)
这篇文章是关于使用C语言实现一个简单的学生管理系统,包括文件的基本应用、数据结构设计、函数实现以及用户界面交互。
学生管理系统(C语言简单实现)
|
3月前
|
存储 数据可视化 数据安全/隐私保护
【C语言】C语言-成绩管理系统(管理员+教师+学生 源码)【独一无二】
【C语言】C语言-成绩管理系统(管理员+教师+学生 源码)【独一无二】
108 2
|
3月前
|
存储 数据可视化 C语言
【C语言】C语言-身份证管理系统(源码+注释)【独一无二】
【C语言】C语言-身份证管理系统(源码+注释)【独一无二】