c语言小课设--通讯录(动态内存管理+可持久化数据)

简介: c语言小课设--通讯录(动态内存管理+可持久化数据)

前言:

在没学动态内存管理之前,我们用的结构体,数组等都是静态分配内存的,也就是说数组的长度是固定的,但是这并不满足我们的实际需求,所以在通讯录项目里面我就用到了动态内存分布。简单来说,就是当需要储存的联系人数据太多了的时候,我们就可以扩大一点空间用来存放新的数据,也就是说实现了要多少,就开辟多少的空间。

项目介绍:

该项目实现一个通讯录功能,除了能根据具体需求扩大空间之外,也实现了最基本基本的增删查改等功能,并在退出通讯录时销毁创造的空间,从而不造成内存泄露。

另外,这个项目由三部分组成,函数功能的实现在Contact.c源文件中,各种头文件、函数等声明则由文件Contact.h来实现,最后测试在源文件test.c文件中进行。

一、teat.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
 
 
enum Option {
  Exit,
  add,
  modify,
  del,
  search,
  show,
  sort
};
 
void menu() {
  printf("************************\n");
  printf("**1.添加    2.修改******\n");
  printf("**3.删除    4.搜索******\n");
  printf("**5.展示    6.排序******\n");
  printf("**0.退出          ******\n");
  printf("************************\n");
}
 
 
int main() {
  int input = 0;
  Contacts Con;
  Init(&Con);
  do {
    menu();
    printf("请输入你的选择--》\n");
    scanf("%d", &input);
    switch (input) {
    case add://添加
      Add_Peo(&Con);
      break;
    case modify://修改
      Modify_Peo(&Con);
      break;
    case del:
      Del_Peo(&Con);
      break;
    case search:
      Sear_Peo(&Con); 
      break;
    case show:
      Show_Peo(&Con);
      break;
    case sort:
      Sort_Peo(&Con);
      break;
    case Exit:
      SaveContact(&Con);
      Destory_Contacts(&Con);
      printf("退出通讯录\n");
      break;
    default:
      printf("你的输入有误!\n");
      break;
 
    }
  } while (input != 0);
  return 0;
}

二、Contact.h头文件:

#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 5
#define tele_max 12
#define addr_max 20
#define num_max 100
#define default_cap 3
 
typedef struct PeoInfo {
  char name[name_max];
  char sex[sex_max];
  char tele[tele_max];
  int age;
}PeoInfo;
//静态通讯录版本
//typedef struct Contacts {
//  PeoInfo data[num_max];
//  int sz;
//}Contacts;
//动态版本
typedef struct Contacts {
  PeoInfo *data;//存放数据
  int sz;//记录当前联系人的数量
  int cap;//当前通讯录的容量
}Contacts;
 
 
 
//初始化通讯录
void Init(Contacts* Con);
//添加功能
void Add_Peo(Contacts* Con);
//修改功能
void Modify_Peo(Contacts* Con);
//删除联系人
void Del_Peo(Contacts* Con);
//展示联系人
void Show_Peo(Contacts* Con);
//查询联系人
void Sear_Peo(Contacts* Con);
//排序
void Sort_Peo(Contacts* Con);
//保存数据到通讯录中
void SaveContact(Contacts* Con);
//加载信息到通讯录
void LoadContact(Contacts* Con);

三、Contact.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
 
// 自定义比较剂,按名字字典序排序
 
