手把手教你实现通讯录

简介: 手把手教你实现通讯录

整体构思

我们现在要实现一个通讯录 它应该有以下的功能

通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址

提供方法:

1.添加联系人信息

2.删除指定联系人信息

3.查找指定联系人信息

4.修改指定联系人信息

5.显示所有联系人信息

6.清空所有联系人

7.以名字排序所有联系人

首先和三子棋还有扫雷一样 我们要设计三个工程文件 一个头文件 一个实现文件 一个测试文件

实现这三个文件之后 我们开始设计菜单

然后按照上面的规律一步步实现这个通讯录的功能

一. 实现菜单

我们使用通讯录的功能肯定不是只是一次性的 需要多次使用

这样子的话就要求我们使用一个循环来设计

大体的设计模型代码如下

void memu()
{
  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()
{
  int input = 0;
  //创建通信录
  Contact con;
  //初始化通信录
  InitContact(&con);
 
 
  do
  {
    memu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      AddContact(&con);
      break;
    case 2:
      DelContact(&con);
      break;
    case 3:
      SearchContact(&con);
      break;
    case 4:
      ModityContact(&con);
      break;
    case 5:
      ShowContact(&con);
      break;
    case 6:
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  } while (input);
}
int main()
{
  test();
  return 0;
}

实现效果如下

二. 设计通讯录

我们要设计一个通讯录 首先要使用一个结构体来实现

这个结构体里面要有姓名 性别 年龄 住址等元素

并且这样的结构体要有100个 这样我们就可以使用一个结构体数组来设计

typedef struct PeoInfo
{
  char name[MAX_NEME];
  int age;
  char sex[MAX_SEX];
  char addr[MAX_ADDR];
  char tele[MAX_TELE];
}PeoInfo;

数组的大小我们定义一个宏来实现可更改大小

#define MAX 100
#define MAX_NEME 20
#define MAX_SEX 5
#define MAX_ADDR 30
#define MAX_TELE 12

这样子我们就设计好可以存放一百个人的结构体数组了

但是这个结构体还有可以优化的地方 我们需要一个数字来指向这个结构体的第n个元素

那么我们可以设计一个再大一点的结构体 代码如下

typedef struct Contact
{
  PeoInfo date[MAX];//存放人的信息
  int sz;//当前已经放的信息个数
}Contact;

现在我们需要初始化这个数组 将这个数组中的所有元素都设置为0

不知道大家还记不记得我们在上几篇博客中学习了几个函数 memset 这里我们可以使用一个memset来设计这个功能

实现代码如下

void InitContact(Contact* pc)
{
    assert(pc);
    pc->sz = 0;
    memset(pc->date, 0, sizeof(pc->date));
}

三. 添加联系人

添加联系人的时候我们首先要找到目前sz指向哪里

如果sz指向100的话 那么代表通讯录没有空名额了

打印没有空名额

如果没有指向100 这时候我们开始输入数据

** 这里要注意的是 date是一个数组 我们还必须指向里面的元素才可以**

代码表示如下

void AddContact(Contact* pc)
{
  assert(pc);
  if (pc->sz == MAX)
  {
    printf("通信录已满,无法添加\n");
    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].addr);
  printf("请输入电话:>");
  scanf("%s", pc->date[pc->sz].tele);
  pc->sz++;
 
}

四. 删除指定联系人

首先 我们肯定是根据名字来删除指定联系人的

首先 我们应该遍历整个数组

查找其中有没有符合这个名字的练习人

如果有的话 首先先打出来 再询问是否真的要删除 如果确定 删除之 如果不确定 取消之

int FindByName(Contact* pc, 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(Contact* pc)
{
  assert(pc);
  int i = 0;
  char name[MAX_NEME];
  if (pc->sz == 0)
  {
    printf("通讯录为空,无法删除\n");
  }
  printf("请输入要删除人的名字:>");
  scanf("%s", &name);
  int del = 0;
  //找到删除人的名字
  int ret = FindByName(pc, name);
  if (-1 == ret)
  {
    printf("要删除的人不存在\n");
  }
 
  //删除
  for (i = ret; i < pc->sz - 1; i++)
  {
    pc->date[i] = pc->date[i + 1];
  }
  pc->sz--;
  printf("删除成功\n");
}

实现代码如上

我们来测试一下

五. 查到指定联系人

我们沿用上面删除联系人的思路 如果找到这个联系人就打印他的所有信息

如果找不到就打印找不到

这个很简单 上面设计删除的时候代码就已经设计好了 代码如下

void SearchContact(const Contact* pc)
{
  char name[MAX_NEME] = { 0 };
  printf("请输入查找人的名字:>");
  scanf("%s", &name);
  int pos = FindByName(pc, name);
  if (-1 == pos)
  {
    printf("查找人的信息不存在\n");
    return ;
  }
  //打印信息
  printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");
  printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->date[pos].name,
      pc->date[pos].age,
      pc->date[pos].sex,
      pc->date[pos].addr,
      pc->date[pos].tele);
 
}

我们来看看效果

六. 修改指定联系人

这个的实现思路也很简单

首先查到到 然后依次修改就可以

 
void ModityContact(Contact* pc)
{
  assert(pc);
  char name[MAX_NEME] = { 0 };
  printf("请输入修改人的名字:>");
  scanf("%s", &name);
  int pos = FindByName(pc, name);
  if (-1 == pos)
  {
    printf("修改人的信息不存在\n");
    return;
  }
  //录入信息
  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].addr);
  printf("请输入电话:>");
  scanf("%s", pc->date[pos].tele);
 
  printf("修改完成\n");
}

