通讯录
- 前言
- 1.初始化通讯录
- 2.SHOW展示通讯录
- 3.ADD添加联系人的函数
- 4.DEL删除联系人的函数
- 5.SEARCH查找联系人的函数
- 6.MODIFY修改联系人的函数
- 7.销毁通讯录
- 8.整体代码展示
- 1.头文件"contact.h"
- 2.源文件"contact.c"
- 3.测试文件"test.c"
前言
那么好了好了,宝子们,之前学了进阶指针和动态内存管理,我们就拿通讯录来练练手吧,来吧开始整活!⛳️
因为我们之前就学过,写过类似的小游戏,都是将各个不同的功能封装成一个函数,我们依然延续这个做法。
1.初始化通讯录
//函数声明
//初始化
void Initcon(Contact* pc);
初始化静态版
//void Initcon(Contact* pc)
//{
// memset(pc->data, 0, sizeof(pc->data));
// pc->sz = 0;
//
//}
//动态的版本
void Initcon(Contact* pc)
{
assert(pc);
pc->data = (Info*)malloc(DEFAULT_SZ * sizeof(Info));
if (pc->data == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
//判断容量的函数
int CheckCapacity(Contact* pc);
int CheckCapacity(Contact* pc)//判断容量
{
if (pc->sz == pc->capacity)
{
Info* ptr = (Info*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(Info));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
return 1;
}
}
return 1;
}
2.SHOW展示通讯录
//SHOW展示
void ContactSHOW(Contact* pc);
//SHOW
void ContactSHOW(const Contact* pc)
{
assert(pc);
int i = 0;
//先加一个列标题
printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].home);
}
}
3.ADD添加联系人的函数
为什么添加联系人还有静态版和动态版的?因为静态版就是你固定了这个空间的大小不能再增加,如果动态版的话,它是像弹簧一样有弹性的,你要多大我就开辟多大,要多小我就开辟多小。所以说我们都是先学完动态内存管理和结构体和指针这一块才来写通讯录的。
ADD静态
//void ContactADD(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通讯录爆满!无法添加\n");
// return;
// }
//
// puts("请输入姓名:");
// scanf("%s", pc->data[pc->sz].name);
// puts("请输入性别:");
// scanf("%s", pc->data[pc->sz].sex);
// puts("请输入年龄:");
// scanf("%d", &(pc->data[pc->sz].age));
// puts("请输入电话:");
// scanf("%s", pc->data[pc->sz].tele);
// puts("请输入住址:");
// scanf("%s", pc->data[pc->sz].home);
//
// pc->sz++;
// printf("联系人增加成功!\n");
//}
//动态的版本
void ContactADD(Contact* pc)
{
assert(pc);
if (0 == CheckCapacity(pc))
{
return;
}
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].home);
pc->sz++;
printf("成功增加联系人\n");
}
4.DEL删除联系人的函数
在进行删除联系人,查找联系人和修改联系人的时候,我们都需要先找到这个联系人所在的位置,所以说这以下三种方法都要用一个封装find的函数。
//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到了直接返回i
}
return -1;//找不到
}
//DEL删除
void ContactDEL(Contact* pc);
//DEL
void ContactDEL(Contact* pc)
{
assert(pc);
//为空
if (pc->sz == 0)
{
printf("通讯录为空,无法删除!\n");
return;
}
//确定你要删除谁?
printf("输入你要删除人的名字:>");
char name[MAX_NAME] = { 0 };
scanf("%s", name);
找到你要删除人的名字
//int i = 0;
//int del = 0;//目的是做标记:记下删除人的下标位置
//int flag = 0;//另一个flag的原因是,如果要删除的人根本就不存在。
//for (i = 0; i < pc->sz; i++)
//{
// if (strcmp(pc->data[i].name, name) == 0)
// {
// del = i;
// flag = 1;
// break;
// }
// if (flag == 0)
// {
// puts("要删除的人根本就不存在!\n");
// return;
// }
//}
//找到你要删除人的名字
int i = 0;
//目的是做标记:记下删除人的下标位置
//封装一个Find函数
int del = FindByName(pc, name);//把整个通讯录和要删除人的名字传过去
if (del == -1)
{
printf("所要查找的联系人不存在!\n");
return;
}
//(覆盖式删除)
for (i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除联系人成功!\n");
}
5.SEARCH查找联系人的函数
//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到了直接返回i
}
return -1;//找不到
}
//SEARCH
void ContactSearch(Contact* pc)
{
assert(pc);
//输入你要查找的人
char name[MAX_NAME] = { 0 };
printf("输入你要查找的人\n");
scanf("%s", &name);
//调用查找函数
int pos = FindByName(pc, name);//position位置
if (pos == -1)
{
printf("找不到了\n");
return;
}
else
{
//直接粘贴SHOW函数中的:打印数据
//先加一个列标题
printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
pc->data[pos].name,
pc->data[pos].sex,
pc->data[pos].age,
pc->data[pos].tele,
pc->data[pos].home);
}
}
6.MODIFY修改联系人的函数
//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到了直接返回i
}
return -1;//找不到
}
//MODIFY修改
void ContactModify(Contact* pc);
//MODIFY
void ContactModify(Contact* pc)
{
assert(pc);
//输入你要修改的人
char name[MAX_NAME] = { 0 };
printf("输入你要修改的人\n");
scanf("%s", &name);
//调用查找函数
int pos = FindByName(pc, name);//position位置
if (pos == -1)
{
printf("找不到了\n");
return;
}
else
{
puts("请输入姓名:");
scanf("%s", pc->data[pos].name);
puts("请输入性别:");
scanf("%s", pc->data[pos].sex);
puts("请输入年龄:");
scanf("%d", &(pc->data[pos].age));
puts("请输入电话:");
scanf("%s", pc->data[pos].tele);
puts("请输入住址:");
scanf("%s", pc->data[pos].home);
}
printf("修改成功!\n");
}
7.销毁通讯录
//销毁通讯录
void DestroyContact(Contact* pc);
void DestroyContact(Contact* pc)
{
free(pc->data);//直接free
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
8.整体代码展示
在这里我们还是用到了三个窗口文件,一个是头文件“contact.h”,一个是源文件"contact.c",一个是测试文件"test.c"。
1.头文件"contact.h"
头文件里面定义了许多宏,是为了修改方便,以后大家要常用这种方法。
#pragma once
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_HOME 20
#define DEFAULT_SZ 3//初始化默认sz为3个
#define INC_SZ 2//每次扩容2个
//一个人的所有信息
typedef struct info
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
int tele[MAX_TELE];
char home[MAX_HOME];
}Info;
//通讯录
//静态版
//typedef struct contact
//{
// Info data[MAX];
// int sz;
//}Contact;
//动态版
typedef struct contact
{
Info* data;//指向了存放数据的空间
int sz;//记录的当前放的有效元素的个数
int capacity;//通讯录当前的最大容量
}Contact;
//设置这个枚举是为了让读者更好地理解零代表退出,1代表添加,2代表删除,3代表查找,4代表修改,5代表显示,6代表排序。因为这是枚举的优点!!!
enum OPTION
{
EXIT,//默认为0,下面的按顺序:1,2,3,4,5,6......
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
//函数声明
//初始化
void Initcon(Contact* pc);
//ADD添加
void ContactADD(Contact* pc);
//SHOW展示
void ContactSHOW(Contact* pc);
//DEL删除
void ContactDEL(Contact* pc);
//SEARCH查找
void ContactSearch(Contact* pc);
//MODIFY修改
void ContactModify(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
2.源文件"contact.c"
#include "contact.h"
初始化静态版
//void Initcon(Contact* pc)
//{
// memset(pc->data, 0, sizeof(pc->data));
// pc->sz = 0;
//
//}
//动态的版本
void Initcon(Contact* pc)
{
assert(pc);
pc->data = (Info*)malloc(DEFAULT_SZ * sizeof(Info));
if (pc->data == NULL)
{
perror("InitContact");
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
int CheckCapacity(Contact* pc);
int CheckCapacity(Contact* pc)//判断容量
{
if (pc->sz == pc->capacity)
{
Info* ptr = (Info*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(Info));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
return 1;
}
}
return 1;
}
ADD静态
//void ContactADD(Contact* pc)
//{
// assert(pc);
// if (pc->sz == MAX)
// {
// printf("通讯录爆满!无法添加\n");
// return;
// }
//
// puts("请输入姓名:");
// scanf("%s", pc->data[pc->sz].name);
// puts("请输入性别:");
// scanf("%s", pc->data[pc->sz].sex);
// puts("请输入年龄:");
// scanf("%d", &(pc->data[pc->sz].age));
// puts("请输入电话:");
// scanf("%s", pc->data[pc->sz].tele);
// puts("请输入住址:");
// scanf("%s", pc->data[pc->sz].home);
//
// pc->sz++;
// printf("联系人增加成功!\n");
//}
//动态的版本
void ContactADD(Contact* pc)
{
assert(pc);
if (0 == CheckCapacity(pc))
{
return;
}
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].home);
pc->sz++;
printf("成功增加联系人\n");
}
//SHOW
void ContactSHOW(const Contact* pc)
{
assert(pc);
int i = 0;
//先加一个列标题
printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
for (i = 0; i < pc->sz; i++)
{
printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].tele,
pc->data[i].home);
}
}
//封装一个Find函数
int FindByName(Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;//找到了直接返回i
}
return -1;//找不到
}
//DEL
void ContactDEL(Contact* pc)
{
assert(pc);
//为空
if (pc->sz == 0)
{
printf("通讯录为空,无法删除!\n");
return;
}
//确定你要删除谁?
printf("输入你要删除人的名字:>");
char name[MAX_NAME] = { 0 };
scanf("%s", name);
找到你要删除人的名字
//int i = 0;
//int del = 0;//目的是做标记:记下删除人的下标位置
//int flag = 0;//另一个flag的原因是,如果要删除的人根本就不存在。
//for (i = 0; i < pc->sz; i++)
//{
// if (strcmp(pc->data[i].name, name) == 0)
// {
// del = i;
// flag = 1;
// break;
// }
// if (flag == 0)
// {
// puts("要删除的人根本就不存在!\n");
// return;
// }
//}
//找到你要删除人的名字
int i = 0;
//目的是做标记:记下删除人的下标位置
//封装一个Find函数
int del = FindByName(pc, name);//把整个通讯录和要删除人的名字传过去
if (del == -1)
{
printf("所要查找的联系人不存在!\n");
return;
}
//(覆盖式删除)
for (i = del; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除联系人成功!\n");
}
//SEARCH
void ContactSearch(Contact* pc)
{
assert(pc);
//输入你要查找的人
char name[MAX_NAME] = { 0 };
printf("输入你要查找的人\n");
scanf("%s", &name);
//调用查找函数
int pos = FindByName(pc, name);//position位置
if (pos == -1)
{
printf("找不到了\n");
return;
}
else
{
//直接粘贴SHOW函数中的:打印数据
//先加一个列标题
printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "住址");
printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\t\n",
pc->data[pos].name,
pc->data[pos].sex,
pc->data[pos].age,
pc->data[pos].tele,
pc->data[pos].home);
}
}
//MODIFY
void ContactModify(Contact* pc)
{
assert(pc);
//输入你要修改的人
char name[MAX_NAME] = { 0 };
printf("输入你要修改的人\n");
scanf("%s", &name);
//调用查找函数
int pos = FindByName(pc, name);//position位置
if (pos == -1)
{
printf("找不到了\n");
return;
}
else
{
puts("请输入姓名:");
scanf("%s", pc->data[pos].name);
puts("请输入性别:");
scanf("%s", pc->data[pos].sex);
puts("请输入年龄:");
scanf("%d", &(pc->data[pos].age));
puts("请输入电话:");
scanf("%s", pc->data[pos].tele);
puts("请输入住址:");
scanf("%s", pc->data[pos].home);
}
printf("修改成功!\n");
}
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
3.测试文件"test.c"
#include <stdio.h>
#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");
}
void test()
{
//首先我得有个通讯录
Contact con;
//初始化通讯录
Initcon(&con);
int input = 0;
do
{
menu();
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case ADD:
ContactADD(&con);
break;
case DEL:
ContactDEL(&con);
break;
case SEARCH:
ContactSearch(&con);
break;
case MODIFY:
ContactModify(&con);
break;
case SHOW:
ContactSHOW(&con);
break;
case SORT:
//排序?qsort
//按照姓名?
//按照年龄?......
break;
case EXIT:
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
break;
};
} while (input);
}
int main()
{
test();
return 0;
}
注意:
- 运用枚举,可以增加代码的可读性,避免自己写代码以及别人阅读代码时不明确0,1,2,3,4,5,6的具体意义。
- 用#define定义一些常用数据,如联系人个数1000,以便之后需要修改时只需修改一处,而不是修改全部用到1000的地方。
好了,今天的分享就到这里了
如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!