c语言小项目(动态通讯录的实现)

简介: 前面我们已经实现了静态通讯录,下面来实现一下动态通讯录,其框架与静态有多不同,但是很多功能在使用的时候是一样的,这里添加联系人的方式是不同的,所以我们这里只说一下框架和不要改动的地方,这里如果有什么不懂的可以先看看静态通讯录的实现(点击链接即可看静态通讯录的实现),下面进入正题。1. 框架每件事请都有逻辑性,实现一个东西也少不了其逻辑。

前面我们已经实现了静态通讯录,下面来实现一下动态通讯录,其框架与静态有多不同,但是很多功能在使用的时候是一样的,这里添加联系人的方式是不同的,所以我们这里只说一下框架和不要改动的地方,这里如果有什么不懂的可以先看看静态通讯录的实现(点击链接即可看静态通讯录的实现),下面进入正题。

1. 框架

每件事请都有逻辑性,实现一个东西也少不了其逻辑。

先来了解一下结构:

6afcf729c26b0db11bb9188e0d5a089f.png

这里我们我们使用新了结构,所以只用初始化中改变和对增加联系人这个功能和退出程序时释放通讯录空间这三个地方都有所变动,其他功能和静态一样。

2. 具体实现

这里我只说说初始化通讯录和添加联系人以及退出程序销毁通讯录三个操作的实现

2.1 初始化通讯录

首先我们要对个人信息这个结构体进行申请空间操作(使用malloc库函数实现)并把记录个人信息的数量置为0(没有联系人所以要置为0)还要设置一下整体通讯录的容量大小

2.2 添加联系人信息

首先就是要对个人信息数量和通讯录容量进行一个比较,如果相等就对存储个人信息空间进行扩容,这里使用realloc库函数对其扩容,并且还要把通讯录容量变大。

2.3 退出程序时销毁通讯录

把通讯录的空间释放掉(用free库函数进行释放),在把指向该通讯录的地址置为空指针(防止野指针的存在),再把记录个人信息数量置为0以及把通讯录容量置为0。

3. 多文件形式展示源代码

3.1 main.c文件

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Dynamic_AdressList.h"
//动态通讯录实现
//主逻辑
int main()
{
  //创建通讯录
  struct Adress_List List;
  //初始化通讯录
  Init_Adress_List(&List);//传地址节省了空间同时也对其原变量进行修改
  int input = 0;
  //选择并操作
  //增加联系人信息,删除联系人信息,查找联系人信息,修改联系人信息,对通讯录进行按年龄排序,展示通讯录
  do
  {
    menu();
    printf("请输出操作前的提示数字,可完成此操作:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      //添加联系人信息
      Add_Linkman(&List);
      system("cls");
      break;
    case 2:
      //删除联系人信息
      Delete_Linkman(&List);
      system("cls");
      break;
    case 3:
      //查找联系人
      Find_Linkman(&List);
      system("cls");
      break;
    case 4:
      //修改联系人信息
      Modify_Linkman_Information(&List);
      system("cls");
      break;
    case 5:
      //按照年龄进行排序
      SortList_By_age(&List);
      system("cls");
      break;
    case 6:
      //展示通讯录
      Show_Adress_List(&List);
      system("cls");
      break;
    case 7:
      //删除所有联系人信息
      Delete_AllLinkman(&List);
      system("cls");
      break;
    case 0:
      //销毁通讯录
      Destory_Adress_List(&List);
      printf("------------------退出程序!------------------\n");
      break;
    default:
      printf("-------------输入错误!请重新输入:>-------------\n");
      Sleep(1000);
      system("cls");
      break;
    }
  } while (input);
  system("pause");
  return 0;
}

