- 初始化通讯录
- 相关功能的实现(增删查改显排)
- 最终的代码
设计思路讲解:
我们以手机上的通讯录为例,用C来设计一个简单的通讯录版本
通讯录的功能参照手机上的版本应该有增加,删除,修改,查找,因为我们的代码最终是在终端显示的,所以我们再给出一个显示通讯录的功能,以及最后对通讯录进行排序的功能。
我们使用结构体来集合关于通讯录中联系人的信息(定义为PeoInfo),这就需要我们要有一个关于PeoInfo的集合来存放多个人的信息,集合的大小可以由动态内存函数来开辟,内存空间不足时自动增加空间以便增添联系人。
删除时,有很多的方法,可以将要删除的联系人的信息全部改为0,然后qsort一下就ok了。也可以用该联系人后面的联系人覆盖掉要删除的,这样也能实现。方法还有很多,这里不一一给出了。
修改时我们要先输入该联系人的名字,然后重新输入信息。
查找也是要先输入联系人的名字,然后显示联系人的信息,我们发现在实现删除,修改查找等功能时,都要涉及到输入联系人的名字进行插查询,所以我们在写代码时,可以将这一功能封装成一个函数,以减少我们重复的代码。
显示通讯录就很容易实现了,只需要将所有的联系人信息全部打印出来就好了,这里可以使用循环来解决。
排序我们就使用qsort进行,可以按照名字,年龄,或者其他的信息来进行排
序,这个取决于程序员自己。
接下来我们就来开始对各个功能的代码实现,在最后会给出最后的代码。有基础的小伙伴可以直接跳到最后查看最终代码。
初始化通讯录首先要创建一个通讯录出来才能对其初始化,前面我们说过使用PeoInfo来收集联系人的信息
struct PeoInfo
{
char name[MAX_NAME];
char sex[SEX];
int age;
char telephone[TelePhone];
};
大小我们统一使用宏定义来 *** 作,方便我们后续的修改。
只有一个结构体行吗??
肯定是不行的,因为我们还需要一个集合体来存放PeoInfo的信息,所以还要有一个结构体,这个结构体包含我们的PeoInfo。
//通讯录结构体
struct Contact
{
//创建sz的目的是为了在进行添加删除等 *** 作时,好找到元素的下标
int sz;
struct PeoInfo* arr;
int capacity;//容量大小.
};
这还给出了sz和capacity两个参数,capacity是记录通讯录结构体的大小,sz是用来记录当前联系人的个数,以方便我们后续的增加,删除和查找等功能的实现,这一点如果能想到的话,后面的实现就很容易了,因为后续的大多功能都是以这两个参数为工具进行的。
结构体创建好了之后,我们就要对其初始化了,除了capacity需要给定一个初始大小之外,剩下的都要全部初始化为0。
//初始化为全0;
void InitContact(struct Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = 3;//默认容量大小是3
pc->arr = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));
if (pc->arr == NULL)
{
strerror(errno);
return; //exit(-1)
}
}
我们把有关通讯录的实现的代码放到contact.c的文件中,把所有包含的头文件放在contact.h的头文件当中,把代码的主主体躯干放在test.c的测试文件当中。
相关功能的实现(增删查改显排)剩下功能的实现以及注意事项我们在代码中注释了,大家留意一下就好,另外我把上面初始化的代码也一并在这里给大家展示出来,这里的代码就是contact.c中的代码啦~
#include "contact.h"
//初始化为全0;
void InitContact(struct Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = 3;//默认容量大小是3
pc->arr = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));
if (pc->arr == NULL)
{
strerror(errno);//打印错误信息
return;
}
}
//增加联系人
void ADDContact(struct Contact* pc)
{
assert(pc);
//如果空间已满的话,要先增加一定的空间
if (pc->sz == pc->capacity)
{
//增加容量
struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->arr, (pc->capacity + 2)*sizeof(struct PeoInfo));//一次扩充两个大小的空间
if (ptr == NULL)
{
strerror(errno);//对应的头文件,
return;
}
else
{
pc->capacity += 2;
pc->arr = ptr;
ptr = NULL;
printf("增容成功!\n");
}
}
//增加
printf("请输入名字:>");
scanf("%s", pc->arr[pc->sz].name);
printf("请输入性别:>");
scanf("%s", pc->arr[pc->sz].sex);
printf("请输入年龄:>");
scanf("%d", &(pc->arr[pc->sz].age));
printf("请输入电话:>");
scanf("%s", pc->arr[pc->sz].telephone);
//sz++指向下一个空白的元素,方便下次直接添加联系人
pc->sz++;
printf("成功增加联系人\n");
}
//将查找指定联系人封装成一个函数,因为在后续的功能中还要用到这个
int FindByName(const struct Contact* pc, char* n)
{
assert(pc && n);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
//strcmp比较两个字符串是否相同
if (0 == strcmp(pc->arr[i].name, n))
{
return i;
}
}
return -1;
}
//删除void DeleContact(struct Contact* pc);
void DeleContact(struct Contact* pc)
{
assert(pc);
char n[MAX_NAME];
printf("请输入查找联系人的名字:>");
scanf("%s", n);
int ret = FindByName(pc, n);
if (ret == -1)
printf("该联系人不存在\n");
else
{
//删除
for (int j = ret; j < pc->sz - 1; j++)
{
pc->arr[j] = pc->arr[j + 1];
}
//记得减减!!!!
pc->sz--;
printf("成功删除指定联系人\n");
//方法2,qsort排序,将要删除的人的数据改为0,再qsort排序一下也行,同样记得pc->sz--;
}
}
//修改
void ModifyContact(struct Contact* pc)
{
assert(pc);
printf("请输入要修改人的名字:>");
char name[MAX_NAME];
scanf("%s", name);
int ret = FindByName(pc, name);
if (ret == -1)
printf("要修改的人不存在\n");
else
{
//将要修改的人的信息重新录入,并提示修改成功!
printf("请输入名字:>");
scanf("%s", pc->arr[ret].name);
printf("请输入性别:>");
scanf("%s", pc->arr[ret].sex);
printf("请输入年龄:>");
scanf("%d", &(pc->arr[ret].age));
printf("请输入电话:>");
scanf("%s", pc->arr[ret].telephone);
printf("修改成功\n");
}
}
//查找
void SearchContact(const struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要查找的人的名字:>");
scanf("%s", name);
//查找一下指定的人是否存在
int ret = FindByName(pc, name);
if (ret == -1)
printf("要查找的人不存在\n");
else
{
printf("%-20s\t%-5s\t%-5s\t%-12s\n", "姓名", "性别", "年龄", "电话");
printf("%-20s\t%-5s\t%-5d\t%-12s\n", pc->arr[ret].name,
pc->arr[ret].sex,
pc->arr[ret].age,
pc->arr[ret].telephone);
}
}
//显示联系人
void ShowContact(const struct Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s\t%-5s\t%-5s\t%-12s\n", "姓名", "性别", "年龄", "电话");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-12s\n", pc->arr[i].name,
pc->arr[i].sex,
pc->arr[i].age,
pc->arr[i].telephone);
}
}
//按照名字排
//大家也可以自己写一个使用年龄排序的代码
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);//这里排的是升序
}
void SortContact(const struct Contact* pc)
{
assert(pc);
qsort(pc->arr, pc->sz, sizeof(pc->arr[0]), cmp_name);
printf("排序成功!结果如下:\n");
//在tect.c文件中在调用一次ShowContact函数即可
}
//退出通讯录的最后一定要记得释放空间!!!!!
void Destroy(struct Contact* pc)
{
free(pc->arr);
pc->arr = NULL;
}
最终的代码
下面就给出有关test.c和contact.h的相关代码。
test.c
#include "contact.h"
enum ST
{
退出通讯录,//0
增加联系人,//1
删除联系人,//2
修改联系人,//3
查找联系人,//4
显示联系人,//5
排序联系人//6
};
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;
//创建通讯录
struct Contact contact;
//初始化通讯录数组
InitContact(&contact);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 增加联系人:
ADDContact(&contact);
system("pause");
system("cls");
break;
case 删除联系人:
DeleContact(&contact);
system("pause");
system("cls");
break;
case 修改联系人:
ModifyContact(&contact);
system("pause");
system("cls");
break;
case 查找联系人:
SearchContact(&contact);
system("pause");
system("cls");
break;
case 显示联系人:
ShowContact(&contact);
system("pause");
system("cls");
break;
case 排序联系人:
//qsort排序
SortContact(&contact);
ShowContact(&contact);
system("pause");
system("cls");
break;
case 0:
//释放指针-当程序退出的时候,释放掉自己开创的空间,防止内存泄露!!
Destroy(&contact);
printf("再见!\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
contact.h
#include
#include
#include
#include
#include
#include
//方便以后的修改
#define MAX_NAME 30
#define SEX 6
#define TelePhone 13
//联系人信息
struct PeoInfo
{
char name[MAX_NAME];
char sex[SEX];
int age;
char telephone[TelePhone];
};
//通讯录结构体
struct Contact
{
//创建sz的目的是为了在进行添加删除等 *** 作时,好找到元素的下标
int sz;
struct PeoInfo* arr;
int capacity;//容量大小.
};
void InitContact(struct Contact* pc);
void ADDContact(struct Contact* pc);
void DeleContact(struct Contact* pc);
void ModifyContact(struct Contact* pc);
void SearchContact(const struct Contact* pc);
void ShowContact(const struct Contact* pc);
void SortContact(const struct Contact* pc);
void Destroy(struct Contact* pc);
热心老铁,在线答疑!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)