【C语言课程设计】通讯录(3.0版本)

简介: 【C语言课程设计】通讯录(3.0版本)



一、通讯录的再优化方案

在前面的文章中,我们将通讯录改为了动态增容的版本,这是之前的链接

【C语言课程设计】通讯录(2.0版本)_青色_忘川的博客-CSDN博客

现在,我们继续优化通讯录,使其可以保存通讯录中的联系人

二、具体实现

1.保存联系人功能

这部分我实现也是比较简单的,我们打开一个文件一个,我们可以使用二进制的文件的文件进行读写,也可以使用文本文件的形式进行读写,这里我们采用二进制的文件进行读写

当我们读写的时候,我们有四种函数可以进行选择,fputc,fputs,fprintf,fwrite。但是前三种显然不太适合,因为我们要保存的是一个通讯录,联系人是我们自定义类型出来的,所以使用fwrite是最好的选择,我们选择一个一个的读取。当读取到size的大小的时候,程序也刚好结束

//保存通讯录中的信息到文件中
void SaveContact(Contact* pc)
{
  FILE* pf = fopen("Contact.txt", "wb");
  if (pf == NULL)
  {
    perror("SaveContact");
    return;
  }
  int i = 0;
  for (i = 0; i < pc->size; i++)
  {
    fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
  }
  fclose(pf);
  pf = NULL;
  printf("数据已保存\n");
}

2.读取存档

这里我们要注意,我们既然使用fwrite,那么我们就要使用对应的fread。

使用fread的时候,我们遇到一个很尴尬的问题,我们不知道要读取多少个数据。所以我们只能一个一个的读取,直到将文件全部读取完成。

因为fread函数他是会返回他读取的元素个数的。如果读取了5个数据,就会返回5,如果读取了0个数据,就会返回0

所以我们就需要使用while语句来进行循环读取。要注意的是,我们每次读取都需要检查容量是否足够

//读取存档
void LoadContact(Contact* pc)
{
  FILE* pf = fopen("Contact.txt", "rb");
  if (pf == NULL)
  {
    perror("LoadContact");
    return;
  }
  PeoInfo tmp = { 0 };
  int i = 0;
  while (fread(&tmp, sizeof(PeoInfo), 1, pf))
  {
    check_capacity(pc);
    pc->data[i] = tmp;
    pc->size++;
    i++;
  }
  fclose(pf);
  pf = NULL;
  printf("读取存档成功\n");
}