Dynamic_AdressList.c文件

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Dynamic_AdressList.h"
//封装通讯录函数
//初始化通讯录
void Init_Adress_List(struct Adress_List* List)
{
  assert(List);
  List->data = (struct Person_Information*)malloc(sizeof(struct Person_Information) * MAX_CAPACITY);
  if (List->data == NULL)
  {
    perror("Init_Adress_List()");
    return;
  }
  List->size = 0;
  List->capacity = MAX_CAPACITY;
}
//打印菜单
void menu()
{
  printf("\n");
  printf("************************************************\n");
  printf("*****    1.AddLinkman    2.DeleteLinkman  ******\n");
  printf("*****    3.FindLinkman   4.ModifyLinkman  ******\n");
  printf("*****    5.SortByAge     6.ShowList       ******\n");
  printf("*****    7.DeleteAll     0.exit           ******\n");
  printf("************************************************\n");
  printf("\n");
}
//添加联系人信息
void Add_Linkman(struct Adress_List* List)
{
  assert(List);
  //判断是否满容
  int ret = Judge_Capactiy(List);
  //申请空间失败
  if (ret == 0)
  {
    return;
  }
  //扩容成功可再次添加联系人信息
  else
  {
    //直接添加
    //名字、性别、电话、年龄、家庭住址
    printf("请输入名字:>");
    scanf("%s", List->data[List->size].name);
    printf("请输入性别:>");
    scanf("%s", List->data[List->size].sex);
    printf("请输入电话:>");
    scanf("%s", List->data[List->size].phone);
    printf("请输入年龄:>");
    scanf("%d", &List->data[List->size].age);
    printf("请输入家庭住址:>");
    scanf("%s", List->data[List->size].adress);
    List->size++;
    printf("添加联系人成功!\n");
    Sleep(800);
  }
}
//展示通讯录
void Show_Adress_List(const struct Adress_List* List)
{
  printf("\n");
  printf("-------------------------------------------------------------------------------\n");
  printf("暂时的通讯录的所有信息:>\n");
  printf("%-5s\t%-5s\t%-15s\t%-20s\t%-20s\n", "姓名", "性别", "电话", "年龄", "家庭住址");
  int i = 0;
  for (i = 0; i < List->size; i++)
  {
    printf("%-5s\t%-5s\t%-15s\t%-20d\t%-20s\n",
      List->data[i].name,
      List->data[i].sex,
      List->data[i].phone,
      List->data[i].age,
      List->data[i].adress);
  }
  printf("-------------------------------------------------------------------------------\n");
  printf("\n");
  printf("请等上5秒,再次操作!\n");
  Sleep(5000);
}
//删除联系人
void Delete_Linkman(struct Adress_List* List)
{
  char name[MAX_NAME];
  printf("请输入你想删除的联系人的姓名:>");
  scanf("%s", name);
  //删除操作,若找到删除的联系人返回下标进行删除,没有找到进行标注
  int ret = Find_By_Name(List, name);
  if (-1 == ret)
  {
    printf("该联系人不存在!\n");
    Sleep(800);
  }
  else
  {
    //进行删除操作(这里是使用覆盖的的方式)
    int i = 0;
    for (i = ret; i < List->size; i++)
    {
      List->data[i] = List->data[i + 1];
    }
    //通讯录大小改变
    List->size--;
    printf("成功删除该联系人!\n");
    Sleep(800);
  }
}
//查找联系人
void Find_Linkman(struct Adress_List* List)
{
  printf("请输入你想查找的联系人的姓名:>");
  char name[MAX_NAME];
  scanf("%s", name);
  int ret = Find_By_Name(List, name);
  if (ret == -1)
  {
    printf("此联系人不存在!\n");
    Sleep(800);
  }
  else
  {
    printf("\n");
    printf("你的通讯录里面有此联系人,它的信息是:>\n");
    Show_Person_Information(List, ret);
    Sleep(800);
  }
}
//修改联系人信息
void Modify_Linkman_Information(struct Adress_List* List)
{
  //找到联系人,如果有此联系人就对其进行修改
  printf("请输入你想修改信息的联系人的姓名:>");
  char name[MAX_NAME];
  scanf("%s", name);
  int ret = Find_By_Name(List, name);
  if (-1 == ret)
  {
    printf("此联系人不存在!\n");
    Sleep(800);
  }
  else
  {
    //拿到下标
    printf("请输入名字:>");
    scanf("%s", List->data[ret].name);
    printf("请输入性别:>");
    scanf("%s", List->data[ret].sex);
    printf("请输入电话:>");
    scanf("%s", List->data[ret].phone);
    printf("请输入年龄:>");
    scanf("%d", &List->data[ret].age);
    printf("请输入家庭住址:>");
    scanf("%s", List->data[ret].adress);
    printf("修改成功!\n");
    printf("\n");
    Sleep(800);
  }
}
//按照年龄进行排序
void SortList_By_age(const struct Adress_List* List)
{
  assert(List);
  //通讯录里面没有信息或者只有一个信息排序也是没必要的
  if (List->size <= 1)
  {
    printf("\n");
    printf("通讯录里面联系人个数小于两个没有必要对其进行排序!\n");
    Sleep(800);
    return;
  }
  //排序用到qsort库函数
  qsort(List->data, List->size, sizeof(struct Person_Information), compare);
  printf("排序完成!\n");
  Sleep(800);
}
//删除通讯录所有联系人信息
void Delete_AllLinkman(struct Adress_List* List)
{
  //拿到的一个通讯录里面没有信息就标注
  if (List->size == 0)
  {
    printf("通讯录为空,无法操作!\n");
    Sleep(800);
  }
  else
  {
    //动态的内存用free释放空间(这里没有用到动态存储)
    //删除的方法:用一个临时的空间去保存
    struct Person_Information Delete[MAX];
    int i = 0;
    //删除一次通讯录空间变小一次
    //Lisr->size会改变,所有把初值保存下来
    int k = List->size;
    for (i = 0; i < k; i++)
    {
      Delete[i] = List->data[i];
      List->size--;
    }
    printf("删除成功!\n");
    Sleep(800);
  }
}
//销毁通讯录
void Destory_Adress_List(struct Adress_List* List)
{
  assert(List);
  free(List->data);
  List->data = NULL;
  List->size = 0;
  List->capacity = 0;
}

