目录
前言
程序设计
1. 创建通讯录
2. 初始化通讯录
3. 实现通讯录内的功能
1. 增加联系人
2. 显示所有联系人
3. 查找联系人
4. 删除指定联系人
5. 修改联系人的信息
6. 清空通讯录
7. 排序所有联系人
源代码
制作一个通讯录需要包涵以下内容:
- 增加联系人
- 删除指定联系人
- 查找联系人
- 修改联系人的信息
- 显示所有联系人
- 清空通讯录
- 排序所有联系人(姓名/年龄等)
完成代码最主要的就是需要先构思代码内需要包涵的功能,并一步一步的实现它,那么接下来就带大家一起完成这个简易的通讯录吧!
首先,创建通讯录之前我们需要创建一个结构体来表示一个人的信息,例如一个人的信息可以包括姓名、性别、年龄、电话和地址等。
struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
};
在这里我们使用了#define定义符号以便在后期可以方便更改内容的大小。
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
接下来就是创建通讯录。
通讯录里面需要包涵n个人的信息,那么我可以创建一个结构体PeoInfo的数组来存放这些信息。那么我们要怎么知道里面有多少个数组呢?我们可以再创建一个变量来表示通讯录里面信息的数量。(很重要!!!)
struct Contact
{
struct PeoInfo data[MAX];
int sz;
//通过sz来将信息存放到data数组里面
};
#define MAX 1000
创建完通讯录之后,我们需要对通信录内的信息进行初始化。
//初始化通讯录
void InitContact(struct Contact* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, 100 * sizeof(struct PeoInfo));
}
这一部分较为简单,主要是利用memset函数将data里面的信息都初始化成0。
至于详细的内容,大家可以在链接里面了解: https://cplusplus.com/reference/cstring/memset/?kw=memsety
要注意,使用memset函数需要引用头文件#include
首先,我们需要思考两种情况:一种是通讯录满了、一种是通讯录还没满。
通讯录满了就无法再添加联系人了,因此无法再进行增加的操作。
//增加一个人的信息
void AddContact(struct Contact* pc)
{
assert(pc);
if (MAX == pc->sz)
{
printf("通讯录已满,无法添加信息\n");
return;
}
printf("请输入姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:");
scanf("%d", &pc->data[pc->sz].age);//数组名为首元素地址,因此非数组需要加上‘&‘符号
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功添加联系人\n");
}
我们对pc指针指向的data数组内下标为pc指针指向的sz数量所对应的元素进行操作。
因为一开始data数组为0个信息,因此可以在data数组下标为0的元素进行操作,在操作完之后对sz进行加一的操作,令之后的增加操作也可以如此进行。
当某一次增加操作将sz加到MAX的值时无法再对通讯录进行增加的操作。
在对通讯录进行增加联系人完成之后,我们想要先看到通讯录的情况,因此我们可以先完成对通讯录的显示操作。
void ShowContact(const struct Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s\t%-5s\t%-2s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-2d\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].addr);
}
}
显示所有联系人的操作,我们只需要注意显示的格式就可以了。只要标题能够对应好相应的信息即可。
当有大量联系人在通讯录时,用户想查找通讯录里面的某一位联系人就变得非常困难,因此我们需要增加查找联系人的操作以完善通讯录的功能。
注意:再此之前我们可以先思考思考,删除联系人与修改联系人信息是不是也需要先找到指定的联系人?所以我们可以为查找指定联系人封装一个内部的函数,当返回-1时,通讯录里面没有这位联系人;当返回其他值时,则返回对应联系人在data数组里的下标。
//查找通讯录中是否存在此人
static int FindNamePeo(const struct Contact* pc, char* name)
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name))
return i;
}
return -1;
}
//查找通讯录中某个人的信息
void SearchContact(const struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要查找的人的姓名:>");
scanf("%s", &name);
int ret = FindNamePeo(pc, name);
if (-1 == ret)
{
printf("找不到此人信息\n");
return;
}
else
{
printf("%-20s\t%-5s\t%-2s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-5s\t%-2d\t%-12s\t%-30s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].addr);
}
}
如果用户想删除某一位联系人,我们可以直接将对应的联系人删除并将后面的联系人向前移动一位即可。(还有一种方法就是将最后一位联系人的信息补齐到要删除的人的位置)
在进行上述操作之前,我们是不是应该先需要知道通讯录是否有这位联系人呀,所以我们需要先查找这一位联系人是否存在通讯录里。
//删除通讯录中某一个人的信息
void DeleteContact(struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要删除的人的姓名:>");
scanf("%s", &name);
int ret = FindNamePeo(pc, name);
if (-1 == ret)
{
printf("找不到此人信息\n");
return;
}
else
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
pc->data[ret + i] = pc->data[ret + i + 1];
}
pc->sz--;
printf("成功删除信息\n");
}
}
再最后将通讯录的总数sz减一就达到删除联系人的效果。
用户想要修改某一个人的信息,先要查找修改人的信息,只用引入上面的查找函数。返回的数字为data数组的下标。
//修改通讯录中某一个人的信息
void ModifyContact(struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要修改信息的人的姓名:>");
scanf("%s", &name);
int ret = FindNamePeo(pc, name);
if (-1 == ret)
{
printf("找不到此人信息\n");
return;
}
else
{
printf("请输入姓名:");
scanf("%s", pc->data[ret].name);
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄:");
scanf("%d", &pc->data[ret].age);
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
}
printf("成功修改信息\n");
}
清空通讯录就是将通讯录里面的信息全部清零,即初始化。
//清空所有联系人
void RemoveContant(struct Contact* pc)
{
assert(pc);
InitContact(pc);
printf("成功清除所有联系人\n");
}
说到排序就不得不提起qsort函数,将数组的内容进行排序。
qsort函数具体用法在此链接可以了解:https://cplusplus.com/reference/cstdlib/qsort/?kw=qsort
void SortContact(struct Contact* pc)
{
assert(pc);
qsort(pc->data, pc->sz, sizeof(struct PeoInfo), CmpByName);
}
使用qsort函数最主要的就是自己创建的排序方法,例如上述代码中的CmpByName
将数组的两个元素相减,剩下的值为排序的方法。
这里我提供两种排序方法:
以年龄作排序:
//以年龄作排序
int CmpByAge(const void* e1, const void* e2)
{
return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
以姓名作排序:
//以姓名作排序
int CmpByName(const void* e1, const void* e2)
{
return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
留意字符串的比较需要使用strcmp函数。
至此,静态版本的通讯录的基本功能就已经实现了。
contact.h
#include
#include
#include
#include
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
//表示一个人的信息:姓名、性别、年龄、电话、住址
struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char addr[MAX_ADDR];
};
struct Contact
{
struct PeoInfo data[MAX];
int sz;
//通过sz来将信息存放到data数组里面
};
//初始化通信录
void InitContact(struct Contact* pc);
//增加一个人的信息
void AddContact(struct Contact* pc);
//显示通讯录
void ShowContact(const struct Contact* pc);
//查找通讯录中某一个人的信息
void SearchContact(const struct Contact* pc);
//删除通讯录中某一个人的信息
void DeleteContact(struct Contact* pc);
//修改通讯录中某一个人的信息
void ModifyContact(struct Contact* pc);
//清空所有联系人
void RemoveContant(struct Contact* pc);
//排序通讯录
void SortContact(struct Contact* pc);
test.c
#include "contact.h"
void mune()
{
printf("************************************\n");
printf("***** 1. Add 2. Delete *****\n");
printf("***** 3. Search 4. Modify *****\n");
printf("***** 5. Show 6. Remove *****\n");
printf("***** 7. Sort 0. Exit *****\n");
printf("************************************\n");
}
void test()
{
int input = 0;
//创建通讯录
struct Contact con;
//初始化通讯录
InitContact(&con);
do
{
mune();
printf("请输入:> ");
scanf("%d", &input);
switch (input)
{
case 1://add
AddContact(&con);
break;
case 2://delete
DeleteContact(&con);
break;
case 3://search
SearchContact(&con);
break;
case 4://modify
ModifyContact(&con);
break;
case 5://show
ShowContact(&con);
break;
case 6://remove
RemoveContant(&con);
break;
case 7://sort
SortContact(&con);
break;
case 0:
printf("退出通讯录\n");
break;
default:
printf("请重新输入正确的数字\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
contact.c
#include "contact.h"
//初始化通讯录
void InitContact(struct Contact* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, 100 * sizeof(struct PeoInfo));
}
//增加一个人的信息
void AddContact(struct Contact* pc)
{
assert(pc);
if (MAX == pc->sz)
{
printf("通讯录已满,无法添加信息\n");
return;
}
printf("请输入姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:");
scanf("%d", &pc->data[pc->sz].age);//数组名为首元素地址,因此非数组需要加上‘&‘符号
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("成功添加联系人\n");
}
//显示通讯录
void ShowContact(const struct Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s\t%-5s\t%-2s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-2d\t%-12s\t%-30s\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].addr);
}
}
//查找通讯录中是否存在此人
static int FindNamePeo(const struct Contact* pc, char* name)
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name))
return i;
}
return -1;
}
//查找通讯录中某个人的信息
void SearchContact(const struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要查找的人的姓名:>");
scanf("%s", &name);
int ret = FindNamePeo(pc, name);
if (-1 == ret)
{
printf("找不到此人信息\n");
return;
}
else
{
printf("%-20s\t%-5s\t%-2s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-5s\t%-2d\t%-12s\t%-30s\n",
pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].addr);
}
}
//删除通讯录中某一个人的信息
void DeleteContact(struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要删除的人的姓名:>");
scanf("%s", &name);
int ret = FindNamePeo(pc, name);
if (-1 == ret)
{
printf("找不到此人信息\n");
return;
}
else
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
pc->data[ret + i] = pc->data[ret + i + 1];
}
pc->sz--;
printf("成功删除信息\n");
}
}
//修改通讯录中某一个人的信息
void ModifyContact(struct Contact* pc)
{
assert(pc);
char name[MAX_NAME];
printf("请输入要修改信息的人的姓名:>");
scanf("%s", &name);
int ret = FindNamePeo(pc, name);
if (-1 == ret)
{
printf("找不到此人信息\n");
return;
}
else
{
printf("请输入姓名:");
scanf("%s", pc->data[ret].name);
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄:");
scanf("%d", &pc->data[ret].age);
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
}
printf("成功修改信息\n");
}
//清空所有联系人
void RemoveContant(struct Contact* pc)
{
assert(pc);
InitContact(pc);
printf("成功清除所有联系人\n");
}
//以年龄作排序
int CmpByAge(const void* e1, const void* e2)
{
return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//以姓名作排序
int CmpByName(const void* e1, const void* e2)
{
return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
//排序通讯录(姓名)
void SortContact(struct Contact* pc)
{
assert(pc);
qsort(pc->data, pc->sz, sizeof(struct PeoInfo), CmpByName);
}