文章目录
1.模拟实现通讯录总体架构一览图
2.文件执行任务
3.分模块实现
测试模块 test.c
1.为了更好地展示,制作一个菜单,在菜单中有 添加,删除,查找,修改,排序,清空,退出的选项。
2.因为起先要进入程序一趟,所以用do····while循环(输入选项来看具体操作,退出还是其他操作)
#include "contact.h"
void menu()
{
printf("*****************************************\n");
printf("******** Contact ******\n");
printf("******** 1.add 2. del ******\n");
printf("******** 3.search 4.modify ******\n");
printf("******** 5.print 6.empty ******\n");
printf("******** 7.sort 0.exit ******\n");
printf("*****************************************\n");
}
enum Option
//为什么要使用枚举
//因为这样可以防止命名污染,而且使用枚举,枚举成员有默认初始值,默认从0开始,这样省去的诸多的代码量
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
PRINT,
EMPTY,
SORT,
};
int main()
{
//先打印菜单,展示通讯录功能
int input = 0;
//先进行设置一个通讯录
//设置每个人的信息
//初始化通讯录
//通讯录中的一个元素
contact con;
//contact 是自定义数据类型,包括一个联系人的基本信息
InitContact(&con);
do
{
menu();//设置菜单
printf("请选择>");
scanf("%d", &input);
switch (input)
{
case ADD:
//实现添加功能
AddContact(&con);
break;
case DEL:
//实现删除功能
DelContact(&con);
break;
case SEARCH:
//实现查找功能
SearchContact(&con);
break;
case MODIFY:
//实现修改功能
ModifyContact(&con);
break;
case PRINT:
//显示
PrintContact(&con);
break;
case SORT:
//实现名字排序
SortContact(&con);
break;
case EMPTY:
//实现清空
EmptyContact(&con);
break;
case EXIT:
//退出程序
ExitContact(&con);
break;
default:
printf("输入错误,请重新输入\n");
}
} while (input);
return 0;
}
头文件 功能函数声明 contact.h
1.声明各类功能函数
2.定义各个常量,把常量定义成通俗易懂的变量,便于在多处使用。
3.定义结构体,自定义类型中,有一个联系人的基本信息。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_NAME 20 //定义姓名字符串的大小为20
#define MAX_SEX 10 //定义性别字符串的大小为10
#define MAX_TELE 12 //定义电话字符串的大小为12
#define MAX_ADDR 20 //定义地址字符串的大小为20
#define MAX 1000 //定义通讯录的最大容量为1000
#define IN_NUM 3 //在动态申请空间时默认空间为3
#define SET_NUM 2 //当基本信息大于3份时,开辟两个空间
//设置每一个人的信息
//通讯录规定要求一共有1000个人
typedef struct base
{
char name[MAX_NAME]; //姓名
char sex[MAX_SEX]; //性别
int age; //年龄
char tele[MAX_TELE]; //电话
char addr[MAX_ADDR]; //住址
}base;
//设置1000人的通讯录
//静态版
//typedef struct contact
//{
//
// int sz; //计算当前通讯录中联系人的个数
// base data[MAX]; //存放联系人的信息
//
//}contact;
//动态初始化通讯录
typedef struct contact
{
//有个结构体类型中需要,监视通讯录人数的一项,还有当联系人为3人时,这时候要进行增容
int sz; //计算当前联系人的个数
base* data; //指向动态申请的空间,存放联系人的信息
int capciaty; //计算当前通讯录中的最大容量
}contact;
//初始化通讯录
void InitContact(contact* pc);
//添加联系人
void AddContact(contact* pc);
//显示
void PrintContact(contact* pc);
//删除联系人
void DelContact(contact* pc);
//查找联系人
void SearchContact(contact* pc);
//修改信息
void ModifyContact(contact* pc);
//排序联系人信息
void SortContact(contact* pc);
//清空联系人信息
void EmptyContact(contact* pc);
//退出程序时,释放空间
void ExitContact(contact* pc);
功能函数逐一实现 contact.c
1.初始化通讯录
动态申请空间
默认在动态空间中存放3个基本单位信息
void InitContact(contact* pc)
{
pc->data = (base*)malloc(sizeof(base) * IN_NUM);
if (pc->data == NULL)
//如果空间开辟失败
//退出程序
{
perror("InitContact");
return;
}
//把每个成员都设置为0
pc->sz = 0;
pc->capciaty = IN_NUM;
}
2.添加联系人
当默认的空间被装满时,然后以后的每一次都开辟两个基本空间
void AddContact(contact* pc)
{
//先判断通讯录中是否满了
//if (pc->sz == MAX)
//{
// printf("通讯录已满,无法添加\n");
// return;
//}
//动态判断人的个数是否满足3
if (pc->sz == pc->capciaty)
{
printf("开始增容:\n");
//从新设置一个指针,存放新开辟的内存
base* ptr = (base*)realloc(pc->data, (pc->capciaty + SET_NUM) * sizeof(base));
//判断是否开辟成功
if (ptr == NULL)
{
printf("开辟失败\n");
perror("AddContact");
return;
}
else
{
printf("开辟成功\n");
//开辟成功的话,把ptr转交给data来维护,这样在内存释放的时候只需要释放pc->data
pc->data = ptr;
//增加基本信息数量
pc->capciaty += SET_NUM;
}
printf("增容完毕\n");
}
//添加
printf("姓名是>");
scanf("%s", pc->data[pc->sz].name);
printf("年龄是>");
scanf("%d", &pc->data[pc->sz].age);
printf("性别>");
scanf("%s", pc->data[pc->sz].sex);
printf("电话>");
scanf("%s", pc->data[pc->sz].tele);
printf("住址>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
3.显示联系人信息
逐一打印联系人信息,注意之间的距离(保持美观)
//显示
void PrintContact(contact* pc)
{
//显示标题
printf("%-20s %-10s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话", "住址");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-20s %-10s %-5d %-15s %-20s\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].addr);
}
}
4.删除联系人
在删除联系人之前,首先要查找要删除联系人的名字,然后进行删除,注意如何删除
让删除的这个单位的后一个单位去覆盖这个删除的单位(这样原来要删除的地方变成了后面一个值) i = i+1
当通讯录中有被删除着的名字时,返回这个单位的下标
当通讯录中没有时,返回-1
//查找联系人
static int Find_name(contact* pc, char name[])
{
int i = 0;
for ( i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;
}
//删除联系人
void DelContact(contact* pc)
{
//如果通讯录是空的
if (pc->sz == 0)
{
printf("通讯为空,无需删除\n");
return;
}
//下进行查找被删除联系人的名字
char name[MAX_NAME];
printf("请输入要删除联系人的名字:");
scanf("%s", name);
int ret = Find_name(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
//删除
//删除项后边的一项,覆盖前面的一项
for (int i = ret; i < pc->sz; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
4.查找联系人
在删除联系人的时候有查找函数,在这里直接引用,并打印。这个人的信息。
//查找联系人
void SearchContact(contact* pc)
{
char name[MAX_NAME];
printf("请输入要查找联系人的名字:");
scanf("%s", name);
int ret = Find_name(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
printf("%-20s %-10s %-5s %-15s %-20s\n", "姓名", "性别", "年龄", "电话", "住址");
printf("%-20s %-10s %-5d %-15s %-20s\n", pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].addr);
}
5.修该联系人信息
还是现在通讯录中查找这个联系人,在进行输入修改
//修改信息
void ModifyContact(contact* pc)
{
char name[MAX_NAME];
printf("请输入要修改联系人的名字:");
scanf("%s", name);
int ret = Find_name(pc, name);
if (ret == -1)
{
printf("该联系人不存在\n");
return;
}
printf("姓名是>");
scanf("%s", pc->data[ret].name);
printf("年龄是>");
scanf("%d", &pc->data[ret].age);
printf("性别>");
scanf("%s", pc->data[ret].sex);
printf("电话>");
scanf("%s", pc->data[ret].tele);
printf("住址>");
scanf("%s", pc->data[ret].addr);
}
6.排序联系人姓名
利用冒泡排序对联系人的名字进行排序(也可以使用快排)
//排序
//交换名字,但是名字要和联系人的信息匹配
//先比较名字,根据名字的大小,再排序
static void SwapByname(base* pa, base* pb)
{
base b;
b = *pa;
*pa = *pb;
*pb = b;
}
void SortContact(contact* pc)
{
printf("开始排序\n");
//使用冒泡排序对联系人的名字进行排序
int i = 0;
int j = 0;
for (i = 0; i < pc->sz; i++)
{
for (j = 0; j < pc-> sz - i - 1; j++)
{
if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
{
//实现交换姓名
SwapByname(&pc->data[j], &pc->data[j + 1]);
}
}
}
printf("排序结束\n");
}
7.清空联系人
在这里直接使用sz–,就可以删除
//清空
void EmptyContact(contact* pc)
{
//如果原来的通讯录是空的就无须清空
if (pc->sz == 0)
{
printf("通讯录为空,无需清空\n");
return;
}
printf("开始清除数据:\n");
int num = pc->sz;
for (int i = 0; i < num; i++)
{
pc->sz--;
}
printf("清空完毕\n");
}
8.退出通讯录
手动开辟,手动释放
//退出程序,释放空间
void ExitContact(contact* pc)
{
//释放空间
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capciaty = 0;
}
运行展示: