前言 : 在生活中我们经常会遇到通讯录的使用,比如存进一个新的联系人的信息,或者对其删除,修改,查找;那这些神奇的功能是如何实现的?我们不禁好奇。今天,这篇博文将教会大家实现一个静态的或者动态的通讯录,以后我们就可以靠自己实现一个通讯录啦 ~
1.静态通讯录讲解
1.1 静态通讯录的功能列表的实现(text.c)
1.1.1 菜单的实现
这里我们实现一个简易的功能菜单,运用print语句即可 功能有 1.新增联系人 2.删除联系人 3.查找指定联系人 4.修改指定联系人信息 5.展示目前存入的联系人 6.对联系人按照一定的标准排序 以及 0.退出通讯录
void menu()
{
printf("*******************************\n");
printf("**** 1.add 2.del *****\n");
printf("**** 3.search 4.modify *****\n");
printf("**** 5.show 6.sort *****\n");
printf("**** 0.exit *****\n");
printf("*******************************\n");
}
1.1.2 菜单功能的枚举
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
EXIT 从0开始向下递增,分别对应菜单上的各个功能,目的是为了下面的switch接口能更加方便直观看出各个功能,以防出错。
1.1.3 main函数的实现
这一块我们实现从键盘上输入各个数字代表不同功能,再实现循环输入, 代码如下:
int main()
{
int input = 0;
struct Contact con;
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 SHOW:
ShowContact(&con);
break;
case EXIT:
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
1.2 静态通讯录各个函数的声明包含 (contact.h)
1.2.1 #define 定义各个标号以及头文件的引用
#define DEFAULT_SZ 3
#define NAME_MAX 30
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000
分别定义了 默认存放联系人数量为3 (后面动态通讯录会使用到) 名字数组最大长度为 30‘ 性别数组最大长度为 5 电话数组最大长度为 15 地址数组最大长度为 30 静态通讯录能存放最大联系人为 1000
头文件的引用:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
引用整个工程所要使用到的函数头文件,避免重复引用(每个文件前面加上 #include "contact.h),这样就实现所有声明头文件放在一个头文件中,分开管理,提升工程书写效率;
1.2.2 定义联系人信息结构体
struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
1.2.3定义静态通讯录结构体
struct Contact
{
struct PeoInfo date[MAX];
int sz;
};
包含了可以存放1000个人信息的联系人结构体以及当前存放进去的有效联系人个数 sz ;
1.2.4 各个功能函数的声明
void InitContact(struct Contact* pc);
void Addcontact(struct Contact* pc);
void ShowContact(struct Contact*pc);
void DelContact(struct Contact* pc);
void SearchContact(struct Contact* pc);
void ModifyContact(struct Contact* pc);
void DestroyContact(struct Contact* pc);
1.3 功能函数的实现讲解 (contact.c)
1.3.1 静态通讯录初始化函数讲解
void InitContact(struct Contact* pc)
{
pc->sz = 0;
memset(pc->date, 0, MAX * sizeof(struct PeoInfo));
}
结构体传参,传的一般是结构体地址,结构体指针接受,实现对结构体本身的修改 。(传址调用) 初始化有效联系人个数sz为0; 用memset内存设置函数,将1000个联系人信息结构体初始化为0;
1.3.2 Add新增联系人函数的实现讲解
void Addcontact(struct Contact* pc)
{
struct Contact tmp = { 0 };
if (pc->sz == MAX)
{
printf("通讯录可用空间已满\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
printf("添加成功\n");
pc->sz++;
}
}
用pc->date[pc->sz].xxx找到各个联系人信息位置,将信息存入 后有效联系人个数sz++; 实现对下一个联系人信息的存放
1.3.3 展示当前存入的联系人信息函数讲解
void ShowContact(struct Contact* pc)
{
int i = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
"name", "age", "sex", "tele", "addr");
for (i = 0; i < pc->sz; i++)
{
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
printf("%15s\t%5s\t%8s\t%15s\t%30s\n", “name”, “age”, “sex”, “tele”, “addr”); 实现初始化联系人信息表头的域宽 接下来打印每一个数据即可;
1.3.4 通过姓名查找当前存放进去的联系人信息位置函数实现讲解
int FindContactByName(const struct Contact* pc, const char* name)
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
strcmp库函数实现对字符串的比较,相同的话返回数字0; 返回数字0即代表查找成功,此时返回位置 i 即可; 查找不成功返回-1;
1.3.5 删除指定联系人函数实现讲解
void DelContact(struct Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME_MAX] = {0};
printf("请输入要删除人的名字:>");
scanf("%s", name);
int pos=FindContactByName(pc, name);
if (pos == -1)
{
printf("指定的联系人不存在\n");
}
else
{
int j = 0;
for (j = pos; j<pc->sz-1; j++)
{
pc->date[j] = pc->date[j + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
相应讲解在代码中以注释形式给出;
1.3.6 查找指定联系人函数实现讲解
void SearchContact(const struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
"name", "age", "sex", "tele", "addr");
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
查找成功的话将此位置(pos)打印出即可,格式和增加联系人函数的类似;
1.3.7 修改指定联系人信息函数实现讲解
void ModifyContact(struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("要修改的联系人不存在\n");
}
else
{
printf("请输入新的名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入新的年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入新的性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入新的电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入新的地址:>");
scanf("%s", pc->date[pos].addr);
printf("修改成功\n");
}
}
查找指定联系人成功的话,将此位置(pos)对应的联系人信息修改即可, 格式依旧和新增联系人函数类似;
到此为止,静态通讯录各个模块实现讲解基本完毕; 我们大致可以看一下效果 ;
2.动态通讯录实现讲解
动态通讯录与静态通讯录实现上大致相同,我们就把不同的地方区分出来进行详细讲解 : 动态通讯录与静态通讯录区别就在于: 静态通讯录一开始就创建好一个可以存放1000个人信息的空间,存不满的话对内存浪费就会比较大; 而动态通讯录可以实现随着放入的联系人信息的增多而相应的增加内存空间,用malloc函数实现,这样对内存空间的浪费就避免了,是更好的实现方法,下面我们就对动态通讯录进行讲解 :
2.1 动态通讯录结构体实现
struct Contact
{
struct PeoInfo* date;
int sz;
int capacity;
};
实现一个 date结构体指针,指向联系人信息结构体 实现一个当前有效联系人信息个数 sz 实现一个当前通讯录最大联系人容量 capacity
2.2 初始化动态通讯录函数讲解
void InitContact(struct Contact* pc)
{
pc->sz = 0;
pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
pc->capacity = DEFAULT_SZ;
}
有效联系人个数sz制为0;
pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
malloc函数实现一开始动态内存开辟3个联系人空间大小,写法上 DEFAULT_SZ (元素个数:3)* sizeof(struct PeoInfo)(每个元素的大小) 返回开辟空间的地址,date结构体指针来接收;
一开始最大容量capacity制为 3 ;
2.3 动态通讯录新增联系人函数实现讲解
动态通讯录与静态通讯录不同就在新增联系人函数实现方式上有所变化, 其他函数一致保持不变 ;
void Addcontact(struct Contact* pc)
{
if (pc->sz == pc->capacity)
{
struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
if (ptr != NULL)
{
pc->date = ptr;
pc->capacity += 2;
printf("扩容成功\n");
}
else
{
return;
}
}
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
printf("添加成功\n");
pc->sz++;
}
struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
扩容代码讲解:如果空间满了就用realloc函数实现扩容,realloc函数的意思是扩容为xx,不是扩容xx ; realloc函数传入需要扩容的地址dete,扩容一次扩容+2个联系人空间,pc->capacity + 2,每个联系人大小为 sizeof(struct PeoInfo) ; 返回的地址强制类型转换为 (struct PeoInfo*) 存放在结构体指针 ptr 中 ; 其他讲解在代码中以注释形式给出 ;
2.4 退出(销毁动态开辟的内存空间)通讯录函数实现讲解
void DestroyContact(struct Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
}
释放+制空: free(pc->date); pc->date = NULL; 实现避免对内存空间的浪费使用 ; pc->sz = 0; pc->capacity = 0; 将有效联系人个数以及最大联系人个数制为 0 ; 退出通讯录 ;
3.整体工程源代码展示
3.1 text.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
printf("*******************************\n");
printf("**** 1.add 2.del *****\n");
printf("**** 3.search 4.modify *****\n");
printf("**** 5.show 6.sort *****\n");
printf("**** 0.exit *****\n");
printf("*******************************\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
int main()
{
int input = 0;
struct Contact con;
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 SHOW:
ShowContact(&con);
break;
case EXIT:
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
3.2 contact .c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void InitContact(struct Contact* pc)
{
pc->sz = 0;
pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
pc->capacity = DEFAULT_SZ;
}
void Addcontact(struct Contact* pc)
{
struct Contact tmp = { 0 };
if (pc->sz == MAX)
{
printf("通讯录可用空间已满\n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
printf("添加成功\n");
pc->sz++;
}
}
void ShowContact(struct Contact* pc)
{
int i = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
"name", "age", "sex", "tele", "addr");
for (i = 0; i < pc->sz; i++)
{
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
int FindContactByName(const struct Contact* pc, const char* name)
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(struct Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME_MAX] = {0};
printf("请输入要删除人的名字:>");
scanf("%s", name);
int pos=FindContactByName(pc, name);
if (pos == -1)
{
printf("指定的联系人不存在\n");
}
else
{
int j = 0;
for (j = pos; j<pc->sz-1; j++)
{
pc->date[j] = pc->date[j + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
void SearchContact(const struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
"name", "age", "sex", "tele", "addr");
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
void ModifyContact(struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("要修改的联系人不存在\n");
}
else
{
printf("请输入新的名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入新的年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入新的性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入新的电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入新的地址:>");
scanf("%s", pc->date[pos].addr);
printf("修改成功\n");
}
}
void DestroyContact(struct Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
}
3.3 contact.h
#pragma once
#define DEFAULT_SZ 3
#define NAME_MAX 30
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
struct Contact
{
struct PeoInfo* date;
int sz;
int capacity;
};
void InitContact(struct Contact* pc);
void Addcontact(struct Contact* pc);
void ShowContact(struct Contact*pc);
void DelContact(struct Contact* pc);
void SearchContact(struct Contact* pc);
void ModifyContact(struct Contact* pc);
void DestroyContact(struct Contact* pc);
4.尾声
|