升级版通讯录(C语言版)

简介: 升级版通讯录(C语言版)

一、使用动态开辟内存

在低版本中,我们使用固定长度的数组存放通讯录信息,但是数据信息过多就会出现越界错误,如果数据信息过少,又会造成极大的内存浪费,故我们可以采用动态内存开辟来很好地解决。

我们首先需要改变初始化函数,先利用malloc开辟一定的空间。

void initContact(struct Contact* connect)
{
  assert(connect);
  connect->size = 0;
  connect->capacity = FAULT_SZ;
   connect->data= (struct PeoInfo*)malloc(FAULT_SZ * sizeof(struct PeoInfo));
  memset(connect->data, 0, sizeof(struct PeoInfo) * connect->capacity);
}

接下来在添加元素时,可能会出现空间不足的情况,所以我们首先应该判断size是否等于capacity,如果容量不足,我们就需要利用realloc函数进行扩容。

int check_is_full( struct Contact* connect)
{
  if (connect->size == connect->capacity)
  {
    struct PeoInfo* p = (struct PeoInfo*)realloc(connect->data, (connect->capacity+EXPAND_SZ) * sizeof(struct PeoInfo));
    if (p != NULL)
    {
      connect->data = p;
      connect->capacity += EXPAND_SZ;
      printf("扩容成功!\n");
      p = NULL;
      return 1;
    }
    else
    {
      printf("扩容失败,无法再继续添加!");
      return 0;
    }
    
  }
  else
  {
    return 1;
  }
}


那么,我们添加元素的函数就会变成如下所示:

void addContact(struct Contact* connect)
{
  assert(connect);
  int flag = check_is_full(connect);
  if (flag)
  {
      printf("姓名:");
      scanf("%s", connect->data[connect->size].name);
      printf("性别:");
      scanf("%s", connect->data[connect->size].sex);
      printf("年龄:");
      scanf("%d", &(connect->data[connect->size].age));
      printf("电话号码:");
      scanf("%s", connect->data[connect->size].tele);
      printf("地址:");
      scanf("%s", connect->data[connect->size].adder);
      connect->size++;
      printf("添加成功!\n");
  }
  else
  {
    return;
  }
  
}

但是在退出程序时,我们需要对开辟的内存进行释放,那么我们就需要再增加一个函数来释放空间。

void destoryContact(struct Contact* connect)
{
  free(connect->data);
  connect->data = NULL;
  connect->capacity = 0;
  connect->size = 0;
}

二、对通讯录信息进行文件存储

我们通常使用的通讯录是能够保存信息的,这时就需要在函数退出时,并将信息保存到一个文件上。

void saveContact(struct Contact* connect)
{
  FILE* fpw =fopen("contact.txt", "wb");
  if (fpw == NULL)
  {
    perror("fopen");
    return;
  }
  for (int i = 0; i < connect->size; i++)
  {
    fwrite(connect->data + i, sizeof(struct PeoInfo), 1, fpw);
  }
//fwrite(connect->data, sizeof(struct PeoInfo), connect->size, fpw);
//这样写也没问题
  fclose(fpw);
  fpw = NULL;
}

那么在进行初始化的时候,我们就应该将存储到文件的通讯录信息初始到Contact对象中去,以便能更好地进行排序、删除、查找等操作。 并且在这个函数中我们还需要调用是否需要扩容的那个函数。

void loadContact(struct Contact* connect)
{
  FILE* fpr = fopen("contact.txt", "rb");
  if (fpr == NULL)
  {
    perror("fopen");
    return;
  }
  struct PeoInfo temp = { 0 };
  while (fread(&temp, sizeof(struct PeoInfo), 1, fpr))
  {
    check_is_full(connect);
    connect->data[connect->size] = temp;
    connect->size++;
  }
  fclose(fpr);
  fpr = NULL;
}

那么,初始化函数就会变为:

void initContact(struct Contact* connect)
{
  assert(connect);
  connect->size = 0;
  connect->capacity = FAULT_SZ;
   connect->data= (struct PeoInfo*)malloc(FAULT_SZ * sizeof(struct PeoInfo));
  memset(connect->data, 0, sizeof(struct PeoInfo) * connect->capacity);
  loadContact(connect);
}

这样我们的信息就会保存在文件中去了。

在升级版通讯录中,我们其余函数是保持不变的,我们的主函数做了略微修改:

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
enum Option
{
  quit,
  add,
  delete,
  search,
  modify,
  sort,
  list,
  empty
};
void menu()
{
  printf("--------------------------------------------------------------------\n");
  printf("-----------1.add                  2.delete--------------------------\n");
  printf("-----------3.search               4.modify--------------------------\n");
  printf("-----------5.sort                 6.list----------------------------\n");
  printf("-----------7.empty                0.exit----------------------------\n");
  printf("--------------------------------------------------------------------\n");
}
int main()
{
  enum Option option;
  struct Contact connect;
  initContact(&connect);
  do
  {
    menu();
    printf("请输入您要进行的操作:");
    scanf("%d", &option);
    switch (option)
    {
    case add:
      addContact(&connect);
      break;
    case delete:
      deleteContact(&connect);
      break;
    case search:
      searchContact(&connect);
      break;
    case modify:
      modifyContact(&connect);
      break;
    case sort:
      sortContact(&connect);
      break;
    case list:
      listContact(&connect);
      break;
    case empty:
      emptyContact(&connect);
      break;
    case quit:
      saveContact(&connect);
      destoryContact(&connect);
      printf("保存成功!\n");
      printf("退出成功!\n");
      break;
    default:
      printf("您的输入有误!");
      break;
    }
 
  } while (option);
 
  return 0;
}


目录
相关文章
|
1月前
|
C语言
C语言——通讯录系统—基于 VS2022
C语言——通讯录系统—基于 VS2022
|
10天前
|
机器学习/深度学习 搜索推荐 程序员
C语言实现个人通讯录(功能优化)-2
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-2
|
10天前
|
存储 C语言 索引
C语言实现个人通讯录(功能优化)-1
C语言实现个人通讯录(功能优化)
C语言实现个人通讯录(功能优化)-1
|
17天前
|
C语言
C语言学习记录——通讯录(静态内存)
C语言学习记录——通讯录(静态内存)
14 2
|
27天前
|
存储 C语言
C语言实现通讯录
C语言实现通讯录
21 2
|
27天前
|
存储 C语言
C语言实验-动态顺序表实现简易通讯录(二)
在这个C语言实验中,你将实现一个简单的通讯录,它使用动态顺序表来存储联系人信息。
28 2
|
27天前
|
存储 C语言
C语言实验-动态顺序表实现简易通讯录(一)
本文介绍了使用C语言模拟实现通讯录的步骤,包括使用动态顺序表存储联系人信息,每个联系人包含姓名、性别、电话和住址。功能包括新增、查找、删除、修改和查看联系人信息,以及按关键词排序。代码示例展示了如何定义联系人结构体、通讯录顺序表,以及主函数中的菜单选择和输入处理。文章还强调了在读取用户输入时避免出现死循环的问题,并提供了初始化和销毁通讯录的函数,以及如何判断和增加通讯录容量的方法。
36 1
|
17天前
|
存储 C语言
C语言学习记录——通讯录(动态内存)
C语言学习记录——通讯录(动态内存)
13 0
|
27天前
|
存储 C语言
动态+静态+文件操作 C语言实现通讯录
通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址
24 0
|
2天前
|
C语言 C++
C语言----C语言内存函数
C语言----C语言内存函数