C实现通讯录(静态版+动态版)(二)

简介: C实现通讯录(静态版+动态版)

二、动态版


分析


我们想想,如果要实现动态版,那么在定义结构体的时候,我们就不能定义一个数组了,而应该定义一个指针,这个指针未来是要指向动态开辟的内存的。光定义一个指针够吗?跟静态版一样还需要一个 sz 来计数,还需要什么变量吗?

我们知道起初初始化的时候会开辟一个小一点的动态内存,当这个内存满了之后,就要在此基础上再扩大内存,那么如何判断内存是否满了呢?

我们可以再定义一个变量 max ,该变量记录了当前状态下动态内存最大元素个数,当 sz 与 max 相等的时候,我们便知道内存已满,要扩大动态内存了。

于是,我们可以这样写:


struct contacts
{
  struct Information* data;
  int sz;
  int max;
};


接下来就是初始化了,在初始化函数里用 malloc 开辟一个动态内存:


void chu_shi(struct contacts* pc)
{
  assert(pc);                    //这里的3也可以用#define来定义一下,方便修改
  pc->data = (struct Information*)malloc(3 * sizeof(struct Information));
  pc->max = 3;
  pc->sz = 0;
}


接下来就是添加联系人了,我们知道添加联系人的时候可能会发生内存已满,无法添加的情况,那么在添加前,我们应该进行判断一下,如果内存已满,那么我们就增容,然后继续添加。

我们将增容这个操作封装成一个函数,如下:


int zeng_rong(struct contacts* pc)   
{    //返回一个int方便判断是否增容成功 
  if (pc->max == pc->sz)
  {
  struct Information* ptr = (struct Information*)realloc(pc->data, (pc->max + 2) * sizeof(struct Information));
  if (ptr != NULL)
  {
    pc->data = ptr;      //ptr不为空则赋值
    pc->max += 2;        //更新一下max的大小
    printf("增容成功\n");   //提示一下
    return 1;
  }
  else
  {
    perror("zeng_rong()");    //增容失败则报错
    return 0;
  }
  }
  return 1;
}


再来看看添加联系人函数:


void Add(struct contacts* pc)
{
  assert(pc);
  if (0 == zeng_rong(pc))    //增容失败返回0
  {
  return;
  }
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[pc->sz].name);
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[pc->sz].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[pc->sz].age));
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[pc->sz].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[pc->sz].addr);
  printf("添加成功\n");
  pc->sz++;
}


这样添加函数就完成了,那么接下来的函数需要修改吗,其实后面的函数都不需要修改,因为都没涉及到内存的增长,虽然删减函数会导致内存空出来一点,但是没有修改的必要。


问:那我们这样就修改完了吗?


虽然我们确实实现了通讯录的动态增长,但是我们忘了一个重要点,那就是内存的释放,这点不能忘!


void shi_fang(struct contacts* pc)
{
  free(pc->data);       //释放
  pc->data = NULL;      //置空
  pc->max = 0;
  pc->sz = 0;
}


总代码


1.test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contacts.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 contacts con;
  chu_shi(&con);
  do
  {
  menu();
  printf("请输入:>");
  scanf("%d", &input);
  switch (input)
  {
  case ADD:
    Add(&con);
    break;
  case DEL:
    Del(&con);
    break;
  case SEARCH:
    Search(&con);
    break;
  case MODIFY:
    Modify(&con);
    break;
  case SHOW:
    Show(&con);
    break;
  case SORT:
    Sort(&con);
    break;
  case EXIT:
    shi_fang(&con);   //退出的时候释放
    break;
  default:
    printf("输入错误\n");
    break;
  }
  } while (input);
  return 0;
}


2.contacts.h

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
struct Information
{
  char name[MAX_NAME];
  char sex[MAX_SEX];
  int age;
  char tele[MAX_TELE];
  char addr[MAX_ADDR];
};
//静态版
//struct contacts
//{
//  struct Information data[MAX];
//  int sz;
//};
//动态版
struct contacts
{
  struct Information* data;
  int sz;
  int max;
};
//初始化通讯录
void chu_shi(struct contacts* pc);
//增加联系人
void Add(struct contacts* pc);
//删除联系人
void Del(struct contacts* pc);
//查找联系人
void Search(const struct contacts* pc);
//修改联系人
void Modify(struct contacts* pc);
//显示联系人
void Show(const struct contacts* pc);
//名字排序
void Sort(struct contacts* pc);
//释放空间
void shi_fang(struct contacts* pc);


