通讯录的实现:

正文开始@Assassin

目录:

  • 通讯录的实现:
    • 1. 创建基本信息结构体:
    • 2. 创建通讯录结构体:
    • 3. 初始化通讯录:
    • 4. 添加联系人信息:
    • 5. 查找联系人信息:
    • 6. 删除联系人信息:
    • 7. 查找指定联系人并打印其信息:
    • 8. 修改联系人信息:
    • 9. 显示通讯录全部联系人信息:
    • 10. 按联系人名字排序:
    • 11. 清空通讯录信息:
    • 12. 源代码:
      • 12.1 contact.h:
      • 12.2 contact.cpp:
      • 12.3 test.cpp:
    • 结果展示:
    • see you next blog~~

1. 创建基本信息结构体:

首先,通讯录中每个联系人的信息至少包括:姓名、年龄、性别、电话、住址等。我们可以将这些内容定义为一个结构体,因为每个联系人的信息都有这几个要素:结构体PeoInfo包含一个人的基本信息。

struct PeoInfo
{char name[15];  //姓名int age;    //年龄char sex[5];  //性别int tele[12];  //电话char address[20];  //地址
};//每一个联系人的信息内容

2. 创建通讯录结构体:

当我们要操作通讯录中联系人的信息内容时,比如增删查改时,我们需要知道通讯录中的联系人是否已经到达上限,如果达到上限就无法再添加联系人。
为了方便管理,我们可以将 联系人信息通讯录中已有联系人个数,一同放入同一个结构体中,这样就避免了执行每个功能时都要相同地传入两个变量(联系人信息,已有联系人个数)。结构体Contact包含人的信息结构体PeoInfo和一个当前已有人数的变量size

struct Contact
{struct PeoInfo data[1000];//存放1000个联系人的信息int size;//记录当前已有联系人的个数
};

3. 初始化通讯录:

我们在写工程化的代码时,一定要自身有意识地去把一些简单的且会重复用到的操作封装成函数,这样既方便管理,让别人阅读起来也条理清晰。
像初始化这种操作,封装成一个Init函数,向外提供一个使用的接口就行了。

值得注意的是,在传参的时候,传的是结构体指针,而不是结构体变量。
我们知道,
传参也要创建局部变量和临时变量,意味着也要压栈,入栈出栈有时间和空间的开销,当一个结构过大时,传值操作就显得不太划算,所以以后传参时尽量传指针或引用。

by the way,这里用到了内存函数memset函数~~

点我跳转到cplusplus的memset介绍!!

把信息结构体空间初始化为0,把人数置为0。

//初始化通讯录
void InitContact(struct Contact* ps)
{memset(ps->data, 0, sizeof(ps->data));//将待用内存空间设置为0ps->size = 0;//设置通讯录最初只有0个元素
}

4. 添加联系人信息:

首先,进入该函数体我们就需要判断通讯录内联系人是否已达上限,达到上限则无法继续添加,如果未达上限,用户就可以输入待添加的联系人的信息,而我们可以通过传入的指针找到联系人信息应当存放在哪一块内存空间。
添加完成后一定要记得将size++,即通讯录中联系人个数++。

//添加一个联系人的信息
void AddContact(struct Contact* ps)
{if (ps->size == 1000){printf("通讯录已满,无法添加!\n");}//通讯录内联系人已达上限else{printf("请输入姓名:>");scanf("%s", ps->data[ps->size].name);printf("请输入年龄:>");scanf("%d", &(ps->data[ps->size].age));printf("请输入性别:>");scanf("%s", ps->data[ps->size].sex);printf("请输入电话:>");scanf("%s", ps->data[ps->size].tele);printf("请输入地址:>");scanf("%s", ps->data[ps->size].address);ps->size++;//通讯录中联系人个数+1printf("添加成功\n");}
}

5. 查找联系人信息:

strcmp函数来比较名字的字符是否相同来查找所对应的下标。

点我跳转到cplusplus的strcmp函数介绍!!

