c语言实现通讯录

简介: c语言实现通讯录

一、通讯录:


1.1 通讯录介绍:


本次通讯录采用 结构体数组 存储 联系人 数据.


结构体数组 的每个成员保存着联系人的具体信息特征.


用一个参数 sz 记录当前联系人个数.



1.2 通讯录功能介绍:


1.添加联系人


2.删除联系人


3.修改联系人


4.查询联系人


5.展示通讯录



效果展示:



二、通讯录的实现:


2.1 通讯录类型的声明:


//宏定义,为了修改时更加方便
#define NAME_MAX 10   //名字的最大长度
#define SEX_MAX 5   //性别的最大长度
#define ADDR_MAX 20   //地址的最大长度
#define N 200     //定义最大存储联系人个数
//创建描述的人结构体类型
typedef struct people
{
  char name[NAME_MAX];    //姓名
  int age;          //年龄
  char sex[SEX_MAX];      //性别
  float stature;        //身高
  char addr[ADDR_MAX];    //地址
}peo;
//创建通讯录类型
typedef struct Contact
{
  peo data[N];//结构体数组,数组每个成员都是结构体,其中保存着联系人的信息
  int sz;//用于记录当前练习人的个数
}Contact;


2.2 通讯录的初始化:


通讯录 的大体框架已经建好,但是那只是通讯录的类型,我们应当利用类型创建变量并进行合理的初始化操作.


定义 通讯录 变量:


Contact cont;//创建通讯录cont


对 通讯录 进行合理的 初始化 操作.


InitContact(Contact* cont)//初始化通讯录函数
{
  assert(cont);//防止传入空指针
  cont->sz = 0;//初始时.通讯录为空,即0个联系人
  memset(cont->data, 0, sizeof(cont->data));//将结构体数组所占内存区域全部初始化为0.
}


2.3 添加联系人函数:


由于这一版本的 通讯录 采用的数组存储信息,数组的大小是 有限的 ,所以在进行添加联系人之前,我们应当考虑此时通讯录是否已经满了,当通讯录已经满了的时候,返回添加失败的错误信息.

否则正常插入,在数组下标sz位置添加联系人信息,最后sz++,表示联系人的个数增加1.


void add(Contact* cont)//添加联系人函数
{
  assert(cont);//防止传入空指针
  if (cont->sz == N)//如果已有200联系人,则不能添加
  {
    printf("添加失败,通讯录已满");
    return;
  }
  printf("请输入要添加联系人的信息:\n");
  printf("请输入姓名:");
  scanf("%s", cont->data[cont->sz].name);
  printf("请输入年龄:");
  scanf("%d", &cont->data[cont->sz].age);
  printf("请输入的性别:");
  scanf("%s", cont->data[cont->sz].sex);
  printf("请输入身高:");
  scanf("%f", &cont->data[cont->sz].stature);
  printf("请输入地址:");
  scanf("%s", cont->data[cont->sz].addr);
  cont->sz++;//人数加一
  printf("添加成功\n");
}


2.4 查询指定联系人函数:


为什么先介绍"查询指定联系人函数"呢?


我们知道,后面我们需要实现下列功能


删除联系人


修改联系人


这些功能都需要先找到目标联系人,所以我们先实现这个函数,后续需要在删除联系人和修改联系人时,可以直接调用该函数即可,


为了更好让该函数可以被其他函数复用,我们设计规则是:


该函数如果查找到了指定联系人,则返回该联系人在数组中的下标位置.


如果该联系不存在,则返回一个负数(因为数组的下标不可能是负数).

int FindName(const Contact* cont,const char* name)//查找人函数
{
  assert(cont && name);//防止传入空指针
  int i = 0;
  for (i = 0; i < cont->sz; i++)
  {
  //注意,字符串的比较不能使用"==",而要借助strcmp函数
    if (!strcmp(cont->data[i].name, name))//查找通讯录是否有这个名字
    {
      return i;//有就返回下标
    }
  }
  return -1;//查找失败,返回一个负数.
}


当然,有时候实际我们需要的查询联系人函数实现的功能不是返回下标,而是,如果存在该联系人,则打印该联系人的信息,没有则打印相应的提示信息.


void sel(const Contact* cont)//查询联系人函数
{
  char name[NAME_MAX];
  printf("请输入要查询的联系人的名字:\n");
  scanf("%s", name);
  int ret = FindName(cont, name);//利用查询人函数查找指定联系人的下标
  if (ret == -1)//如果返回-1,则查找失败
  {
    printf("通讯录中没有该联系人,查询失败.\n");
    return;
  }
  printf("查询成功,该联系信息如下:\n");
  printf("  +---------------------------------------------------------------+\n");
  printf("  |%-10s  %-5d  %-5s  %-7f  %-15s |\n", cont->data[ret].name, cont->data[ret].age, cont->data[ret].sex, cont->data[ret].stature, cont->data[ret].addr);
  printf("  +---------------------------------------------------------------+\n");
}


2.5 删除联系人函数


删除联系人操作:


1.需要知道该联系所在下标.


2.将该元素后的所有元素向前"移动"(说是移动,其实就是向前覆盖)一步.


3.size–,这样后面的元素其实并没有删除,而是访问不到了.


动态图解:



void del(Contact* cont)//删除联系人函数
{
  assert(cont);//防止传入空指针
  int i = 0;
  char name[NAME_MAX];
  printf("请输入需要删除的联系人的姓名:\n");
  scanf("%s", name);
  i=FindName(cont, name);
  if (i == -1)
  {
    printf("通讯录中没有该联系人,删除失败\n");
    return;
  }
  for (; i < cont->sz-1; i++)//注意这里sz要-1,因为下面用到了i+1下标
  {
    cont->data[i] = cont->data[i + 1];
  }
  cont->sz--;
  printf("删除成功,姓名为%s的联系人已删除\n", name);
}


2.6 修改指定联系人函数


其实讲到这里,修改指定联系人应该是一个很简单的操作.


1.我们先利用查找人函数,将下标找到.


2.获取要修改后联系人的信息.


3.将该下标位置的联系人信息覆盖为为新的信息.


void mod(Contact* cont)//修改联系人函数
{
  assert(cont);//防止传入空指针
  int ret = 0;
  char name[NAME_MAX];
  printf("请输入要修改的联系人的姓名:\n");
  scanf("%s", name);  
  ret = FindName(cont, name);
  if (ret == -1)
  {
    printf("通讯录中没有该联系人,修改失败\n");
    return;
  }
  printf("请输入修改后联系人的信息:\n");
  printf("请输入姓名:");
  scanf("%s", cont->data[ret].name);
  printf("请输入年龄:");
  scanf("%d", &cont->data[ret].age);
  printf("请输入的性别:");
  scanf("%s", cont->data[ret].sex);
  printf("请输入身高:");
  scanf("%f", &cont->data[ret].stature);
  printf("请输入地址:");
  scanf("%s", cont->data[ret].addr);
  printf("修改成功.\n");
}


总结


此版本的通讯录还有很多方面有待提高.


例如:


1.我们能否动态增长该通讯录的存储容量?


2.能否增加排序等新的功能?


3.能否保存以前的通讯录信息,当我们下次打开通讯录后,通讯录还保存以前的信息.


……


这些优化,会涉及到文件等后需要学习的知识,下回牛牛在细细分解.今天就到这里啦!!


总代码:


主测试区:


#include "声明区.h"
void menu()
{
  printf("\n        欢迎使用通讯录:\n");
  printf("  +-------------------------------------------------------------+\n");
  printf("  |     0.退出通讯录.            |\n");
  printf("  | 1.添加联系人     2.删除联系人       |\n");
  printf("  | 3.修改联系人     4.查询联系人       |\n");
  printf("  |     5.展示通讯录           |\n");
  printf("  +-------------------------------------------------------------+\n");
  printf("请选择:");
}
int main()
{
  int input = 0;
  Contact cont;//创建通讯录cont
  InitContact(&cont);
  do
  {
    menu();
    scanf("%d", &input);
    switch (input)
    {
    case 0:
      printf("退出通讯录");
      break;
    case 1:
      add(&cont);//添加联系人
      break;
    case 2:
      del(&cont);//删除联系人
      break;
    case 3:
      mod(&cont);//修改联系人
      break;
    case 4:
      sel(&cont);//查询联系人
      break;
    case 5:
      show(&cont);//展示通讯录
      break;
    default:
      printf("输入错误");
      break;
    }
  } while (input);
  return 0;
}


函数实现区:


#include "声明区.h"
InitContact(Contact* cont)//初始化通讯录函数
{
  assert(cont);//防止传入空指针
  cont->sz = 0;
  memset(cont->data, 0, sizeof(cont->data));
}
void add(Contact* cont)//添加联系人函数
{
  assert(cont);//防止传入空指针
  if (cont->sz == N)//如果已有200联系人,则不能添加
  {
    printf("添加失败,通讯录已满");
    return;
  }
  printf("请输入要添加联系人的信息:\n");
  printf("请输入姓名:");
  scanf("%s", cont->data[cont->sz].name);
  printf("请输入年龄:");
  scanf("%d", &cont->data[cont->sz].age);
  printf("请输入的性别:");
  scanf("%s", cont->data[cont->sz].sex);
  printf("请输入身高:");
  scanf("%f", &cont->data[cont->sz].stature);
  printf("请输入地址:");
  scanf("%s", cont->data[cont->sz].addr);
  cont->sz++;//人数加一
  printf("添加成功\n");
}
void show(const Contact* cont)//展示通讯录函数
{
  assert(cont);//防止传入空指针
  int i = 0;
  printf("        通讯录\n");
  printf("  +---------------------------------------------------------------+\n");
  printf("  |姓名   年龄  性别  身高    地址    |\n");
  for (i = 0; i < cont->sz; i++)
  {
    printf("  |%-10s  %-5d  %-5s  %-7f  %-15s |\n", cont->data[i].name, cont->data[i].age, cont->data[i].sex, cont->data[i].stature, cont->data[i].addr);
  }
  printf("  +---------------------------------------------------------------+\n");
}
int FindName(const Contact* cont,const char* name)//查找人函数
{
  assert(cont && name);//防止传入空指针
  int i = 0;
  for (i = 0; i < cont->sz; i++)
  {
    if (!strcmp(cont->data[i].name, name))//查找通讯录是否有这个名字
    {
      return i;//有就返回下标
    }
  }
  return -1;//没有返回一个负数.
}
void del(Contact* cont)//删除联系人函数
{
  assert(cont);//防止传入空指针
  int i = 0;
  char name[NAME_MAX];
  printf("请输入需要删除的联系人的姓名:\n");
  scanf("%s", name);
  i=FindName(cont, name);
  if (i == -1)
  {
    printf("通讯录中没有该联系人,删除失败\n");
    return;
  }
  for (; i < cont->sz-1; i++)//注意这里sz要-1,因为下面用到了i+1下标
  {
    cont->data[i] = cont->data[i + 1];
  }
  cont->sz--;
  printf("删除成功,姓名为%s的联系人已删除\n", name);
}
void mod(Contact* cont)//修改联系人函数
{
  assert(cont);//防止传入空指针
  int ret = 0;
  char name[NAME_MAX];
  printf("请输入要修改的联系人的姓名:\n");
  scanf("%s", name);  
  ret = FindName(cont, name);
  if (ret == -1)
  {
    printf("通讯录中没有该联系人,修改失败\n");
    return;
  }
  printf("请输入修改后联系人的信息:\n");
  printf("请输入姓名:");
  scanf("%s", cont->data[ret].name);
  printf("请输入年龄:");
  scanf("%d", &cont->data[ret].age);
  printf("请输入的性别:");
  scanf("%s", cont->data[ret].sex);
  printf("请输入身高:");
  scanf("%f", &cont->data[ret].stature);
  printf("请输入地址:");
  scanf("%s", cont->data[ret].addr);
  printf("修改成功.\n");
}
void sel(const Contact* cont)//查询联系人函数
{
  char name[NAME_MAX];
  printf("请输入要查询的联系人的名字:\n");
  scanf("%s", name);
  int ret = FindName(cont, name);
  if (ret == -1)
  {
    printf("通讯录中没有该联系人,查询失败.\n");
    return;
  }
  printf("查询成功,该联系信息如下:\n");
  printf("  +---------------------------------------------------------------+\n");
  printf("  |%-10s  %-5d  %-5s  %-7f  %-15s |\n", cont->data[ret].name, cont->data[ret].age, cont->data[ret].sex, cont->data[ret].stature, cont->data[ret].addr);
  printf("  +---------------------------------------------------------------+\n");
}


函数声明区:


#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 10
#define SEX_MAX 5
#define ADDR_MAX 20
#define N 200//定义最大存储联系人个数
//创建描述的人结构体类型
typedef struct people
{
  char name[NAME_MAX];    //姓名
  int age;          //年龄
  char sex[SEX_MAX];      //性别
  float stature;        //身高
  char addr[ADDR_MAX];    //地址
}peo;
//创建通讯录类型
typedef struct Contact
{
  peo data[N];
  int sz;
}Contact;
InitContact(Contact *cont);//初始化通讯录
void add(Contact *cont);//声明添加联系人函数
void show(const Contact* cont);//展示通讯录函数
int FindName(const Contact* cont,const char* name);//找人函数
void del(Contact* cont);//删除联系人函数
void mod(Contact* cont);//修改联系人函数
void sel(const Contact* cont);//查询联系人函数
目录
相关文章
|
8天前
|
C语言
用c语言实现一个通讯录
用c语言实现一个通讯录
12 0
|
8天前
|
存储 C语言
C语言详解【通讯录的实现】
C语言详解【通讯录的实现】
|
3天前
|
编译器 C语言
C语言进阶⑯(自定义类型)项目:静态通讯录,增删查改排序打印。
C语言进阶⑯(自定义类型)项目:静态通讯录,增删查改排序打印。
13 1
|
3天前
|
C语言
C语言实现通讯录
C语言实现通讯录
9 0
|
1天前
|
C语言
C语言——通讯录系统—基于 VS2022
C语言——通讯录系统—基于 VS2022
|
2天前
|
安全 数据库 C语言
【C语言】通讯录(文件) -- 详解
【C语言】通讯录(文件) -- 详解
|
2天前
|
安全 C语言
【C语言】动态通讯录 -- 详解
【C语言】动态通讯录 -- 详解
|
2天前
|
安全 C语言
【C语言】静态通讯录 -- 详解
【C语言】静态通讯录 -- 详解
|
2天前
|
C语言
c语言小课设--通讯录(动态内存管理+可持久化数据)
c语言小课设--通讯录(动态内存管理+可持久化数据)
|
3天前
|
存储 编译器 C语言
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose(下)
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose
9 0