3.contacts.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contacts.h"
//静态版
//void chu_shi(struct contacts* pc)
//{
//  assert(pc);
//  memset(pc->data, 0, MAX * sizeof(struct Information));
//  pc->sz = 0;
//}
void chu_shi(struct contacts* pc)
{
  assert(pc);
  pc->data = (struct Information*)malloc(3 * sizeof(struct Information));
  pc->max = 3;
  pc->sz = 0;
}
//静态版
//void Add(struct contacts* pc)
//{
//  printf("请输入联系人姓名:>");
//  scanf("%s", pc->data[pc->sz].name);
//  printf("请输入联系人性别:>");
//  scanf("%s", pc->data[pc->sz].sex);
//  printf("请输入联系人年龄:>");
//  scanf("%d", &(pc->data[pc->sz].age));
//  printf("请输入联系人电话:>");
//  scanf("%s", pc->data[pc->sz].tele);
//  printf("请输入联系人住址:>");
//  scanf("%s", pc->data[pc->sz].addr);
//  printf("添加成功\n");
//  pc->sz++;
//}
int zeng_rong(struct contacts* pc)
{
  if (pc->max == pc->sz)
  {
  struct Information* ptr = (struct Information*)realloc(pc->data, (pc->max + 2) * sizeof(struct Information));
  if (ptr != NULL)
  {
    pc->data = ptr;
    pc->max += 2;
    printf("增容成功\n");
    return 1;
  }
  else
  {
    perror("zeng_rong()");
    return 0;
  }
  }
  return 1;
}
void Add(struct contacts* pc)
{
  assert(pc);
  if (0 == zeng_rong(pc))
  {
  return;
  }
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[pc->sz].name);
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[pc->sz].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[pc->sz].age));
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[pc->sz].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[pc->sz].addr);
  printf("添加成功\n");
  pc->sz++;
}
int cha_zhao(const struct contacts* pc, char* name)
{
  int i = 0;
  for (i; i < pc->sz; i++)
  {
  if (strcmp(pc->data[i].name, name) == 0)
    return i;
  }
  return -1;
}
void Del(struct contacts* pc)
{
  char name[20];
  printf("请输入要删除的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  pc->data[m] = pc->data[pc->sz-1];
  pc->sz--;
  printf("删除成功\n");
  }
  else
  printf("没有该联系人\n");
}
void Search(const struct contacts* pc)
{
  char name[20];
  printf("请输入要查看的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  printf("%-20s\t%-6s\t%-4s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "住址");
  printf("%-20s\t%-6s\t%-4d\t%-12s\t%-30s\n", pc->data[m].name, 
    pc->data[m].sex, pc->data[m].age, 
    pc->data[m].tele, pc->data[m].addr);
  }
  else
  printf("没有该联系人\n");
}
void Modify(struct contacts* pc)
{
  char name[20];
  printf("请输入要修改的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[m].name);
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[m].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[m].age));
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[m].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[m].addr);
  printf("添加成功\n");
  }
  else
  printf("没有该联系人\n");
}
void Show(const struct contacts* pc)
{
  int i = 0;
  printf("%-20s\t%-6s\t%-4s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "住址");
  for (i; i < pc->sz; i++)
  {
  printf("%-20s\t%-6s\t%-4d\t%-12s\t%-30s\n", pc->data[i].name,
    pc->data[i].sex, pc->data[i].age,
    pc->data[i].tele, pc->data[i].addr);
  }
}
int bi_jiao(const void* e1, const void* e2)
{
  return strcmp(((struct Information*)e1)->name, ((struct Information*)e2)->name);
}
void Sort(struct contacts* pc)
{
  qsort(pc->data, pc->sz, sizeof(struct Information), bi_jiao);
}
void shi_fang(struct contacts* pc)
{
  free(pc->data);
  pc->data = NULL;
  pc->max = 0;
  pc->sz = 0;
}


总结


与静态版相比,动态版可以根据需求来开辟空间大小,更节省空间,提高代码运行速率。


相关文章
|
6月前
【C进阶】通讯录的实现(静态+动态)(上)
【C进阶】通讯录的实现(静态+动态)(上)
|
4月前
|
存储 编译器 C语言
通讯录详解(静态版,动态版,文件版)
通讯录详解(静态版,动态版,文件版)
21 0
|
6月前
【C进阶】通讯录的实现(静态+动态)(中)
【C进阶】通讯录的实现(静态+动态)(中)
|
6月前
【C进阶】通讯录的实现(静态+动态)(下)
【C进阶】通讯录的实现(静态+动态)(下)
|
6月前
|
存储
【静态通讯录】
【静态通讯录】
12 0
|
8月前
|
存储
C实现通讯录(静态版+动态版)(一)
C实现通讯录(静态版+动态版)
19 0
C实现通讯录(静态版+动态版)(一)
|
8月前
|
存储
通讯录(静态版)
通讯录(静态版)
|
9月前
|
C语言
C/【静态通讯录】
C/【静态通讯录】
|
10月前
|
C语言
静态通讯录
C语言学习——教你学会静态通讯录的实现(保姆级教程哦~)
|
10月前
|
存储
通讯录(静态版)(一)
大家好,有好久没有带大家一起搞实战的编程了,今天就给大家带来一个简单的通讯录小系统
55 0