int cmp(void* e1,void *e2) {
  //printf("%s %s\n", (, ((struct PeoInfo*)e2)->name);
  return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
 
//初始化通讯录
void Init(Contacts* Con) {
  assert(Con);
  Con->sz = 0;
  Con->cap = default_cap;
  Con->data = calloc(Con->cap, sizeof(PeoInfo));
  if (Con->data == NULL) {
    printf("初始化失败\n");
    return;
  }
  LoadContact(Con);
}
 
//void Init(Contacts* Con) {
//  assert(Con);
//  Con->sz = 0;
//  memset(Con->data, 0, sizeof(Con->data));
//}
 
//增加容量
void check_cap(Contacts* Con) {
  
    PeoInfo* ptr = realloc(Con->data, (Con->cap + 2) * sizeof(PeoInfo));
    if (ptr != NULL) {
      Con->data = ptr;
      Con->cap += 2;
      printf("增容成功\n");
    }
    else {
      perror("AddContacts->realloc");
      return;
    }
  
}
//添加功能
//动态版本
void Add_Peo(Contacts* Con) {
  assert(Con);
  if (Con->sz == Con->cap) {
    check_cap(Con);
  }
  printf("请输入添加人的姓名\n");
  scanf("%s", Con->data[Con->sz].name);
  printf("请输入添加人的年龄\n");
  scanf("%d", &Con->data[Con->sz].age);
  printf("请输入添加人的性别\n");
  scanf("%s", Con->data[Con->sz].sex);
  printf("请输入添加人的号码\n");
  scanf("%s", Con->data[Con->sz].tele);
  Con->sz++;
  return;
}
//静态版本
//void Add_Peo(Contacts* Con) {
//  assert(Con);
//  if (Con->sz == num_max) {
//    printf("通讯录已满\n");
//    return;
//  }
//  else {
//    printf("请输入添加人的姓名\n");
//    scanf("%s", Con->data[Con->sz].name);
//    printf("请输入添加人的年龄\n");
//    scanf("%d", &Con->data[Con->sz].age);
//    printf("请输入添加人的性别\n");
//    scanf("%s", Con->data[Con->sz].sex);
//    printf("请输入添加人的号码\n");
//    scanf("%s", Con->data[Con->sz].tele);
//    Con->sz++;
//    return;
//  }
//}
//按名字查找
int find_name(Contacts* Con,char *tager) {
  assert(Con);
  for (int i = 0; i < Con->sz; i++) {
    if (strcmp(Con->data[i].name, tager)==0) {
      return i;
    }
  }
  return -1;
  
  
}
//修改功能
void Modify_Peo(Contacts* Con) {
  assert(Con);
  char name[name_max] = {0};
  while (1) {
    printf("请输入你要修改联系人的名字\n");
    scanf("%s", name);
    int k = find_name(Con, name);
    if ( k!= -1&&k>=0&&k<Con->sz) {
      printf("请重新输入修改的姓名\n");
      scanf("%s", Con->data[k].name);
      printf("请重新输入修改的的年龄\n");
      scanf("%d",&Con->data[k].age);
      printf("请重新输入修改的的性别\n");
      scanf("%s", Con->data[k].sex);
      printf("请重新输入修改的的号码\n");
      scanf("%s", Con->data[k].tele);
      printf("修改成功!\n");
      break;
    }
    else {
      printf("查无此人\n");
      break;
    }
  }
 
}
//删除联系人
void Del_Peo(Contacts* Con) {
  assert(Con);
  if (Con->sz == 0) {
    printf("该通讯录还没有联系人\n");
    return;
  }
  printf("请输入你要删除联系人的姓名\n");
  char name1[name_max] = { 0 };
  scanf("%s", name1);
  int k = find_name(Con, name1);
  if (k != -1&&k>=0&&k<Con->sz) {
    for (int i = k; i < Con->sz - 1; i++) {
      Con->data[i] = Con->data[i + 1];
    }
    Con->sz--;
    printf("删除成功\n");
  }
  else {
        printf("查无此人\n");
    return;
  }
}
//展示联系人
void Show_Peo(Contacts* Con) {
  assert(Con);
  if (Con->sz == 0) {
    printf("没有联系人\n");
    return;
  }
  printf("-------------------------------------------------\n");
  printf("|%-20s |%-5s |%-5s |%-12s| \n","姓名","年龄","性别","号码");
  printf("-------------------------------------------------\n");
  for (int i = 0; i < Con->sz; i++) {
    printf("|%-20s |%-5d |%-5s |%-12s|\n", Con->data[i].name, Con->data[i].age, Con->data[i].sex, Con->data[i].tele);
    if (i != (Con->sz - 1)) {
      printf("-------------------------------------------------\n");
    }
  }
  printf("-------------------------------------------------\n");
}
//查询联系人
void Sear_Peo(Contacts* Con) {
  assert(Con);
  char tager[name_max] = { 0 };
  if (Con->sz == 0) {
    printf("没有联系人\n");
    return;
  }
  printf("请输入你要查找的名字\n");
  scanf("%s", tager);
  int k = find_name(Con, tager);
  if (k != -1 && k >= 0 && k < Con->sz) {
    printf("-------------------------------------------------\n");
    printf("|%-20s |%-5s |%-5s |%-12s| \n", "姓名", "年龄", "性别", "号码");
    printf("|%-20s |%-5d |%-5s |%-12s|\n", Con->data[k].name, Con->data[k].age, Con->data[k].sex, Con->data[k].tele);
    printf("-------------------------------------------------\n");
  }
  else {
    printf("查无此人\n");
    return;
  }
}
//排序
void Sort_Peo(Contacts* Con) {
  assert(Con);
  qsort(Con->data, Con->sz, sizeof(struct PeoInfo), cmp);
  printf("排序成功\n");
  return;
}
//销毁通讯录
void Destory_Contacts(Contacts* Con) {
  free(Con->data);
  Con->data = NULL;
  Con->cap = 0;
  Con->sz = 0;
}
 
//保存数据到文件中
void SaveContact(Contacts* Con) {
  assert(Con);
 
  FILE* pf = fopen("Contact.txt", "wb");
  if (pf == NULL) {
    perror("SaveContact");
    return;
  }
 
  for (int i = 0; i < Con->sz; i++) {
    fwrite(Con->data + i, sizeof(PeoInfo), 1, pf);
  }
 
  fclose(pf);
  pf = NULL;
}
 
//加载文件中的数据到通讯录中
void LoadContact(Contacts* Con) {
  assert(Con);
 
  FILE* pf = fopen("Contact.txt", "rb");
  if (pf == NULL) {
    perror("LoadContact");
    return;
  }
 
  PeoInfo temp = { 0 };
  while (fread(&temp, sizeof(PeoInfo), 1, pf)) {
    check_cap(Con);
    Con->data[Con->sz] = temp;
    Con->sz++;
  }
 
  fclose(pf);
  pf = NULL;
}

好了以上就是整个项目的源代码了,是不是很简单呢?感兴趣的可以自己去试试哦!

相关文章
|
3天前
|
消息中间件 存储 Kafka
实时计算 Flink版产品使用问题之 从Kafka读取数据,并与两个仅在任务启动时读取一次的维度表进行内连接(inner join)时,如果没有匹配到的数据会被直接丢弃还是会被存储在内存中
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
2天前
|
存储 分布式计算 监控
Java一分钟之-Hazelcast:内存数据网格
【6月更文挑战第17天】**Hazelcast是开源的内存数据网格(IMDG),加速分布式环境中的数据访问,提供内存存储、分布式计算、线性扩展及高可用性。常见挑战包括内存管理、网络分区和数据分布不均。通过配置内存限制、优化网络和分区策略可避免问题。示例展示如何创建Hazelcast实例并使用分布式Map。使用Hazelcast提升性能和扩展性,关键在于理解和调优。**
17 1
|
4天前
|
程序员 C语言 C++
【C语言基础】:动态内存管理(含经典笔试题分析)-2
【C语言基础】:动态内存管理(含经典笔试题分析)
|
4天前
|
程序员 编译器 C语言
【C语言基础】:动态内存管理(含经典笔试题分析)-1
【C语言基础】:动态内存管理(含经典笔试题分析)
|
4天前
|
存储 小程序 编译器
【C语言基础】:数据在内存中的存储
【C语言基础】:数据在内存中的存储
|
4天前
|
安全 C语言
【C语言基础】:内存操作函数
【C语言基础】:内存操作函数
TU^
|
4天前
|
程序员 编译器 C语言
C语言之动态内存管理
C语言之动态内存管理
TU^
5 1
|
存储 程序员 编译器
一文读懂C语言与C++动态内存
一文读懂C语言与C++动态内存
127 0
|
5天前
|
算法 Unix Linux
C语言随机数的产生(rand、srand、time函数细节讲解)
C语言随机数的产生(rand、srand、time函数细节讲解)
|
4天前
|
编译器 C语言 C++
【C语言基础】:字符函数和字符串函数-2
【C语言基础】:字符函数和字符串函数