HiddenFunction.c文件

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Dynamic_AdressList.h"
//通过名字找到联系人存储的位置
int Find_By_Name(const struct Adress_List* List, char name[])
{
  int i = 0;
  for (i = 0; i < List->size; i++)
  {
    if (0 == strcmp(List->data[i].name, name))
    {
      return i;
    }
  }
  return -1;
}
//qsort库函数中比较函数
int compare(const void* e1, const void* e2)
{
  return ((struct Person_Information*)e1)->age - ((struct Person_Information*)e2)->age;
}
//展示个人信息
void Show_Person_Information(struct Adress_List* List, int ret)
{
  printf("-------------------------------------------------------------------------------\n");
  printf("%-5s\t%-5s\t%-15s\t%-20s\t%-20s\n", "姓名", "性别", "电话", "年龄", "家庭住址");
  printf("%-5s\t%-5s\t%-15s\t%-20d\t%-20s\n",
    List->data[ret].name,
    List->data[ret].sex,
    List->data[ret].phone,
    List->data[ret].age,
    List->data[ret].adress);
  printf("-------------------------------------------------------------------------------\n");
  printf("\n");
}
int Judge_Capactiy(struct Adress_List* List)
{
  if (List->size == List->capacity)
  {
    //对个人信息空间扩容
    struct Person_Information* information_capacity = (struct Person_Information*)realloc(List->data, (List->capacity + 2) * sizeof(struct Person_Information));
    if (information_capacity == NULL)
    {
      perror("Add_Linkman:Judge_Capactiy()");
      Sleep(1000);
      return 0;
    }
    else
    {
      //把扩容返回的地址再次指向起始位置
      List->data = information_capacity;
      //把通讯录整体容量增加
      List->capacity = List->capacity + ADD_CAPACITY_LIMIT;
      return 1;
    }
  }
  else
  {
    return 1;
  }
}

Dynamic_AdressList.h文件

#pragma once
//包含头文件、函数声明、变量定义
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <Windows.h>
#define MAX 100
#define MAX_NAME 10
#define MAX_SEX 5
#define MAX_PONE 15
#define MAX_ADRESS 20
#define MAX_CAPACITY 3
#define ADD_CAPACITY_LIMIT 2
//个人信息
struct Person_Information
{
  //名字、性别、电话、年龄、家庭住址
  //名字一般都是最长的就是5个字
  char name[MAX_NAME];
  //男,女,保密
  char sex[MAX_SEX];
  //电话号码有11位
  char phone[MAX_PONE];
  int age;
  char adress[MAX_ADRESS];
};
//通讯录
struct Adress_List
{
  //包含个人信息
  struct Person_Information* data;
  //记录通讯录大小
  int size;
  //记录容量
  int capacity;
};
//初始化通讯录
void Init_Adress_List(struct Adress_List* List);
//打印菜单
void menu();
//添加联系人信息
void Add_Linkman(struct Adress_List* List);
//判断是否满容
int Judge_Capactiy(struct Adress_List* List);
//展示通讯录
void Show_Adress_List(const struct Adress_List* List);
//删除联系人信息
void Delete_Linkman(struct Adress_List* List);
//通过名字找到联系人存储的位置
int Find_By_Name(const struct Adress_List* List, char name[]);
//展示个人信息
void Show_Person_Information(struct Adress_List* List, int ret);
//查找联系人
void Find_Linkman(struct Adress_List* List);
//修改联系人信息
void Modify_Linkman_Information(struct Adress_List* List);
//按照年龄对通讯录进行排序
void SortList_By_age(const struct Adress_List* List);
//qsort库函数中比较函数
int compare(const void* e1, const void* e2);
//删除所有联系人信息
void Delete_AllLinkman(struct Adress_List* List);
//销毁通讯录
void Destory_Adress_List(struct Adress_List* List);












相关文章
|
9天前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-2
|
9天前
|
存储 C语言 索引
C语言实现个人通讯录(功能优化)-1
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-1
|
16天前
|
C语言
C语言学习记录——通讯录(静态内存)
C语言学习记录——通讯录(静态内存)
14 2
|
25天前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
26 1
|
25天前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
26 1
|
26天前
|
存储 C语言
C语言实现通讯录
C语言实现通讯录
21 2
|
27天前
|
存储 C语言
C语言实验-动态顺序表实现简易通讯录(二)
在这个C语言实验中,你将实现一个简单的通讯录,它使用动态顺序表来存储联系人信息。
28 2
|
16天前
|
存储 C语言
C语言学习记录——通讯录(动态内存)
C语言学习记录——通讯录(动态内存)
12 0
|
16天前
|
C语言
C语言学习记录——鹏哥扫雷项目实现及递归展开、记录雷坐标
C语言学习记录——鹏哥扫雷项目实现及递归展开、记录雷坐标
19 0
|
25天前
|
C语言 C++
C语言项目(1)----扫雷小游戏的实现
C语言项目(1)----扫雷小游戏的实现
26 0