七. 显示所有联系人

这个操作也很简单 上面查找联系人的时候遍历一遍就可以

实现代码如下

void ShowContact(const Contact* pc)
{
  assert(pc);
  int i = 0;
  printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");
  for (i = 0; i < pc->sz; i++)
  {
    printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->date[i].name,
      pc->date[i].age,
      pc->date[i].sex,
      pc->date[i].addr,
      pc->date[i].tele);
  }
}

八、按照名字排序

在我们前面讲解qsort的时候讲解了怎么按照名字排序 这里我们只要写一个比较函数 然后传递参数进去

就可以了

代码表示如下

int cmp(void* a, void* b)
{
  Contact* p1 = (Contact*)a;
  Contact* p2 = (Contact*)b;
  return strcmp(p1->date->name, p2->date->name);
}
 
void SortContact(Contact* pc)
{
 
  qsort(pc, pc->sz, sizeof(Contact*), cmp);
}

以上便是本文所有内容,如有错误请各位大佬不吝赐教,感谢留言

目录
相关文章
|
1月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
452 108
|
机器学习/深度学习 人工智能 自然语言处理
【ACL2024】基于长尾检索知识增强的大语言模型
近日,阿里云人工智能平台PAI与阿里集团安全部内容安全算法团队、华东师范大学何晓丰教授团队合作,在自然语言处理顶级会议ACL2024上发表论文《On the Role of Long-tail Knowledge in Retrieval Augmented Large Language Models》,论文主题为长尾知识检索增强的大语言模型。通过将问题识别为普通可回答和长尾两种性质,让大模型针对性的对长尾问题进行检索文档增强。对于普通可回答的用户提问可以直接通过大模型回答,而不需要进行文档检索增强,从而能增强大模型处理不同类型用户提问的效率。
|
存储 Linux 文件存储
Linux 存储管理 (二)创建文件系统
【8月更文挑战第13天】使用`fdisk`创建分区后,通过`mkfs`命令创建文件系统,支持多种类型如ext4、XFS等。创建前确认分区无重要数据,示例命令为`mkfs.ext4 /dev/sdc1`。之后使用`mount`命令将分区挂载至指定目录,如`mount /dev/sdc1 /w`。为实现开机自动挂载,可在`/etc/fstab`文件中添加相应条目。这些步骤有助于高效管理和利用存储空间。
286 2
|
9月前
|
Java 程序员 开发者
Java 中的多态性
Java中的多态性是面向对象编程的重要特性之一,允许一个接口或基类引用指向其不同子类的对象,实现“一种接口,多种方法”。通过方法重写和动态绑定,多态性提高了代码的灵活性和可扩展性。
250 3
|
11月前
|
移动开发 JavaScript 前端开发
HTML5 表单属性详解
HTML5引入了多种新的表单属性,使表单创建与验证更加便捷高效。新增的输入类型包括`email`、`url`、`tel`等,常用属性有`placeholder`、`required`等。表单元素如`&lt;form&gt;`可设置提交方法和目标URL,`&lt;button&gt;`及`&lt;input type=&quot;submit&quot;&gt;`用于提交。新元素`&lt;datalist&gt;`和`&lt;output&gt;`提供更多功能。HTML5还提供了内置表单验证机制,增强用户体验。
|
10月前
|
运维 Kubernetes 数据安全/隐私保护
K8S 拉取私有仓库镜像
在Kubernetes中从私有仓库拉取镜像时,需先创建包含认证信息的Secret,然后在Pod或Deployment中引用此Secret。本文通过具体步骤演示了如何创建Secret、更新Kubernetes资源配置文件以引用Secret,并验证了镜像拉取及应用运行的成功。
663 6
|
存储 编译器 C语言
C陷阱:数组越界遍历,不报错却出现死循环?从内存解析角度看数组与局部变量之“爱恨纠葛”
在代码练习中,通常会避免数组越界访问,但如果运行了这样的代码,可能会导致未定义行为,例如死循环。当循环遍历数组时,如果下标超出数组长度,程序可能会持续停留在循环体内。这种情况的发生与数组和局部变量(如循环变量)在内存中的布局有关。在某些编译器和环境下,数组和局部变量可能在栈上相邻存储,数组越界访问可能会修改到循环变量的值,导致循环条件始终满足,从而形成死循环。理解这种情况有助于我们更好地理解和预防这类编程错误。
421 0
|
编译器 C语言
mixing declarations and code is a C99 extension
mixing declarations and code is a C99 extension
712 0
|
消息中间件 数据安全/隐私保护 RocketMQ
RocketMQ ACL使用指南
详细介绍RocketMQ acl访问控制列表的流程图、plain_acl.yml文件各配置项的详细介绍、权限匹配验证流程与acl使用示例。
3101 0
|
数据采集 存储 算法
「AIGC算法」图搜索算法详解
本文探讨了图搜索算法,包括遍历和最短路径搜索。DFS和BFS是遍历算法,前者使用栈深入搜索,后者用队列逐层遍历。Dijkstra、Bellman-Ford、A*、Floyd-Warshall和Johnson算法则解决最短路径问题。文中还给出了DFS的Python实现示例。这些算法在路径规划、网络分析等领域有重要应用。
688 0