【通讯录项目 (3 / 3)】基于顺序表的通讯录实现——通讯录项目实现

简介: 通讯录项目我们实现了大部分内容,接下来你可以自行探索,丰富功能。

通讯录项目 (3 / 3)】基于顺序表的通讯录实现——通讯录项目实现

前言

前两章我们已经知道顺序表的功能并完成了功能实现,下面我们将实现通讯录的以下功能:

1 项目预备工作

1.1 多文件处理

首先我们要对所用文件进行分类管理,以便后续操作。

我们将要在顺序表的基础上增加“contact.h”头文件和“contact.c”功能文件

注意头文件的正确引用

如下

请仔细检查,这是完成较大项目的基础。不同文件管理不同内容,方便快捷,效率高。

1.2 联系人数据管理

接下来是联系人的数据管理,我们需要改变原本顺序表的“SLDataType”为一个新类型。*我们可以想到联系人的信息不一,所以我们使用结构体来管理数据。

#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 20
#define ADDR_MAX 200

//前置声明
typedef struct SeqList  contact;

//用户数据
typedef struct PersonInfo
{
  char name[NAME_MAX];
  char sex[SEX_MAX];
  int age;
  char tel[TEL_MAX];
  char addr[ADDR_MAX];
}PeoInfo;

我们用宏定义常量,方便后续查看修改。这里我设置了姓名 性别 年龄 号码 地址五种信息。代码中“前置声明”是为了避免后续引用出现问题。我们通过“typedef”进行重命名,方便后续书写代码。

2 功能实现

上面将我们的准备工作进行完毕,下面开始实现功能。我们基于顺序表在进行操作。如有不理解的地方请参考【通讯录项目 (2 / 3)】,下面不对 顺序表功能 进行详细说明

我们会使用顺序表大多数功能,请理解顺序表的功能在进行阅读。

2.1 初始化通讯录

“初始化”只需要简单的引用顺序表的初始化即可。

void InitContact(contact* con)
{
  SLInit(con);
}
void SLInit(SL* ps)
{
  assert(ps);//断言判断是否为空
  ps->a = NULL;//将初始地址改为空
  ps->size = ps->capacity = 0;//容量与大小定为空
}

这样就实现了初始化,与初始化顺序表一致。

2.2 添加联系人

添加联系人也非常简单,只需要依次输入数据,在进行顺序表的插入即可。