三、通讯录完整代码(多文件)

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
void menu()
{
  printf("*************************\n");
  printf("****      1.Add      ****\n");
  printf("****      2.Del      ****\n");
  printf("****      3.Search   ****\n");
  printf("****      4.Modify   ****\n");
  printf("****      5.Show     ****\n");
  printf("****      6.Sort     ****\n");
  printf("****      7.Load     ****\n");
  printf("****      8.Save     ****\n");
  printf("****      0.exit     ****\n");
  printf("*************************\n");
}
enum Option
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT,
  Load,
  Save
};
int main()
{
  int input = 0;
  Contact con;
  InitContact(&con);
  do
  {
    menu();
    printf("请输入你的需求>:");
    scanf("%d", &input);
    switch (input)
    {
    case ADD:
      printf("添加联系人\n");
      AddContact(&con);
      break;
    case DEL:
      printf("删除指定联系人\n");
      DelContact(&con);
      break;
    case SEARCH:
      printf("查找指定联系人\n");
      SearchContact(&con);
      break;
    case MODIFY:
      printf("修改指定联系人\n");
      ModifyContact(&con);
      break;
    case SHOW:
      printf("打印所有联系人\n");
      ShowContact(&con);
      break;
    case SORT:
      printf("排序联系人\n");
      SortContact(&con);
      break;
    case Load:
      printf("读取存档\n");
      LoadContact(&con);
      break;
    case Save:
      printf("保存存档\n");
      SaveContact(&con);
      break;
    case EXIT:
      printf("退出通讯录\n");
      printf("是否需要保存存档,输入1保存,输入0不保存\n");
      int tmp = 0;
      scanf("%d", &tmp);
      if (tmp == 1)
      {
        SaveContact(&con);
      }
      DestoryContact(&con);
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  } while (input);
  return 0;
}

Contact.h文件

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 10
#define ADDRESS_MAX 30
#define TELEPHONE_MAX 12
#define DEFAULT_SIZE 3
#define INC_SIZE 2
//定义一个结构体类型,这里存放人的信息
typedef struct PeoInfo
{
  char name[NAME_MAX];
  int age;
  char sex[SEX_MAX];
  char address[ADDRESS_MAX];
  char telephone[TELEPHONE_MAX];
}PeoInfo;
//所有人的都放到这里
typedef struct Contact
{
  PeoInfo* data;//利用指针指向我们的每个人的信息
  int size;//当前通讯录的人数
  int capacity;//当前通讯录的最大容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//添加联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//排序通讯录
void SortContact(Contact* pc);
//打印通讯录
void ShowContact(const Contact* pc);
//通讯录的销毁
void DestoryContact(Contact* pc);
//保存通讯录中的信息到文件中
void SaveContact(Contact* pc);
//读取存档
void LoadContact(Contact* pc);

Contact.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
//初始化通讯录
void InitContact(Contact* pc)
{
  assert(pc);
  PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SIZE, sizeof(PeoInfo));
  if (ptr == NULL)
  {
    perror("InitContact::calloc");
    return;
  }
  pc->data = ptr;
  pc->size = 0;
  pc->capacity = DEFAULT_SIZE;
}
//增容
void check_capacity(Contact* pc)
{
  assert(pc);
  if (pc->size == pc->capacity)
  {
    PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + INC_SIZE));
    if (ptr == NULL)
    {
      perror("check_capacity::realloc");
      return;
    }
    pc->data = ptr;
    pc->capacity += INC_SIZE;
    printf("增容成功\n");
  }
}
//添加联系人
void AddContact(Contact* pc)
{
  assert(pc);
  check_capacity(pc);
  printf("请输入联系人的姓名:");
  scanf("%s", (pc->data)[pc->size].name);
  printf("请输入联系人的年龄:");
  scanf("%d", &((pc->data)[pc->size].age));
  printf("请输入联系人的性别:");
  scanf("%s", (pc->data)[pc->size].sex);
  printf("请输入联系人的地址:");
  scanf("%s", (pc->data)[pc->size].address);
  printf("请输入联系人的电话:");
  scanf("%s", (pc->data)[pc->size].telephone);
  pc->size++;
  printf("恭喜你,添加成功\n");
}
//在通讯录中通过名字查找一个人,并返回他的下标
int FindByName(const Contact* pc, char* arr)
{
  assert(pc && arr);
  int i = 0;
  for (i = 0; i < pc->size; i++)
  {
    if (strcmp(pc->data[i].name, arr) == 0)
    {
      return i;
    }
  }
  return -1;
}
//删除指定联系人
void DelContact(Contact* pc)
{
  assert(pc);
  if (pc->size == 0)
  {
    printf("通讯录为空,无法删除\n");
    return;
  }
  printf("请输入你要删除的联系人姓名>:");
  char arr[NAME_MAX] = { 0 };
  scanf("%s", arr);
  int pos = FindByName(pc, arr);
  if (pos == -1)
  {
    printf("没有这个人\n");
    return;
  }
  int i = pos;
  for (i = pos; i < pc->size - 1; i++)
  {
    pc->data[i] = pc->data[i + 1];
  }
  pc->size--;
  printf("删除成功\n");
}
//查找指定联系人
void SearchContact(const Contact* pc)
{
  assert(pc);
  if (pc->size == 0)
  {
    printf("通讯录为空,无法查找\n");
    return;
  }
  char arr[NAME_MAX] = { 0 };
  printf("请输入你要查找的名字>:");
  scanf("%s", arr);
  int pos = FindByName(pc, arr);
  if (pos == -1)
  {
    printf("通讯录中不存在这个人\n");
    return;
  }
  printf("%-20s %-4s %-5s %-30s %-12s\n", "姓名", "年龄", "性别", "地址", "电话");
  printf("%-20s %-4d %-5s %-30s %-12s\n",
    pc->data[pos].name,
    pc->data[pos].age,
    pc->data[pos].sex,
    pc->data[pos].address,
    pc->data[pos].telephone);
}
//修改指定联系人
void ModifyContact(Contact* pc)
{
  assert(pc);
  if (pc->size == 0)
  {
    printf("通讯录为空,无法修改\n");
    return;
  }
  char arr[NAME_MAX] = { 0 };
  printf("请输入你要修改的人的名字\n");
  scanf("%s", arr);
  int pos = FindByName(pc, arr);
  if (pos == -1)
  {
    printf("该联系人不存在\n");
    return;
  }
  printf("请输入联系人的姓名:");
  scanf("%s", pc->data[pos].name);
  printf("请输入联系人的年龄:");
  scanf("%d", &(pc->data[pos].age));
  printf("请输入联系人的性别:");
  scanf("%s", pc->data[pos].sex);
  printf("请输入联系人的地址:");
  scanf("%s", pc->data[pos].address);
  printf("请输入联系人的电话:");
  scanf("%s", pc->data[pos].telephone);
  printf("修改成功\n");
}
void cmp_by_name(void* e1, void* e2)
{
  return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void cmp_by_age(void* e1, void* e2)
{
  return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//排序通讯录
void SortContact(Contact* pc)
{
  assert(pc);
  int input = 0;
  printf("请选择你需要按姓名排序还是按照年龄排序\n");
  printf("按照姓名排序请输入1,按照年龄排序请输入2 :\n");
  scanf("%d", &input);
  if (input == 1)
    qsort(pc->data, pc->size, sizeof(PeoInfo), cmp_by_name);
  if (input == 2)
    qsort(pc->data, pc->size, sizeof(PeoInfo), cmp_by_age);
  printf("排序成功\n");
}
//打印通讯录
void ShowContact(const Contact* pc)
{
  assert(pc);
  int i = 0;
  printf("%-20s %-4s %-5s %-30s %-12s\n", "姓名", "年龄", "性别", "地址", "电话");
  for (i = 0; i < pc->size; i++)
  {
    printf("%-20s %-4d %-5s %-30s %-12s\n",
      pc->data[i].name,
      pc->data[i].age,
      pc->data[i].sex,
      pc->data[i].address,
      pc->data[i].telephone);
  }
}
//销毁通讯录
void DestoryContact(Contact* pc)
{
  free(pc->data);
  pc->data = NULL;
  pc->capacity = 0;
  pc->size = 0;
  pc = NULL;
}
//保存通讯录中的信息到文件中
void SaveContact(Contact* pc)
{
  FILE* pf = fopen("Contact.txt", "wb");
  if (pf == NULL)
  {
    perror("SaveContact");
    return;
  }
  int i = 0;
  for (i = 0; i < pc->size; i++)
  {
    fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
  }
  fclose(pf);
  pf = NULL;
  printf("数据已保存\n");
}
//读取存档
void LoadContact(Contact* pc)
{
  FILE* pf = fopen("Contact.txt", "rb");
  if (pf == NULL)
  {
    perror("LoadContact");
    return;
  }
  PeoInfo tmp = { 0 };
  int i = 0;
  while (fread(&tmp, sizeof(PeoInfo), 1, pf))
  {
    check_capacity(pc);
    pc->data[i] = tmp;
    pc->size++;
    i++;
  }
  fclose(pf);
  pf = NULL;
  printf("读取存档成功\n");
}

四、通讯录完整代码(单文件)

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 10
#define ADDRESS_MAX 30
#define TELEPHONE_MAX 12
#define DEFAULT_SIZE 3
#define INC_SIZE 2
//定义一个结构体类型,这里存放人的信息
typedef struct PeoInfo
{
  char name[NAME_MAX];
  int age;
  char sex[SEX_MAX];
  char address[ADDRESS_MAX];
  char telephone[TELEPHONE_MAX];
}PeoInfo;
//所有人的都放到这里
typedef struct Contact
{
  PeoInfo* data;//利用指针指向我们的每个人的信息
  int size;//当前通讯录的人数
  int capacity;//当前通讯录的最大容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//添加联系人
void AddContact(Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//排序通讯录
void SortContact(Contact* pc);
//打印通讯录
void ShowContact(const Contact* pc);
//通讯录的销毁
void DestoryContact(Contact* pc);
//保存通讯录中的信息到文件中
void SaveContact(Contact* pc);
//读取存档
void LoadContact(Contact* pc);
void menu()
{
  printf("*************************\n");
  printf("****      1.Add      ****\n");
  printf("****      2.Del      ****\n");
  printf("****      3.Search   ****\n");
  printf("****      4.Modify   ****\n");
  printf("****      5.Show     ****\n");
  printf("****      6.Sort     ****\n");
  printf("****      7.Load     ****\n");
  printf("****      8.Save     ****\n");
  printf("****      0.exit     ****\n");
  printf("*************************\n");
}
enum Option
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT,
  Load,
  Save
};
int main()
{
  int input = 0;
  Contact con;
  InitContact(&con);
  do
  {
    menu();
    printf("请输入你的需求>:");
    scanf("%d", &input);
    switch (input)
    {
    case ADD:
      printf("添加联系人\n");
      AddContact(&con);
      break;
    case DEL:
      printf("删除指定联系人\n");
      DelContact(&con);
      break;
    case SEARCH:
      printf("查找指定联系人\n");
      SearchContact(&con);
      break;
    case MODIFY:
      printf("修改指定联系人\n");
      ModifyContact(&con);
      break;
    case SHOW:
      printf("打印所有联系人\n");
      ShowContact(&con);
      break;
    case SORT:
      printf("排序联系人\n");
      SortContact(&con);
      break;
    case Load:
      printf("读取存档\n");
      LoadContact(&con);
      break;
    case Save:
      printf("保存存档\n");
      SaveContact(&con);
      break;
    case EXIT:
      printf("退出通讯录\n");
      printf("是否需要保存存档,输入1保存,输入0不保存\n");
      int tmp = 0;
      scanf("%d", &tmp);
      if (tmp == 1)
      {
        SaveContact(&con);
      }
      DestoryContact(&con);
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  } while (input);
  return 0;
}
//初始化通讯录
void InitContact(Contact* pc)
{
  assert(pc);
  PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SIZE, sizeof(PeoInfo));
  if (ptr == NULL)
  {
    perror("InitContact::calloc");
    return;
  }
  pc->data = ptr;
  pc->size = 0;
  pc->capacity = DEFAULT_SIZE;
}
//增容
void check_capacity(Contact* pc)
{
  assert(pc);
  if (pc->size == pc->capacity)
  {
    PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + INC_SIZE));
    if (ptr == NULL)
    {
      perror("check_capacity::realloc");
      return;
    }
    pc->data = ptr;
    pc->capacity += INC_SIZE;
    printf("增容成功\n");
  }
}
//添加联系人
void AddContact(Contact* pc)
{
  assert(pc);
  check_capacity(pc);
  printf("请输入联系人的姓名:");
  scanf("%s", (pc->data)[pc->size].name);
  printf("请输入联系人的年龄:");
  scanf("%d", &((pc->data)[pc->size].age));
  printf("请输入联系人的性别:");
  scanf("%s", (pc->data)[pc->size].sex);
  printf("请输入联系人的地址:");
  scanf("%s", (pc->data)[pc->size].address);
  printf("请输入联系人的电话:");
  scanf("%s", (pc->data)[pc->size].telephone);
  pc->size++;
  printf("恭喜你,添加成功\n");
}
//在通讯录中通过名字查找一个人,并返回他的下标
int FindByName(const Contact* pc, char* arr)
{
  assert(pc && arr);
  int i = 0;
  for (i = 0; i < pc->size; i++)
  {
    if (strcmp(pc->data[i].name, arr) == 0)
    {
      return i;
    }
  }
  return -1;
}
//删除指定联系人
void DelContact(Contact* pc)
{
  assert(pc);
  if (pc->size == 0)
  {
    printf("通讯录为空,无法删除\n");
    return;
  }
  printf("请输入你要删除的联系人姓名>:");
  char arr[NAME_MAX] = { 0 };
  scanf("%s", arr);
  int pos = FindByName(pc, arr);
  if (pos == -1)
  {
    printf("没有这个人\n");
    return;
  }
  int i = pos;
  for (i = pos; i < pc->size - 1; i++)
  {
    pc->data[i] = pc->data[i + 1];
  }
  pc->size--;
  printf("删除成功\n");
}
//查找指定联系人
void SearchContact(const Contact* pc)
{
  assert(pc);
  if (pc->size == 0)
  {
    printf("通讯录为空,无法查找\n");
    return;
  }
  char arr[NAME_MAX] = { 0 };
  printf("请输入你要查找的名字>:");
  scanf("%s", arr);
  int pos = FindByName(pc, arr);
  if (pos == -1)
  {
    printf("通讯录中不存在这个人\n");
    return;
  }
  printf("%-20s %-4s %-5s %-30s %-12s\n", "姓名", "年龄", "性别", "地址", "电话");
  printf("%-20s %-4d %-5s %-30s %-12s\n",
    pc->data[pos].name,
    pc->data[pos].age,
    pc->data[pos].sex,
    pc->data[pos].address,
    pc->data[pos].telephone);
}
//修改指定联系人
void ModifyContact(Contact* pc)
{
  assert(pc);
  if (pc->size == 0)
  {
    printf("通讯录为空,无法修改\n");
    return;
  }
  char arr[NAME_MAX] = { 0 };
  printf("请输入你要修改的人的名字\n");
  scanf("%s", arr);
  int pos = FindByName(pc, arr);
  if (pos == -1)
  {
    printf("该联系人不存在\n");
    return;
  }
  printf("请输入联系人的姓名:");
  scanf("%s", pc->data[pos].name);
  printf("请输入联系人的年龄:");
  scanf("%d", &(pc->data[pos].age));
  printf("请输入联系人的性别:");
  scanf("%s", pc->data[pos].sex);
  printf("请输入联系人的地址:");
  scanf("%s", pc->data[pos].address);
  printf("请输入联系人的电话:");
  scanf("%s", pc->data[pos].telephone);
  printf("修改成功\n");
}
void cmp_by_name(void* e1, void* e2)
{
  return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void cmp_by_age(void* e1, void* e2)
{
  return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//排序通讯录
void SortContact(Contact* pc)
{
  assert(pc);
  int input = 0;
  printf("请选择你需要按姓名排序还是按照年龄排序\n");
  printf("按照姓名排序请输入1,按照年龄排序请输入2 :\n");
  scanf("%d", &input);
  if (input == 1)
    qsort(pc->data, pc->size, sizeof(PeoInfo), cmp_by_name);
  if (input == 2)
    qsort(pc->data, pc->size, sizeof(PeoInfo), cmp_by_age);
  printf("排序成功\n");
}
//打印通讯录
void ShowContact(const Contact* pc)
{
  assert(pc);
  int i = 0;
  printf("%-20s %-4s %-5s %-30s %-12s\n", "姓名", "年龄", "性别", "地址", "电话");
  for (i = 0; i < pc->size; i++)
  {
    printf("%-20s %-4d %-5s %-30s %-12s\n",
      pc->data[i].name,
      pc->data[i].age,
      pc->data[i].sex,
      pc->data[i].address,
      pc->data[i].telephone);
  }
}
//销毁通讯录
void DestoryContact(Contact* pc)
{
  free(pc->data);
  pc->data = NULL;
  pc->capacity = 0;
  pc->size = 0;
  pc = NULL;
}
//保存通讯录中的信息到文件中
void SaveContact(Contact* pc)
{
  FILE* pf = fopen("Contact.txt", "wb");
  if (pf == NULL)
  {
    perror("SaveContact");
    return;
  }
  int i = 0;
  for (i = 0; i < pc->size; i++)
  {
    fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
  }
  fclose(pf);
  pf = NULL;
  printf("数据已保存\n");
}
//读取存档
void LoadContact(Contact* pc)
{
  FILE* pf = fopen("Contact.txt", "rb");
  if (pf == NULL)
  {
    perror("LoadContact");
    return;
  }
  PeoInfo tmp = { 0 };
  int i = 0;
  while (fread(&tmp, sizeof(PeoInfo), 1, pf))
  {
    check_capacity(pc);
    pc->data[i] = tmp;
    pc->size++;
    i++;
  }
  fclose(pf);
  pf = NULL;
  printf("读取存档成功\n");
}

总结

实现了通讯录的再次升级,可以使用文件来保存信息

如果对你有帮助的话,不要忘记点赞加收藏哦!!!

想获得更多优质内容,一定要关注我哦!!!

相关文章
|
1月前
|
存储 XML JSON
【C语言-通讯录的分析与实现】
我们以手机里面的通讯录为例,说明通讯录主要有以下什么功能,我们先用一张简单的图来说明一下
18 0
|
1月前
|
C语言
【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化
动态内存管理的函数有:malloc,calloc,ralloc,free,本文讲解动态内存函数和使用,如何进行动态内存管理,实现通讯录联系人容量的动态化,对常见动态内存错误进行总结。
29 0
|
25天前
|
C语言
C语言——通讯录实现(增删查改+动态管理+文件操作)
C语言——通讯录实现(增删查改+动态管理+文件操作)
|
1月前
|
数据可视化 C语言
【C语言】实战项目——通讯录
学会创建一个通讯录,对过往知识进行加深和巩固。 文章很长,要耐心学完哦!
25 0
|
1月前
|
存储 C语言
【C语言进阶篇】模拟实现通讯录 (内附源码)
【C语言进阶篇】模拟实现通讯录 (内附源码)
38 1
|
2月前
|
存储 定位技术 API
贪吃蛇-c语言版本
贪吃蛇-c语言版本
|
2月前
|
存储 人工智能 算法
C语言之“动态顺序表的增删改查及拥有附加功能的通讯录实现”
C语言之“动态顺序表的增删改查及拥有附加功能的通讯录实现”
|
2月前
|
存储 文件存储 C语言
文件操作函数---C语言版本
数据存放在内存中:程序退出、掉电 =》数据丢失 数据存放在硬盘中:即存储在文件中,即使程序退出、掉电 =》数据不会丢失
|
1月前
|
C语言
(C语言内存操作函数)memset函数详情
memset函数的头文件、返回值、参数
17 0
|
2天前
|
C语言 C++
C语言变量、地址、字符及printf()/sizeof()/scanf()函数介绍
C语言变量、地址、字符及printf()/sizeof()/scanf()函数介绍
4 0

相关产品

  • 云迁移中心