目录
前言
通讯录的设计设计的知识点主要包括:结构体、枚举、指针、等知识点。首先我们要设计出通讯录的整体框架及其功能,其中储存的信息分别是什么。一个人的信息包括:名字、性别、年龄、电话、住址等;通讯录的功能有:增、删、差、改、显示、排序等。我们按照以上思路对通讯录进行实现。
1.主函数
1.1菜单
为了让使用者对本通讯录功能的了解,我们设计出一个菜单方便用户了解并进行使用。
void menu()
{
printf("******************************************\n");
printf("***** 1.Add 2. Del *****\n");
printf("***** 3.Sreach 4. Modify *****\n");
printf("***** 5.Show 6. Sort *****\n");
printf("***** 0.Exit *****\n");
printf("******************************************\n");
}
1.2主体函数的设计
基于我们对枚举类型的了解,在函数设计中我们加入枚举类型,以此来增加函数的可读性。
enum
{
Exit, //0
Add, //1
Del, //2
Sreach, //3
Modify, //4
Show, //5
Sort //6
};
void test()
{
menu();
Contact con;
InitContact(&con);
int input = 0;
do
{
printf("请输入要选择的模式:>");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&con);
break;
case Del:
DelContact(&con);
break;
case Sreach:
SreachContact(&con);
break;
case Modify:
ModifyContact(&con);
break;
case Show:
ShowContact(&con);
break;
case Sort:
SortContact(&con);
break;
case Exit:
printf("退出通讯录\n");
DestroyContact(&con);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
system("cls");
} while (input);
}
int main()
{
test();
return 0;
}
1.3结构体成员的设计
我们使用结构体,可以结构体中存入多个成员,为了方便代码的书写,加入了typedef对结构体进行重命名。并且在静态创建空间时,为了后续的空间维护,使用了宏来定义一些特殊的数字。也可以使用动态创建空间,避免了空间浪费的问题。
#define MAX 100
#define Name_Max 20
#define Tele_Max 12
#define Sex_Max 5
#define Addr_Max 30
#define INIT_Max 3
typedef struct Informatio
{
char name[Name_Max];
int age;
char tele[Tele_Max];
char sex[Sex_Max];
char addr[Addr_Max];
}Infor;
//静态的方法
//typedef struct contact
//{
// Infor data[MAX];
// int sz;
//}Contact;
//动态创建
typedef struct contact
{
Infor *data;
int capacity;//记录当前容量
int sz;//记录当前个数
}Contact;
2.通讯录的功能是实现
2.1通讯录的初始化
静态初始化通讯录,使用memset将通讯录的元素设置为0,并将通讯录当前长度设置为0;
动态初始化通讯录,使用malloc函数动态创建空间,将初始空间的大小设为3,同时将长度设置为0,容量设置为3。
初始化通讯录--静态
//void InitContact(Contact* con)
//{
// memset(con->data, 0,sizeof(con->data));
// con->sz = 0; //通讯录中元素的个数
//}
//动态初始化通讯录
void InitContact(Contact* con)
{
con->data = (Infor*)malloc(INIT_Max * sizeof(Infor));
if (con->data == NULL)
{
return;
}
con->sz = 0; //当前长度
con->capacity = INIT_Max; //当前容量
}
2.2增加通讯录成员
在增加通讯录成员的过程中我们首先要对通讯录的容量进行检查,静态数组检查当前长度与最大长度的对比,如果两个相等,直接退出,而动态数组则检查当前长度与容量,如果两个相等,使用realloc函数对容量进行扩充。容量没有问题的情况下,将要添加的输入到当前sz的位置。
//检查容量
void Check_Contact(Contact* con)
{
if (con->sz == con->capacity)
{
Infor* ptr = realloc(con->data, (con->capacity + 2) * sizeof(Infor));
if (ptr == NULL)
{
printf("增容失败\n");
}
else
{
con->data = ptr;
con->capacity += 2;
printf("增容成功\n");
}
}
}
//增加通讯录
void AddContact(Contact* con)
{
assert(con);
Check_Contact(con);
printf("请输入名字:>");
scanf("%s", con->data[con->sz].name);
printf("请输入年龄:>");
scanf("%d", &(con->data[con->sz].age));
printf("请输入性别:>");
scanf("%s", con->data[con->sz].sex);
printf("请输入电话:>");
scanf("%s", con->data[con->sz].tele);
printf("请输入地址:>");
scanf("%s", con->data[con->sz].addr);
con->sz++;//长度++
printf("成功增加联系人\n");
}
2.3通讯录成员的删除
在删除成员时,优先考虑通讯录当前是否为空,为空直接退出,不为空创建一个字符数组用来储存要删除成员的姓名,封装一个FindByName函数用于查找当前通讯录中是否有此成员,找到要删除的成员,将其后面的所有成员向前移动一位将其覆盖,并将sz减1。
//查找通讯录的成员
static int FindByName(const Contact* con, char name[])
{
int i = 0;
for (i = 0; i < con->sz; i++)
{
if (strcmp(con->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
//删除通讯录中的元素
void DelContact(Contact* con)
{
if (con->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
assert(con);
char name[Name_Max] = { 0 }; //储存要删除成员的名字
printf("请输入要删除人的名字:>");
scanf("%s", name);
int ret = FindByName(con, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
for (int i=ret; i < con->sz-1; i++)
{
con->data[i] = con->data[i + 1];
}
con->sz--;
printf("删除成功\n");
}
2.4通讯录成员的查找
使用封装好的FindByName函数对通讯录中的元素进行查找,并返回查找到的元素长度,在屏幕中打印出来。
//查找通讯录的人员
void SreachContact(Contact* con)
{
assert(con);
char name[Name_Max] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int ret = FindByName(con, name);
if (ret == -1)
printf("要查找的人不存在\n");
else
{
printf("%-10s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-5d\t%-5s\t%-12s\t%-30s\n",
con->data[ret].name,
con->data[ret].age,
con->data[ret].sex,
con->data[ret].tele,
con->data[ret].addr);
}
}
2.5 通讯录成员的修改
在上面通讯录查找的基础上,找到要查找人员所在的长度将其中的所有内容将其修改,也可以建立一个菜单,写上通讯录中的姓名、地址等精准打击修改,可参照2.7通讯录的排序。
void ModifyContact(Contact* con)
{
assert(con);
char name[Name_Max] = { 0 };
printf("请输入修改人的名字:>");
scanf("%s", name);
int ret = FindByName(con, name);
if (ret == -1)
printf("要查找的人不存在\n");
else
{
printf("请输入名字:>");
scanf("%s", con->data[ret].name);
printf("请输入年龄:>");
scanf("%d", &(con->data[ret].age));
printf("请输入性别:>");
scanf("%s", con->data[ret].sex);
printf("请输入电话:>");
scanf("%s", con->data[ret].tele);
printf("请输入地址:>");
scanf("%s", con->data[ret].addr);
printf("修改成功\n");
}
}
2.6通讯录成员的打印
用for循环将通讯录的元素进行打印。
void ShowContact(Contact* con)
{
assert(con);
//打印标题
printf("%-10s\t%-5s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
for (int i = 0; i < con->sz; i++)
{
printf("%-10s\t%-5d\t%-10s\t%-12s\t%-30s\n",
con->data[i].name,
con->data[i].age,
con->data[i].sex,
con->data[i].tele,
con->data[i].addr);
}
}
2.7对通讯录成员的排序
在其中建立菜单,让用户选择想要的排序方式,使用qsort对通讯录中的元素进行排序。
//按照年龄
int cmp_age(void* str1,void* str2)
{
//return *(char*)str1 - *(char*)str2;
return *(int*)str1 - *(int*)str2;
}
//按照姓名
int cmp_name(void* str1, void* str2)
{
return *(char*)str1 - *(char*)str2;
}
//按照地址
int cmp_addr(void* str1, void* str2)
{
return *(char*)str1 - *(char*)str2;
}
void menu1()
{
printf("****************************\n");
printf("****** 1.name ******\n");
printf("****** 2.age ******\n");
printf("****** 3.addr ******\n");
printf("****** 0.exit ******\n");
printf("****************************\n");
}
//排序
void SortContact(Contact* con)
{
//qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
menu1();
int input = 0;
printf("请输入要排序的模式:>");
scanf("%d", &input);
switch (input)
{
case 1://姓名
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_name);
break;
case 2://年龄
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
break;
case 3://住址
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_addr);
break;
case 0:
break;
default:
printf("输入错误!!!\n");
break;
}
ShowContact(con);
}
2.8通讯录的销毁
我们在使用malloc和realloc动态创建通讯录的空间后,在结束程序时要对创建的空间进行销毁,并将指针指向NULL,否则就会造成内存泄露。
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
3.整体代码
contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
初始化通讯录--静态
//void InitContact(Contact* con)
//{
// memset(con->data, 0,sizeof(con->data));
// con->sz = 0;
//}
//动态初始化通讯录
void InitContact(Contact* con)
{
con->data = (Infor*)malloc(INIT_Max * sizeof(Infor));
if (con->data == NULL)
{
return;
}
con->sz = 0;
con->capacity = INIT_Max;
}
//检查容量
void Check_Contact(Contact* con)
{
if (con->sz == con->capacity)
{
Infor* ptr = realloc(con->data, (con->capacity + 2) * sizeof(Infor));
if (ptr == NULL)
{
printf("增容失败\n");
}
else
{
con->data = ptr;
con->capacity += 2;
printf("增容成功\n");
}
}
}
//增加通讯录
void AddContact(Contact* con)
{
assert(con);
Check_Contact(con);
printf("请输入名字:>");
scanf("%s", con->data[con->sz].name);
printf("请输入年龄:>");
scanf("%d", &(con->data[con->sz].age));
printf("请输入性别:>");
scanf("%s", con->data[con->sz].sex);
printf("请输入电话:>");
scanf("%s", con->data[con->sz].tele);
printf("请输入地址:>");
scanf("%s", con->data[con->sz].addr);
//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);
con->sz++;
printf("成功增加联系人\n");
}
//判断字符串是否为空
int FindContact(Contact* con)
{
if (con->sz == 0)
{
return 0;
}
return 1;
}
//打印通讯录
void ShowContact(Contact* con)
{
assert(con);
//打印标题
printf("%-10s\t%-5s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
for (int i = 0; i < con->sz; i++)
{
printf("%-10s\t%-5d\t%-10s\t%-12s\t%-30s\n",
con->data[i].name,
con->data[i].age,
con->data[i].sex,
con->data[i].tele,
con->data[i].addr);
}
}
static int FindByName(const Contact* con, char name[])
{
int i = 0;
for (i = 0; i < con->sz; i++)
{
if (strcmp(con->data[i].name, name) == 0)
{
return i;//找到了
}
}
return -1;//找不到
}
//删除通讯录中的元素
void DelContact(Contact* con)
{
if (con->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
assert(con);
char name[Name_Max] = { 0 };
printf("请输入要删除人的名字:>");
scanf("%s", name);
int ret = FindByName(con, name);
if (ret == -1)
{
printf("查无此人\n");
return;
}
for (int i=ret; i < con->sz-1; i++)
{
con->data[i] = con->data[i + 1];
}
con->sz--;
printf("删除成功\n");
}
//查找通讯录的人员
void SreachContact(Contact* con)
{
assert(con);
char name[Name_Max] = { 0 };
printf("请输入要查找人的名字:>");
scanf("%s", name);
int ret = FindByName(con, name);
if (ret == -1)
printf("要查找的人不存在\n");
else
{
printf("%-10s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
//打印数据
printf("%-10s\t%-5d\t%-5s\t%-12s\t%-30s\n",
con->data[ret].name,
con->data[ret].age,
con->data[ret].sex,
con->data[ret].tele,
con->data[ret].addr);
}
}
//修改通讯录信息
void ModifyContact(Contact* con)
{
assert(con);
char name[Name_Max] = { 0 };
printf("请输入修改人的名字:>");
scanf("%s", name);
int ret = FindByName(con, name);
if (ret == -1)
printf("要查找的人不存在\n");
else
{
printf("请输入名字:>");
scanf("%s", con->data[ret].name);
printf("请输入年龄:>");
scanf("%d", &(con->data[ret].age));
printf("请输入性别:>");
scanf("%s", con->data[ret].sex);
printf("请输入电话:>");
scanf("%s", con->data[ret].tele);
printf("请输入地址:>");
scanf("%s", con->data[ret].addr);
printf("修改成功\n");
}
}
int cmp_age(void* str1,void* str2)
{
//return *(char*)str1 - *(char*)str2;
return *(int*)str1 - *(int*)str2;
}
int cmp_name(void* str1, void* str2)
{
return *(char*)str1 - *(char*)str2;
}
int cmp_addr(void* str1, void* str2)
{
return *(char*)str1 - *(char*)str2;
}
void menu1()
{
printf("****************************\n");
printf("****** 1.name ******\n");
printf("****** 2.age ******\n");
printf("****** 3.addr ******\n");
printf("****** 0.exit ******\n");
printf("****************************\n");
}
//排序
void SortContact(Contact* con)
{
//qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
menu1();
int input = 0;
printf("请输入要排序的模式:>");
scanf("%d", &input);
switch (input)
{
case 1://姓名
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_name);
break;
case 2://年龄
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_age);
break;
case 3://住址
qsort(con->data, con->sz, sizeof(con->data[0]), cmp_addr);
break;
case 0:
break;
default:
printf("输入错误!!!\n");
break;
}
ShowContact(con);
}
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
contact.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define MAX 100
#define Name_Max 20
#define Tele_Max 12
#define Sex_Max 5
#define Addr_Max 30
#define INIT_Max 3
typedef struct Informatio
{
char name[Name_Max];
int age;
char tele[Tele_Max];
char sex[Sex_Max];
char addr[Addr_Max];
}Infor;
//静态的方法
//typedef struct contact
//{
// Infor data[MAX];
// int sz;
//}Contact;
//动态创建
typedef struct contact
{
Infor *data;
int capacity;//记录当前容量
int sz;//记录当前个数
}Contact;
enum
{
Exit, //0
Add, //1
Del, //2
Sreach, //3
Modify, //4
Show, //5
Sort //6
};
//初始化通讯录
void InitContact(Contact* con);
//通讯录增加
void AddContact(Contact* con);
//打印通讯录
void ShowContact(Contact* con);
//删除通讯录中的元素
void DelContact(Contact* con);
//查找通讯录的人员
void SreachContact(Contact* con);
//修改通讯录信息
void ModifyContact(Contact* con);
//排序
void SortContact(Contact* con);
//通讯录的销毁
void DestroyContact(Contact* pc);
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void menu()
{
printf("******************************************\n");
printf("***** 1.Add 2. Del *****\n");
printf("***** 3.Sreach 4. Modify *****\n");
printf("***** 5.Show 6. Sort *****\n");
printf("***** 0.Exit *****\n");
printf("******************************************\n");
}
void test()
{
menu();
Contact con;
InitContact(&con);
int input = 0;
do
{
printf("请输入要选择的模式:>");
scanf("%d", &input);
switch (input)
{
case Add:
AddContact(&con);
break;
case Del:
DelContact(&con);
break;
case Sreach:
SreachContact(&con);
break;
case Modify:
ModifyContact(&con);
break;
case Show:
ShowContact(&con);
break;
case Sort:
SortContact(&con);
ShowContact(&con);
break;
case Exit:
printf("退出通讯录\n");
DestroyContact(&con);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}