void AddContact(contact* con)
{
  assert(con);
  PeoInfo info;
  printf("请输入联系人姓名:\n");
  scanf("%s", info.name);
  printf("请输入联系人的性别:\n");
  scanf("%s", info.sex);
  printf("请输入联系人的年龄:\n");
  scanf("%d", &info.age); //这里需要取地址,因为age是int类型,其余为数组
  printf("请输入联系人的电话:\n");
  scanf("%s", info.tel);
  printf("请输入联系人的住址:\n");
  scanf("%s", info.addr);

  SLPushBack(con,info);
  printf("添加成功\n");
void SLPushBack(SL* ps, SLDataType x)
{
  assert(ps);
  SLCheckCapacity(ps);
  ps->a[ps->size++] = x;

这样就进行了数据的加入。

2.3 删除联系人

删除联系人依然使用顺序表的删除功能。这里需要一个"查找联系人"的功能。需要通过一个信息来查找联系人是否存在。

2.3.1 查找目标

我们输入一个信息,来进行遍历查找联系人。返回目标的偏移值。

//查找联系人
int findname(contact* con, char name[NAME_MAX])
{
  assert(con);
  for (int i = 0; i < con->size; i++)
  {
    if (strcmp(con->a[i].name, name) == 0)
    {
      return i;
    }   
  }
  return -1;
}
2.3.2 删除联系人

同样使用顺序表的删除功能来实现,通过“查找联系人”返回的偏移值来进行定位

void DelContact(contact* con) 
{
  assert(con);
  char find[NAME_MAX] = { 0 };
  printf("请输入你想删除的联系人姓名:> \n");
  scanf("%s",find);
  int ret = findname(con, find);
  if (ret < 0)
  {
    printf("未找到该联系人\n");
  }
  else
    SLErase(con, ret);
}
void SLErase(SL*ps,int pos)
{                                                                                          
  assert(ps);
  if (pos >= 0 && pos < ps->size)
  {
    for (int i = pos; i < ps->size - 1; i++)
    {
      ps->a[i] = ps->a[i + 1];//a[size-2]=a[size-1]模拟最后一次查找
    }
    ps->size--;
  }
  else
    assert(pos);
}

这样通过覆盖就完成了删除功能。

2.4 展示通讯录

展示通讯录的功能是对顺序表展示的扩展。

void ShowContact(contact* pcon) {
  //打印通讯录所有的数据
  //先打印表头文字
  assert(pcon);
  printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
  for (int i = 0; i < pcon->size; i++)
  {
    printf("%-4s %-4s %-4d %-11s %-4s\n",
      pcon->a[i].name,
      pcon->a[i].sex,
      pcon->a[i].age,
      pcon->a[i].tel,
      pcon->a[i].addr
    );
  }
}

只需遍历顺序表,并打印联系人数据即可。

注意换行符,与打印格式让界面更加美观。

2.5 查找与修改

查找与修改操作相似,我们放在一起说明

2.5.1 查找联系人

查找联系人以上面的查找目标功能为基础,通过遍历进行查找。这里需要进行一次打印操作来展示查找结果

void FindContact(contact* con)
{
  assert(con);
  char find[NAME_MAX] = { 0 };
  printf("请输入想要查找的联系人姓名:> \n");
  scanf("%s",find);
  int ret = findname(con, find);
  if (ret < 0)
  {
    printf("未找到该联系人\n");
    
  }
  else{
    printf("找到了\n");
  printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
    printf("%-4s %-4s %-4d %-4s %-4s\n",
      con->a[ret].name,
      con->a[ret].sex,
      con->a[ret].age,
      con->a[ret].tel,
      con->a[ret].addr
    );
  }
}
2.5.2 修改联系人

修改联系人同样基于“查找目标”功能的基础,并进行一次修改操作。

oid ModifyContact(contact* con)
{
  assert(con);
  int name[NAME_MAX] = { 0 };
  printf("请输入想修改的联系人: > \n");
  scanf("%s", name);
  int ret = findname(con, name);
  //通过偏移量进行修改
  printf("请输入联系人姓名:\n");
  scanf("%s", con->a[ret].name);
  printf("请输入联系人的性别:\n");
  scanf("%s", con->a[ret].sex);
  printf("请输入联系人的年龄:\n");
  scanf("%d", &con->a[ret].age);
  printf("请输入联系人的电话:\n");
  scanf("%s", con->a[ret].tel);
  printf("请输入联系人的住址:\n");
  scanf("%s", con->a[ret].addr);
  printf("修改完成\n");
  ShowContact(con);

}

2.6 销毁通讯录

销毁功能是对储存空间的操作,通过free来实现销毁。

void DestroyContact(contact* con)
{
  assert(con);
  free(con->a);
  con->size = con->capacity = 0;
  con->a = NULL;
}

3 界面完成

上面我们已经实现了通讯录的大部分功能,还有一些额外功能没有加入,比如读取文件数据,储存到文件等。

下面我们开始完善界面内容,来把通讯录的功能进行整合。

3.1 打印菜单

这个容易实现,按照喜好设置即可,下面给予参考

void menu()
{
  printf("*************************************\n");
  printf("*********      通讯录      **********\n");
  printf("**** 1.添加联系人  2.删除联系人 *****\n");
  printf("**** 3.修改联系人  4.查找联系人 *****\n");
  printf("**** 5.查看通讯录  0.退出通讯录 *****\n");
}

效果如图

28b5fba8f0b1fc77e102f527ac054535_03bc56a5cc554a5fa4c7edf408821ee8.png

3.2 完成功能选择

通过switch语句我们可以方便的完成功能选择

int main()
{
  int op = -1;
  contact con;
  InitContact(&con);
  do {
    menu();
    printf("请选择你的操作:> \n");
    scanf("%d",&op);
    switch (op)
    {
      case 1:
        AddContact(&con);
        break;
      case 2:
        DelContact(&con);
        break;
      case 3:
        ModifyContact(&con);
        break;
      case 4:
        FindContact(&con);
        break;
      case 5:
        ShowContact(&con);
        break;
      case 0:
        printf("goodbye~\n");
        break;
      default:
        printf("输入格式有误,重新输入:> \n");
        break;
    }
  } while (op != 0);

  DestroyContact(&con);

  return 0;
}

这样我们就完成了功能选择,都是有一点点瑕疵。

3.3 界面优化

通过上面的菜单我们在进行几步操作后便会发现

界面非常冗杂混乱,如何解决呢。

我们可以通过

system("pause");
  system("cls");

这两行简单的代码便可以大大优化界面

int main()
{
  int op = -1;
  contact con;
  InitContact(&con);
  do {
    menu();
    printf("请选择你的操作:> \n");
    scanf("%d",&op);
    switch (op)
    {
      case 1:
        AddContact(&con);
        system("pause");
        system("cls");
        break;
      case 2:
        DelContact(&con);
        system("pause");
        system("cls");
        break;
      case 3:
        ModifyContact(&con);
        system("pause");
        system("cls");
        break;
      case 4:
        FindContact(&con);
        system("pause");
        system("cls");
        break;
      case 5:
        ShowContact(&con);
        system("pause");
        system("cls");
        break;
      case 0:
        printf("goodbye~\n");
        system("pause");
        system("cls");
        break;
      default:
        printf("输入格式有误,重新输入:> \n");
        system("pause");
        system("cls");
        break;
    }
  } while (op != 0);

  DestroyContact(&con);

  return 0;
}

让我们看看效果

无论进行多少操作,我们的界面依然清爽。

结语

通讯录项目我们实现了大部分内容,接下来你可以自行探索,丰富功能。

谢谢你的阅读

祝您前程似锦

相关文章
|
缓存 JavaScript
运行vue报错npm ERR! A complete log of this run can be found in解决办法
在这里我们需要清除npm的缓存: (1)在cmd命令行窗口中输入:npm cache clean --force (2)然后再运行我们需要安装模块的命令,输入npm install。 有时是网络问题,依赖包加载不完整,删掉node_modules文件后,重新执行npm install即可。
2746 0
|
消息中间件 SQL 分布式计算
大数据-64 Kafka 高级特性 分区Partition 分区重新分配 实机实测重分配
大数据-64 Kafka 高级特性 分区Partition 分区重新分配 实机实测重分配
402 7
|
SQL 前端开发 数据库
SqlAlchemy 2.0 中文文档(六)(1)
SqlAlchemy 2.0 中文文档(六)
163 0
|
前端开发
HTML网页作业代码(仿写商城首页、学校官网网页等、源码可直接运行)
这篇文章提供了HTML网页作业的完整代码,包括仿写商城首页和学校官网网页的源码,以及如何运行和项目结构等详细信息。
HTML网页作业代码(仿写商城首页、学校官网网页等、源码可直接运行)
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
282 1
|
关系型数据库 MySQL 数据库
【随手记】MySQL快照读和当前读
【随手记】MySQL快照读和当前读
457 0
|
存储 安全 搜索推荐
HTTPS协议深度解析
【7月更文挑战第12天】HTTPS协议通过加密通信和身份验证机制,为数据传输提供了强有力的安全保障。在现代互联网环境中,HTTPS已成为保障网站和用户数据安全的重要手段。了解HTTPS的工作原理和安全性特性,有助于更好地应用和维护HTTPS,提升网络安全水平。
1359 5
|
存储 运维 监控
Entity Framework Core 实现审计日志记录超棒!多种方法助你跟踪数据变化、监控操作,超实用!
【8月更文挑战第31天】在软件开发中,审计日志记录对于跟踪数据变化、监控用户操作及故障排查至关重要。Entity Framework Core (EF Core) 作为强大的对象关系映射框架,提供了多种实现审计日志记录的方法。例如,可以使用 EF Core 的拦截器在数据库操作前后执行自定义逻辑,记录操作类型、时间和执行用户等信息。此外,也可通过在实体类中添加审计属性(如 `CreatedBy`、`CreatedDate` 等),并在保存实体时更新这些属性来记录审计信息。这两种方法都能有效帮助我们追踪数据变更并满足合规性和安全性需求。
553 0
|
存储 JSON 小程序
【小程序云开发】不用后端也能构建完整的微信小程序
本文介绍了如何从零开始学习和掌握微信小程序云开发,包括云函数、云数据库和HTTP触发等重要概念。通过详细的步骤和示例,读者将学会如何创建和部署云函数,以及如何使用云数据库来存储和管理小程序的数据。同时,本文还介绍了如何通过HTTP触发器实现小程序与外部API的数据交互,从而为小程序开发提供更灵活、高效的后端解决方案。无论您是初学者还是有一定经验的开发者,本文都将帮助您轻松掌握微信小程序云开发,并为您的小程序开发项目提供更多可能性。
2659 0
|
供应链 监控 安全
ERP系统中的库存管理与优化
【7月更文挑战第25天】 ERP系统中的库存管理与优化
1406 2