int FindByName(char* name,const struct Contact* ps)
{int i = 0;for (i = 0; i < ps->size; i++){if (strcmp(ps->data[i].name, name) == 0)return i;//找到了返回下标}return -1;//找不到的情况
}

6. 删除联系人信息:

首先,我们需要用户输入待删除联系人的名字,并在通讯录中调用实现过的FindByName函数查找是否存在该名字的联系人。如果找到了此人,我们将其信息进行删除。
删除的方法是从将要被删除的元素的后一个开始,依次向前覆盖,最后把size- -,这样便实现了删除(让其遍历不到想要的目标便就是删除)

//删除一个联系人的信息
void DeleteContact(struct Contact* ps)
{char name[15];printf("请输入要删除联系人的姓名:>");scanf("%s", name);//查找int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1//删除if (pos == -1){printf("查无此人\n");}else{int j = 0;for (j = pos; j < ps->size - 1; j++){ps->data[j] = ps->data[j + 1];}//从要删除的联系人位置开始,后一位联系人信息覆盖前一个联系人信息printf("删除成功\n");ps->size--;//通讯录中联系人个数-1}
}

7. 查找指定联系人并打印其信息:

我们也需要用户输入待查找联系人的名字,如果存在此人我们就将其信息打印出来。同样是调用FindByName,这充分体现了封装成函数的必要性

//查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps)
{char name[15];//保存名字printf("请输入要查找联系人的姓名:>");scanf("%s", name);int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1if (pos == -1){printf("查无此人\n");}else{printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",ps->data[pos].name,ps->data[pos].age,ps->data[pos].sex,ps->data[pos].tele,ps->data[pos].address);}//打印该联系人的信息内容
}

8. 修改联系人信息:

同理,还是调用FindByName找到指定联系人,修改信息也就是重新将信息录入一遍。

//修改指定联系人的信息
void ModifyContact(struct Contact* ps)
{char name[15];printf("请输入要修改的联系人的姓名:>");scanf("%s", name);int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1if (pos == -1){printf("查无此人\n");}else{printf("请输入姓名:>");scanf("%s", ps->data[pos].name);printf("请输入年龄:>");scanf("%d", &(ps->data[pos].age));printf("请输入性别:>");scanf("%s", ps->data[pos].sex);printf("请输入电话:>");scanf("%s", ps->data[pos].tele);printf("请输入地址:>");scanf("%s", ps->data[pos].address);printf("修改成功\n");}//修改联系人信息,即将该联系人信息重新录入
}

9. 显示通讯录全部联系人信息:

首先判断通讯录是否为空(如果没有联系人,那就没有打印的必要了)。如果通讯录不为空,我们首先打印一排信息栏,接下来循环size次(即联系人个数次),打印每个联系人的信息即可。

//打印通讯录中的全部信息
void ShowContact(const struct Contact* ps)
{if (ps->size == 0){printf("通讯录为空\n");}//通讯录中联系人个数为0else{printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");//打印信息栏int i = 0;for (i = 0; i < ps->size; i++){printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",ps->data[i].name,ps->data[i].age,ps->data[i].sex,ps->data[i].tele,ps->data[i].address);}//打印通讯录全部信息内容}
}

10. 按联系人名字排序:

这个排序功能我们可以借助于已有的qosrt函数进行排序,只需要写一个自定义的比较函数即可。把自己写的函数的地址传给qsort,函数的返回值>0,则ptr1指向的元素排在ptr2指向元素的后面,也就是从小到大排序,<0则反之。

点我跳转到cplusplus的qsort函数!!

//自定义的比较函数
int CmpByName(const void* ptr1, const void* ptr2)
{return strcmp((const char*)ptr1, (const char*)ptr2);//从小到大
}//通过名字排序通讯录中联系人的先后顺序
void SortContact(struct Contact* ps)
{qsort(ps->data, ps->size, sizeof(struct PeoInfo), CmpByName);//排序
}

在这里自己实现了一个基于bubble_sort的低仿qsort (qsort底层是快速排序,Quicksort)

static int Cmp_ByName(void* p1, void* p2)
{return strcmp(((struct PeoInfo*)p1)->name, ((struct PeoInfo*)p2)->name);
}//交换两个元素的内容(width,是一个元素所占内存空间的大小,单位是字节)
static void Swap(void* p1, void* p2, int width)
{//一个字节一个字节的交换while (width){char tmp = *(char*)p1;*(char*)p1 = *(char*)p2;*(char*)p2 = tmp;++(char*)p1;++(char*)p2;width--;}
}static void MyQsort(void* p, int sz, int width, int(*cmp)(void*, void*))
{int i = 0;int j = 0;int flag = 1;//flag为1是是已经排好序,为0是是还没排好序,先默认它为1//冒泡排序for (i = 0; i < sz - 1; i++)//sz个元素,一共要比较sz-1趟,每一趟排序好一个元素{for (j = 0; j < sz - 1 - i; j++)//每趟要两两比较当前未排好序的元素个数-1次{if (cmp((char*)p + (j*width), (char*)p + ((j + 1)*width)) > 0)//判断是否要交换两个元素(既判断前一个元素的名字是否大于后一个元素的名字){Swap((char*)p + (j*width), (char*)p + ((j + 1)*width), width);//交换两个成员的位置flag = 0;//已经判断这次是无序了,所以flag=0}}if (flag == 1)//若一趟两两比较下来flag仍然=1,则数组肯定有序了,跳出冒泡排序{break;}}
}

11. 清空通讯录信息:

调用初始化函数Init来清空成员信息。

void ClearContact(struct Contact* pc)
{InitContact(pc);printf("清空通讯录成功!\n");
}

12. 源代码:

12.1 contact.h:

#define MAX 1000#define MAX_NAME 15
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDRESS 20#include <stdio.h>
#include <string.h>
#include <stdlib.h>enum Option
{EXIT,//0ADD,//1DELETE,//2SEARCH,//3MODIFY,//4SHOW,//5SORT,//6CLEAR//7
};//增加代码可读性struct PeoInfo
{char name[MAX_NAME];int age;char sex[MAX_SEX];int tele[MAX_TELE];char address[MAX_ADDRESS];
};//每一个联系人的信息内容//通讯录类型
struct Contact
{struct PeoInfo data[MAX];//存放1000个联系人的信息int size;//记录当前已有联系人的个数
};//初始化通讯录
void InitContact(struct Contact* ps);//添加一个联系人的信息
void AddContact(struct Contact* ps);//删除一个联系人的信息
void DeleteContact(struct Contact* ps);//查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps);//修改指定联系人的信息
void ModifyContact(struct Contact* ps);//打印通讯录中的全部信息
void ShowContact(const struct Contact* ps);//通过名字排序通讯录中联系人的先后顺序
void SortContact(struct Contact* ps);//清空通讯录信息
void ClearContact(struct Contact* pc);

12.2 contact.cpp:

#include "contact.h"//初始化通讯录
void InitContact(struct Contact* ps)
{memset(ps->data, 0, sizeof(ps->data));//将待用内存空间设置为0ps->size = 0;//设置通讯录最初只有0个元素
}//添加一个联系人的信息
void AddContact(struct Contact* ps)
{if (ps->size == MAX){printf("通讯录已满,无法添加!\n");}//通讯录内联系人已达上限else{printf("请输入姓名:>");scanf("%s", ps->data[ps->size].name);printf("请输入年龄:>");scanf("%d", &(ps->data[ps->size].age));printf("请输入性别:>");scanf("%s", ps->data[ps->size].sex);printf("请输入电话:>");scanf("%s", ps->data[ps->size].tele);printf("请输入地址:>");scanf("%s", ps->data[ps->size].address);ps->size++;//通讯录中联系人个数+1printf("添加成功\n");}
}//通过名字查找联系人,找到了返回下标,没找到返回-1
static int FindByName(char name[MAX_NAME],const struct Contact* ps)
{int i = 0;for (i = 0; i < ps->size; i++){if (strcmp(ps->data[i].name, name) == 0)return i;//找到了返回下标}return -1;//找不到的情况
}//删除一个联系人的信息
void DeleteContact(struct Contact* ps)
{char name[MAX_NAME];printf("请输入要删除联系人的姓名:>");scanf("%s", name);//查找int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1//删除if (pos == -1){printf("查无此人\n");}else{int j = 0;for (j = pos; j < ps->size - 1; j++){ps->data[j] = ps->data[j + 1];}//从要删除的联系人位置开始,后一位联系人信息覆盖前一个联系人信息printf("删除成功\n");ps->size--;//通讯录中联系人个数-1}
}//查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps)
{char name[MAX_NAME];printf("请输入要查找联系人的姓名:>");scanf("%s", name);int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1if (pos == -1){printf("查无此人\n");}else{printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",ps->data[pos].name,ps->data[pos].age,ps->data[pos].sex,ps->data[pos].tele,ps->data[pos].address);}//打印该联系人的信息内容
}//修改指定联系人的信息
void ModifyContact(struct Contact* ps)
{char name[MAX_NAME];printf("请输入要修改的联系人的姓名:>");scanf("%s", name);int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1if (pos == -1){printf("查无此人\n");}else{printf("请输入姓名:>");scanf("%s", ps->data[pos].name);printf("请输入年龄:>");scanf("%d", &(ps->data[pos].age));printf("请输入性别:>");scanf("%s", ps->data[pos].sex);printf("请输入电话:>");scanf("%s", ps->data[pos].tele);printf("请输入地址:>");scanf("%s", ps->data[pos].address);printf("修改成功\n");}//修改联系人信息,即将该联系人信息重新录入
}//打印通讯录中的全部信息
void ShowContact(const struct Contact* ps)
{if (ps->size == 0){printf("通讯录为空\n");}//通讯录中联系人个数为0else{printf("%-15s\t%-4s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址");//打印信息栏int i = 0;for (i = 0; i < ps->size; i++){printf("%-15s\t%-4d\t%-5s\t%-12s\t%-20s\n",ps->data[i].name,ps->data[i].age,ps->data[i].sex,ps->data[i].tele,ps->data[i].address);}//打印通讯录全部信息内容}
}//自定义的比较函数
int CmpByName(const void* e1, const void* e2)
{return strcmp((const char*)e1, (const char*)e2);
}//通过名字排序通讯录中联系人的先后顺序
void SortContact(struct Contact* ps)
{qsort(ps->data, ps->size, sizeof(struct PeoInfo), CmpByName);//排序
}
//清空通讯录
void ClearContact(struct Contact* pc)
{InitContact(pc);printf("清空通讯录成功!\n");
}

12.3 test.cpp:

#include "contact.h"void Menu()
{printf("|-----------------------|\n");printf("|        contact        |\n");printf("|   1.Add     2.Delete  |\n");printf("|   3.Search  4.Modify  |\n");printf("|   5.Show    6.Sort    |\n");printf("|   7.Clear   0.Exit    |\n");printf("|-----------------------|\n");
} //打印菜单int main()
{int input = 0;//创建通讯录struct Contact con; //con就是通讯录,里面包含1000个元素的数组和size//初始化通讯录InitContact(&con);do{Menu();printf("请选择要进行操作的选项:>");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DELETE:DeleteContact(&con);break;case SEARCH:SreachContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:SortContact(&con);break;case CLEAR:ClearContact(&con);break;case EXIT:printf("退出通讯录\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);return 0;
}

结果展示:

  • 1.演示add


    其他功能也能很好地运行,自己试试吧~~

see you next blog~~

C语言实现支持增删查改的通讯录相关推荐

  1. 支持增删查改的简单Java Web通讯录详细教程【基于Mac OS+IDEA+Servlet+JDBC+Tomcat】

    本文将以Web版通讯录的形式介绍一个支持简单增删查改的Java Web项目,软硬件环境基于Macbook Air M2+macOS Ventura 13.1+IntelliJ IDEA 2022,技术 ...

  2. 【C++ 语言】vector 容器 ( 容器分类 | vector 声明 | vector 初始化 | vector 容器元素增删查改 )

    文章目录 序列式容器 vector 简介 vector ( 向量 ) 头文件 vector ( 向量 ) 声明及初始化 vector ( 向量 ) 添加元素 vector ( 向量 ) 查询元素 ve ...

  3. C语言实现顺序表(增删查改等数据管理)

    顺序表seqlist 小伙伴们,提到顺序表会想到什么呢? 数组?还是链表? 其实,数组和链表都是属于线性表,而链表在逻辑上是线性的,并非物理存储上也为线性:而数组无论在逻辑上还是物理存储上均为线性 所 ...

  4. 【数据结构】顺序表的增删查改 (C语言实现)

    文章目录 一.线性表 二.顺序表 1.什么是顺序表 2.顺序表的分类 三.动态顺序表的实现 1.结构的定义 2.顺序表的初始化 3.检查容量 4.在头部插入数据 5.在尾部插入数据 6.在指定位置插入 ...

  5. c语言单向循环链表实现增删,C语言单向非循环链表增删查改实现

    SList.h #ifndef _SLIST_H_ #define _SLIST_H_ #include#include#include// 1.无头单向非循环链表增删查改实现 typedef int ...

  6. 数据结构C语言实现顺序表——增删查改操作实现详解

    顺序表 顺序表是什么? 顺序表是将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示.实现增删查改的功能. 顺序表所需的头文件: #include<stdio.h> ...

  7. mysql 查询和修改组合_## 超详细MySQL常用语句,增删查改

    ## MySQL常用语句,增删查改,安装配置mysql服务 ***#新手博客,应届生,谢谢支持哟 记得点赞关注哟*** ***-----sql常见命令:--------*** 安装服务:mysqld ...

  8. 【TcaplusDB知识库】GO快速上手PB表的增删查改操作

    PROTOBUF说明 PROTO表是基于PROTOBUF协议设计的TcaplusDB表,PROTOBUF协议是Google开源的通用RPC通信协议,用于TcaplusDB存储数据的序列化.反序列化等操 ...

  9. 【数据结构】链表:带头双向循环链表的增删查改

    本篇要分享的内容是带头双向链表,以下为本片目录 目录 一.链表的所有结构 二.带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2. ...

最新文章

  1. java变量存储位置_java 中变量存储位置的区别
  2. Java中getResourceAsStream的用法
  3. 返回txt格式的文本使用编码 js_Node.js学习笔记第一天
  4. 消除python变量的值_SPSS变量值标签的批量设置、复制、显示及删除问题
  5. 基于Xml 的IOC 容器-载入<bean>元素
  6. 【牛客 - 330F】Applese 的QQ群(拓扑排序,二分)
  7. php正则匹配域名不包含端口_3分钟短文 | PHP极速匹配子字符串,你是怎么做的?...
  8. paip.提升用户体验与安全性----登录与权限流程总结
  9. SpringCloud从入门到精通——微服务注册中心
  10. 给Edge添加chrome主题
  11. Spring中的DataSource
  12. little endian c语言,endian.h这个头文件里面的宏可以直接用么?
  13. 不积跬步 无以至千里
  14. HTML5期末大作业:商城网站设计——仿唯品会购物商城(5页) 纯手写-高质量 HTML+CSS+JavaScript
  15. 国风虚拟人形象频频亮相,虚拟数字人为传统文化传播提供了新载体
  16. 华为防火墙(usg5500)区域间实验
  17. 开发脂肪秤方案PCBA设计
  18. 【众说区块链】公链是否一定要发币,Token到底应该怎么理解?
  19. 小红书KOC和KOL这两者怎样进行投放?
  20. 推荐五款装机必备的常用软件

热门文章

  1. 王一博、张艺兴等多位明星起诉医美平台更美App
  2. 小米屏下摄像头专利曝光!或为小米mix4准备?
  3. 王思聪5亿投资神话破灭?旗下普思资本股权遭冻结,冻结期3年
  4. 华为Mate30、iPhone11、小米9 Pro 到底怎么选?
  5. 骁龙865确定:年底发布 支持5G!
  6. 极客修回应“以次充好”报道:内部已经展开调查
  7. 黑鲨游戏手机2 Pro跑分曝光:搭载骁龙855 Plus实锤
  8. 网红第一股上市首日暴跌37% “为人低调”王思聪评价:公司本身有问题
  9. 腾讯、网易、新浪新闻网站爬虫编写记录及评论格式分析
  10. c++ websocket 客户端