一.什么是通讯录
通讯录是一种用于存储联系人信息的工具或应用程序。它是一种电子化的地址簿,用于记录和管理个人、机构或组织的联系方式,如姓名、电话号码、电子邮件地址和邮寄地址等。通讯录的目的是方便用户在需要时查找和联系他人。
通讯录通常以列表或表格的形式呈现,每个条目代表一个联系人。用户可以根据联系人的姓名、公司、职位或其他标识符来组织和排序通讯录。随着技术的发展,通讯录也可以与其他应用程序、设备或云服务同步,以确保联系人信息的备份和共享。
通讯录在个人生活和商业环境中都非常有用。个人可以使用通讯录存储家庭成员、朋友、同事和其他重要联系人的信息,以便随时与他们保持联系。在商业环境中,通讯录可以用于管理客户、供应商、合作伙伴和员工的联系信息,以便进行业务沟通和合作。
现代的通讯录应用程序通常具有许多高级功能,如快速搜索、批量导入和导出、分组管理、标签和备注、生日提醒、备份和恢复等。这些功能使通讯录更加强大和便捷,满足用户日常联系和管理联系人的需求。
二.通讯录的功能(简易)
1.允许用户添加、编辑和删除联系人信息,包括姓名、电话号码、电子邮件地址、邮寄地址等。
2.快速搜索:提供快速搜索功能,让用户可以根据姓名、公司、职位或其他标识符快速查找特定的联系人。
三.通讯录的函数实现
关于顺序表的补充:
typedef PeoInfo SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SL;
用户的信息:
//前置声明
struct SeqList;
typedef struct SeqList contact;
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
实现通讯录项目需要的代码比较多,我们要使用分文件编写。具体内容我就不再赘述了,如果你还有疑问,可以去看我之前发的扫雷项目。
还有要注意的是此项目是基于顺序表封装,如果对顺序表有疑问,请看我的上一篇文章。
1.初始化联系人列表
程序开始时,可以初始化一个空的联系人列表。InitContact(contact* con)
:初始化通讯录函数。它接受一个指向contact
结构体的指针,通过调用SLInit
函数初始化通讯录列表,并打印初始化成功的消息。
//初始化通讯录
void SLInit(SL* ps)
{
assert(ps);
ps->a = (SLDataType*)malloc(INIT_CAPACITY * sizeof(SLDataType));
assert(ps->a);
ps->size = 0;
ps->capacity = INIT_CAPACITY;
}
void InitContact(contact* con)
{
SLInit(con);
printf("通讯录初始化成功!\n");
}
2.添加联系人
用户可以输入联系人的姓名和电话号码,程序将该联系人添加到列表中。AddContact(contact* con)
:添加通讯录数据函数。它接受一个指向contact
结构体的指针,通过用户输入获取姓名、年龄、性别、电话和地址信息,并调用SLPushBack
函数将该联系人信息添加到通讯录列表中,最后打印添加成功的消息。
//添加通讯录数据
void AddContact(contact* con)
{
PeoInfo x = { 0 };
printf("请输入姓名\n");
scanf("%s", x.name);
printf("请输入年龄\n");
scanf("%d", &x.age);
printf("请输入性别\n");
scanf("%s", x.sex);
printf("请输入电话\n");
scanf("%s", x.tel);
printf("请输入地址\n");
scanf("%s", x.addr);
SLPushBack(con, x);
printf("添加成功!\n");
}
3.删除联系人
用户可以输入要删除的联系人的姓名,程序将在列表中查找并删除该联系人的信息。DelContact(contact* con)
:删除通讯录数据函数。它接受一个指向contact
结构体的指针,通过将通讯录列表的大小减1来删除最后一个联系人的信息,并打印删除成功的消息。
//删除通讯录数据
void DelContact(contact* con)
{
(con->size)--;
printf("删除成功!\n");
}
4.显示联系人列表
程序可以显示当前联系人列表中的所有联系人及其电话号码。ShowContact(contact* con)
:展示通讯录数据函数。它接受一个指向contact
结构体的指针,通过遍历通讯录列表,逐个打印联系人的姓名、年龄、性别、电话和地址信息,并打印已全部显示的消息。
/展示通讯录数据
void ShowContact(contact* con)
{
assert(con);
printf("姓名 年龄 性别 电话 地址\n");
for (int i = 0; i < con->size; i++)
{
printf("%-4s ", ((con->a) + i)->name);
printf("%-4d ", ((con->a) + i)->age);
printf("%-4s ", ((con->a) + i)->sex);
printf("%-4s ", ((con->a) + i)->tel);
printf("%-4s ", ((con->a) + i)->addr);
printf("\n");
}
printf("已全部显示!\n");
}
5.查找联系人
用户可以输入要查找的联系人的姓名,程序将在列表中查找并显示该联系人的信息。FindContactname(contact* con)
:查找通讯录数据函数。它接受一个指向contact
结构体的指针,通过用户输入要查找的联系人姓名,然后在通讯录列表中查找匹配的姓名并返回其索引值(下标)。如果找到了匹配的联系人,返回其下标;如果未找到匹配的联系人,返回-1。
//查找通讯录数据
int FindContactname(contact* con)
{
assert(con);
printf("请输入联系人的名字\n");
char j[NAME_MAX] = { 0 };
scanf("%s", j);
for (int i = 0; i < (con->size); i++)
{
if (strcmp(((con->a) + i)->name, j) == 0)
return i;
}
return -1;
}
6.修改联系人
用户可以输入要修改的联系人的姓名,程序将在列表中查找并允许用户修改该联系人的信息。ModifyContact(contact* con)
:修改通讯录数据函数。它接受一个指向contact
结构体的指针,首先调用FindContactname
函数查找要修改的联系人的下标,如果找到了匹配的联系人,则通过用户输入更新该联系人的姓名、年龄、性别、电话和地址信息。如果未找到匹配的联系人,打印未找到的消息。
//修改通讯录数据
void ModifyContact(contact* con)
{
int i = FindContactname(con);
if (i >= 0)
{
printf("找到了,下标是%d\n", i);
printf("请输入姓名\n");
scanf("%s", ((con->a) + i)->name);
printf("请输入年龄\n");
scanf("%d", &(((con->a) + i)->age));
printf("请输入性别\n");
scanf("%s", ((con->a) + i)->sex);
printf("请输入电话\n");
scanf("%s", ((con->a) + i)->tel);
printf("请输入地址\n");
scanf("%s", ((con->a) + i)->addr);
printf("\n");
}
else
printf("未找到!\n");
}
7.销毁联系人列表
程序结束时,可以销毁联系人列表,释放内存空间。DestroyContact(contact* con)
:销毁通讯录数据函数。它接受一个指向contact
结构体的指针,通过调用SLDestroy
函数销毁通讯录列表,并打印销毁成功的消息。
void SLDestroy(SL* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
//销毁通讯录数据
void DestroyContact(contact* con)
{
SLDestroy(con);
printf("销毁成功!\n");
}
四.通讯录的菜单实现
在main()
函数中,首先调用menu()
函数打印菜单选项,然后通过动态内存分配创建一个contact
结构体的指针p
,并调用InitContact()
函数初始化通讯录。
接下来,通过一个do-while
循环,根据用户输入的选项执行相应的操作。根据用户输入的选项,调用相应的函数,如AddContact()
添加联系人、DelContact()
删除联系人、FindContactname()
查找联系人、ModifyContact()
修改联系人和ShowContact()
显示通讯录。
循环终止条件是用户输入0,即选择退出通讯录。在循环结束后,调用DestroyContact()
函数销毁通讯录,并打印成功退出通讯录的消息。
此程序通过菜单和用户输入实现了对通讯录的基本操作。用户可以根据菜单选项选择要执行的操作,直到选择退出通讯录为止。
#include"contact.h"
#include"SL.h"
void menu()
{
printf("*************************\n");
printf("1.添加联系人 2.删除联系人\n");
printf("3.查找联系人 4.修改联系人\n");
printf("5.显示通讯录 0.退出通讯录\n");
printf("*************************\n");
}
int main()
{
menu();
int i = 0;
contact* p = (contact*)malloc(sizeof(contact));
InitContact(p);
do {
printf("请输入\n");
scanf("%d", &i);
switch (i)
{
case 1:
{
AddContact(p);
break;
}
case 2:
{
DelContact(p);
break;
}
case 3:
{
int k = FindContactname(p);
if (k >= 0)
{
printf("找到了,下标是%d\n", k);
printf("姓名 年龄 性别 电话 地址\n");
printf("%-4s ", ((p->a) + k)->name);
printf("%-4d ", ((p->a) + k)->age);
printf("%-4s ", ((p->a) + k)->sex);
printf("%-4s ", ((p->a) + k)->tel);
printf("%-4s ", ((p->a) + k)->addr);
printf("\n");
}
else
printf("未找到!\n");
break;
}
case 4:
{
ModifyContact(p);
break;
}
case 5:
{
ShowContact(p);
break;
}
default:
{
printf("输入错误,请重新输入!\n");
break;
}
}
} while (i);
DestroyContact(p);
printf("已成功退出通讯录\n");
return 0;
}
五.通讯录的测试
1.菜单的显示
2.添加联系人
3.删除联系人
4.查找联系人
5.修改联系人
6.显示通讯录
7.删除通讯录
六.通讯录项目的源码
1.顺序表的源码
1.SL.h
SL.h
头文件定义了SL
数据结构,表示序列列表。它还定义了初始化、销毁、检查容量、推入和弹出列表中的元素、在特定位置插入和删除元素、以及更改给定位置的元素的函数原型。
#pragma once
#define INIT_CAPACITY 4
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"contact.h"
typedef PeoInfo SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SL;
void SLInit(SL* ps);
void SLDestroy(SL* ps);
//void SLPrint(SL* ps);
void SLCheckCapacity(SL* ps);
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
//int SLFind(SL* ps, SLDataType x);
void SLChange(SL* ps, int pos, SLDataType x);
2.Sl.c
Sl.c文件包含了有关顺序表的函数,这些函数实现了一个简单的单链表数据结构,用于管理通讯录数据。通过链表操作函数,可以向链表中添加元素、删除元素、获取元素以及获取链表的大小。这些函数与contact.c
文件中的功能函数一起使用,实现了对通讯录数据的管理和操作。
#include"SL.h"
void SLInit(SL* ps)
{
assert(ps);
ps->a = (SLDataType*)malloc(INIT_CAPACITY * sizeof(SLDataType));
assert(ps->a);
ps->size = 0;
ps->capacity = INIT_CAPACITY;
}
void SLDestroy(SL* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
//void SLPrint(SL* ps)
//{
// assert(ps);
// for (int i = 0; i < ps->size; i++)
// {
// printf("%d ", *((ps->a) + i));
// }
// printf("\n");
//}
void SLCheckCapacity(SL* ps)
{
assert(ps);
SLDataType* j = NULL;
if (ps->size >= ps->capacity)
{
j = realloc(ps->a, 2 * (ps->capacity) * sizeof(SLDataType));
if (j)
{
free(ps->a);
ps->a = NULL;
perror("fault:");
}
else {
ps->a = j;
}
}
assert(ps->a);
}
void SLPushBack(SL* ps, SLDataType x)
{
SLCheckCapacity(ps);
*((ps->a) + (ps->size)) = x;
(ps->size)++;
}
void SLPopBack(SL* ps)
{
(ps->size)--;
}
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
for (int i = (ps->size) - 1; i > 0; i--)
{
*((ps->a) + i) = *((ps->a) + i - 1);
}
*(ps->a) = x;
(ps->size)++;
}
void SLPopFront(SL* ps)
{
assert(ps);
for (int i = 0; i < ((ps->size) - 1); i++)
{
*((ps->a) + i) = *((ps->a) + i + 1);
}
(ps->size)--;
}
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(pos <= ps->size + 1);
assert(ps);
SLCheckCapacity(ps);
for (int i = (ps->size) - 1; i > pos; i--)
{
*((ps->a) + i) = *((ps->a) + i - 1);
}
*(ps->a + pos) = x;
(ps->size)++;
}
void SLErase(SL* ps, int pos)
{
assert(pos <= ps->size + 1);
assert(ps);
for (int i = pos; i < ((ps->size) - 1); i--)
{
*((ps->a) + i) = *((ps->a) + i + 1);
}
(ps->size)--;
}
//int SLFind(SL* ps, SLDataType x)
//{
// assert(ps);
// for (int i = 0; i < (ps->size); i++)
// {
// if (*((ps->a) + i) == x)
// return i;
// }
// return -1;
//}
void SLChange(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos <= ps->capacity - 1);
*((ps->a) + pos) = x;
}
2.通讯录的源码
1.contact.h
contact.h
头文件定义了用于管理联系人列表的数据结构和函数原型。它包括了SL.h
头文件,该头文件定义了序列列表的函数和数据结构。
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#define NAME_MAX 100
#define SEX_MAX 7
#define TEL_MAX 12
#define ADDR_MAX 100
#include<string.h>
//前置声明
struct SeqList;
typedef struct SeqList contact;
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//初始化通讯录
void InitContact(contact* con);
//添加通讯录数据
void AddContact(contact* con);
//删除通讯录数据
void DelContact(contact* con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
int FindContactname(contact* con);
//修改通讯录数据
void ModifyContact(contact* con);
//销毁通讯录数据
void DestroyContact(contact* con);
2.contact.c
contact.c文件包含了许多功能函数共同实现了对通讯录数据的初始化、添加、删除、展示、查找、修改和销毁的操作。相应的函数实现了对通讯录数据结构的操作,并通过调用SL.h
中的函数实现了具体的链表操作。
#include"contact.h"
#include"SL.h"
//初始化通讯录
void InitContact(contact* con)
{
SLInit(con);
printf("通讯录初始化成功!\n");
}
//添加通讯录数据
void AddContact(contact* con)
{
PeoInfo x = { 0 };
printf("请输入姓名\n");
scanf("%s", x.name);
printf("请输入年龄\n");
scanf("%d", &x.age);
printf("请输入性别\n");
scanf("%s", x.sex);
printf("请输入电话\n");
scanf("%s", x.tel);
printf("请输入地址\n");
scanf("%s", x.addr);
SLPushBack(con, x);
printf("添加成功!\n");
}
//删除通讯录数据
void DelContact(contact* con)
{
(con->size)--;
printf("删除成功!\n");
}
//展示通讯录数据
void ShowContact(contact* con)
{
assert(con);
printf("姓名 年龄 性别 电话 地址\n");
for (int i = 0; i < con->size; i++)
{
printf("%-4s ", ((con->a) + i)->name);
printf("%-4d ", ((con->a) + i)->age);
printf("%-4s ", ((con->a) + i)->sex);
printf("%-4s ", ((con->a) + i)->tel);
printf("%-4s ", ((con->a) + i)->addr);
printf("\n");
}
printf("已全部显示!\n");
}
//查找通讯录数据
int FindContactname(contact* con)
{
assert(con);
printf("请输入联系人的名字\n");
char j[NAME_MAX] = { 0 };
scanf("%s", j);
for (int i = 0; i < (con->size); i++)
{
if (strcmp(((con->a) + i)->name, j) == 0)
return i;
}
return -1;
}
//修改通讯录数据
void ModifyContact(contact* con)
{
int i = FindContactname(con);
if (i >= 0)
{
printf("找到了,下标是%d\n", i);
printf("请输入姓名\n");
scanf("%s", ((con->a) + i)->name);
printf("请输入年龄\n");
scanf("%d", &(((con->a) + i)->age));
printf("请输入性别\n");
scanf("%s", ((con->a) + i)->sex);
printf("请输入电话\n");
scanf("%s", ((con->a) + i)->tel);
printf("请输入地址\n");
scanf("%s", ((con->a) + i)->addr);
printf("\n");
}
else
printf("未找到!\n");
}
//销毁通讯录数据
void DestroyContact(contact* con)
{
SLDestroy(con);
printf("销毁成功!\n");
}
3.test.c
代码中的main()
函数是程序的入口点。它显示一个菜单选项,用于管理联系人列表,并重复提示用户输入,直到用户选择退出程序。根据用户的输入,它调用相应的函数来执行所需的操作。
#include"contact.h"
#include"SL.h"
void menu()
{
printf("*************************\n");
printf("1.添加联系人 2.删除联系人\n");
printf("3.查找联系人 4.修改联系人\n");
printf("5.显示通讯录 0.退出通讯录\n");
printf("*************************\n");
}
int main()
{
menu();
int i = 0;
contact* p = (contact*)malloc(sizeof(contact));
InitContact(p);
do {
printf("请输入\n");
scanf("%d", &i);
switch (i)
{
case 1:
{
AddContact(p);
break;
}
case 2:
{
DelContact(p);
break;
}
case 3:
{
int k = FindContactname(p);
if (k >= 0)
{
printf("找到了,下标是%d\n", k);
printf("姓名 年龄 性别 电话 地址\n");
printf("%-4s ", ((p->a) + k)->name);
printf("%-4d ", ((p->a) + k)->age);
printf("%-4s ", ((p->a) + k)->sex);
printf("%-4s ", ((p->a) + k)->tel);
printf("%-4s ", ((p->a) + k)->addr);
printf("\n");
}
else
printf("未找到!\n");
break;
}
case 4:
{
ModifyContact(p);
break;
}
case 5:
{
ShowContact(p);
break;
}
default:
{
printf("输入错误,请重新输入!\n");
break;
}
}
} while (i);
DestroyContact(p);
printf("已成功退出通讯录\n");
return 0;
}