静态版通讯录——C语言【详解+全部码源】

简介: 静态版通讯录——C语言【详解+全部码源】

通讯录的实现

1. 设计框架

与我们之前的扫雷和三子棋项目设计一样,把程序分装在三个文件中:

test.c:通讯录的总体逻辑,测试通讯录的相关功能

contact.c:通讯录的实现模块

contact.h:通讯录的各种声明,包括库函数、自定义函数以及自定义结构体的声明

2. 菜单函数的实现

实现通讯录建立一个菜单是很重要的,并且菜单要包含通讯录所有的功能,以便于用户的操作

代码如下:

void menu()
{
  printf("********************************\n");
  printf("*****       1. add           ***\n");
  printf("*****       2. del           ***\n");
  printf("*****       3. search        ***\n");
  printf("*****       4. modify        ***\n");
  printf("*****       5. show          ***\n");
  printf("*****       6. sort          ***\n");
  printf("*****       0. exit          ***\n");
  printf("********************************\n");
}


3. 菜单选项功能函数的实现

有了菜单之后我们还需要创建一个函数来进行菜单的选择功能,比如输入1,就会增加联系人,输入0,就可以退出程序

看代码:

enum Option//使用枚举变量来定义
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT
};
int main()
{
  int input = 0;
  Contact con;//通讯录
  //初始化通讯录
  //加载文件的信息到通讯录中
  InitContact(&con);
  int input = 0;
  do
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case ADD:
      AddContact(&con);
      break;
    case DEL:
      DelContact(&con);
      break;
    case SEARCH:
      SearchContact(&con);
      break;
    case MODIFY:
      ModifyContact(&con);
      break;
    case SHOW:
      ShowContact(&con);
      break;
    case SORT:
      SortContact(&con);
      break;
    case EXIT:
      printf("退出通讯录\n");
      break;
    default:
      printf("选择错误\n");
      break;
    }
  } while (input);
  return 0;
}


这里我们用了switch语句和do····while语句来实现


4. 联系人结构体的创建

用第一个结构体 PeoInfo存放人的信息,第二个结构体Contact是通讯录的信息,data是以第一个结构体为类型的数组,用sz记录通讯录里当前有几个人的信息

代码如下:

//表示一个人的信息
typedef struct PeoInfo
{
  char name[MAX_NAME];
  int age;
  char sex[MAX_SEX];
  char tele[MAX_TELE];
  char addr[MAX_ADDR];
}PeoInfo;
typedef struct Contact
{
  PeoInfo data[MAX];//存放数据
  int sz;//记录通讯录中的有效信息个数
}Contact;


5. 全局变量的定义

为了后期处理数据方便,我们用宏来实现这个功能

#include <stdio.h>
#include <string.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30


通讯录功能的实现

1. 初始化通讯录

在对data初始化时,我们使用一个memset函数来实现

此函数需要引用string的头文件

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


2. 增加联系人信息

访问通讯录结构体里的数组中的元素然后输出就可以了

结构体对象访问用:.

指针访问用:->

代码如下:

void AddContact(Contact* pc)
{
  if (pc->sz == MAX)
  {
    printf("通讯录已满,无法增加\n");
    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].addr);
  pc->sz++;
  printf("添加成功\n");
}


3. 打印通讯录

这里我们用for循环来打印通讯录

void ShowContact(const Contact* pc)
{
  int i = 0;
  //打印标题
  printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
  //打印数据
  for (i = 0; i < pc->sz; i++)
  {
    printf("%-10s %-4d %-5s %-12s %-30s\n",
      pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
  }
}


4. 删除指定联系人

因为在删除联系人和查找联系人时都需要查找的功能,所以我们在这里分装了一个查找函数

代码如下:

static int FindByName(const Contact* pc, char name[])
//加上static使得函数只能在自己所在的.c文件内部使用
{
  int i = 0;
  for (i = 0; i < pc->sz; i++)
  {
    if (0 == strcmp(pc->data[i].name, name))
    {
      return i;
    }
  }
  return -1;
}


我们利用查找函数查找下标,查找到我们需要删除的联系人的下标,然后对他进行删除,删除后我们要把后边的元素向前移动,利用for循环来移动

代码如下:

void DelContact(Contact* pc)
{
  char name[MAX_NAME] = { 0 };
  if (pc->sz == 0)
  {
    printf("通讯录为空,无法删除\n");
    return;
  }
  //删除
  //1. 找到要删除的人 - 位置(下标)
  printf("输入要删除人的名字:>");
  scanf("%s", name);
  int pos = FindByName(pc, name);
typedef struct Contact
{
  PeoInfo data[MAX];//存放数据
  int sz;//记录通讯录中的有效信息个数
}Contact, *pContact;
  if (pos == -1)
  {
    printf("要删除的人不存在\n");
    return;
  }
  int i = 0;
  //2. 删除 - 删除pos位置上的数据
  for (i = pos; i < pc->sz - 1; i++)
  {
    pc->data[i] = pc->data[i + 1];
  }
  pc->sz--;
  printf("删除成功\n");
}


另一种写法:

typedef struct Contact
{
  PeoInfo data[MAX];//存放数据
  int sz;//记录通讯录中的有效信息个数
}Contact, *pContact;
void DelContact(pContact pc);
void SearchContact(pContact pc);


5. 查找联系人

代码如下:

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


6. 修改通讯录

代码如下:

void ModifyContact(Contact* pc)
{
  char name[MAX_NAME] = { 0 };
  printf("请输入要修改人的名字:>");
  scanf("%s", name);
  int pos = FindByName(pc, name);
  if (pos == -1)
  {
    printf("要修改的人不存在\n");
    return;
  }
  //修改
  printf("请输入名字:>");
  scanf("%s", pc->data[pos].name);
  printf("请输入年龄:>");
  scanf("%d", &(pc->data[pos].age));
  printf("请输入性别:>");
  scanf("%s", pc->data[pos].sex);
  printf("请输入电话:>");
  scanf("%s", pc->data[pos].tele);
  printf("请输入地址:>");
  scanf("%s", pc->data[pos].addr);
  printf("修改成功\n");
}


7. 排序通讯录

用qsort函数来排序,需要提供比较函数,这里假设我们用名字来排序

代码如下:

//按照名字来排序
int cmp_by_name(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
  qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
  printf("排序成功\n");
}


完整代码

contact.h

#pragma once
#include <stdio.h>
#include <string.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
//表示一个人的信息
typedef struct PeoInfo
{
  char name[MAX_NAME];
  int age;
  char sex[MAX_SEX];
  char tele[MAX_TELE];
  char addr[MAX_ADDR];
}PeoInfo;
typedef struct Contact
{
  PeoInfo data[MAX];//存放数据
  int sz;//记录通讯录中的有效信息个数
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加指定联系人
void AddContact(Contact* pc);
//显示联系人信息
void ShowContact(const Contact* pc);
//删除指定联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//修改通讯录
void ModifyContact(Contact* pc);
//排序通讯录元素
void SortContact(Contact* pc);


contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
//初始化通讯录
void InitContact(Contact* pc)
{
  pc->sz = 0;
  memset(pc->data, 0, sizeof(pc->data));
}
//增加联系人
void AddContact(Contact* pc)
{
  if (pc->sz == MAX)
  {
    printf("通讯录已满,无法增加\n");
    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].addr);
  pc->sz++;
  printf("添加成功\n");
}
//显示联系人信息
void ShowContact(const Contact* pc)
{
  int i = 0;
  //打印标题
  printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
  //打印数据
  for (i = 0; i < pc->sz; i++)
  {
    printf("%-10s %-4d %-5s %-12s %-30s\n",
      pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
  }
}
static int FindByName(const Contact* pc, char name[])
//加上static使得函数只能在自己所在的.c文件内部使用
{
  int i = 0;
  for (i = 0; i < pc->sz; i++)
  {
    if (0 == strcmp(pc->data[i].name, name))
    {
      return i;
    }
  }
  return -1;
}
//删除指定联系人
void DelContact(Contact* pc)
{
  char name[MAX_NAME] = { 0 };
  if (pc->sz == 0)
  {
    printf("通讯录为空,无法删除\n");
    return;
  }
  //删除
  //1. 找到要删除的人 - 位置(下标)
  printf("输入要删除人的名字:>");
  scanf("%s", name);
  int pos = FindByName(pc, name);
  if (pos == -1)
  {
    printf("要删除的人不存在\n");
    return;
  }
  int i = 0;
  //2. 删除 - 删除pos位置上的数据
  for (i = pos; i < pc->sz - 1; i++)
  {
    pc->data[i] = pc->data[i + 1];
  }
  pc->sz--;
  printf("删除成功\n");
}
//查找指定联系人
void SearchContact(const Contact* pc)
{
  char name[MAX_NAME] = { 0 };
  printf("请输入要查找人的名字:>");
  scanf("%s", name);
  //查找
  int pos = FindByName(pc, name);
  if (pos == -1)
  {
    printf("要查找的人不存在\n");
    return;
  }
  //打印
  printf("%-10s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
  //打印数据
  printf("%-10s %-4d %-5s %-12s %-30s\n",
    pc->data[pos].name,
    pc->data[pos].age,
    pc->data[pos].sex,
    pc->data[pos].tele,
    pc->data[pos].addr);
}
//修改通讯录
void ModifyContact(Contact* pc)
{
  char name[MAX_NAME] = { 0 };
  printf("请输入要修改人的名字:>");
  scanf("%s", name);
  int pos = FindByName(pc, name);
  if (pos == -1)
  {
    printf("要修改的人不存在\n");
    return;
  }
  //修改
  printf("请输入名字:>");
  scanf("%s", pc->data[pos].name);
  printf("请输入年龄:>");
  scanf("%d", &(pc->data[pos].age));
  printf("请输入性别:>");
  scanf("%s", pc->data[pos].sex);
  printf("请输入电话:>");
  scanf("%s", pc->data[pos].tele);
  printf("请输入地址:>");
  scanf("%s", pc->data[pos].addr);
  printf("修改成功\n");
}
//排序通讯录元素
//按照名字来排序
int cmp_by_name(const void* e1, const void* e2)
{
  return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
  qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
  printf("排序成功\n");
}


test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
  printf("********************************\n");
  printf("*****       1. add           ***\n");
  printf("*****       2. del           ***\n");
  printf("*****       3. search        ***\n");
  printf("*****       4. modify        ***\n");
  printf("*****       5. show          ***\n");
  printf("*****       6. sort          ***\n");
  printf("*****       0. exit          ***\n");
  printf("********************************\n");
}
enum Option//使用枚举变量来定义
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT
};
int main()
{
  int input = 0;
  Contact con;//通讯录
  //初始化通讯录
  InitContact(&con);
  do
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case ADD:
      AddContact(&con);
      break;
    case DEL:
      DelContact(&con);
      break;
    case SEARCH:
      SearchContact(&con);
      break;
    case MODIFY:
      ModifyContact(&con);
      break;
    case SHOW:
      ShowContact(&con);
      break;
    case SORT:
      SortContact(&con);
      break;
    case EXIT:
      printf("退出通讯录\n");
      break;
    default:
      printf("选择错误\n");
      break;
    }
  } while (input);
  return 0;
}


运行结果如图所示:

这个静态版通讯录还是有很多不足的地方


1.通讯录大小是固定大小(只能是100个元素)

2.当通讯录退出之后,重新运行,之前的信息都丢了

这是因为当前的通讯录信息保存在内存中的,程序退出,内存就收回,下一次重新运行程序,内存重新分配,之前的数据就不见了

数据能否永久保存?——文件

下次七七会更新动态版的通讯录,来解决这个问题,一起期待吧!

目录
相关文章
|
5天前
|
C语言
用c语言实现一个通讯录
用c语言实现一个通讯录
12 0
|
5天前
|
存储 C语言
C语言详解【通讯录的实现】
C语言详解【通讯录的实现】
|
5天前
|
C语言
C语言进阶第八课 --------通讯录的实现
C语言进阶第八课 --------通讯录的实现
|
5天前
|
存储 算法 C语言
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
|
5天前
通讯录(C语言版)
通讯录(C语言版)
|
5天前
|
程序员 C语言
【C语言实战项目】通讯录(动态增容版)
【C语言实战项目】通讯录(动态增容版)
23 0
|
5天前
|
存储 编译器 C语言
【C语言实战项目】通讯录
【C语言实战项目】通讯录
29 0
|
5天前
|
C语言
【C语言】通讯录实现(下)
【C语言】通讯录实现(下)
|
5天前
|
存储 C语言
[C语言]通讯录实现(中)
[C语言]通讯录实现(中)
|
5天前
|
存储 C语言
【C语言】通讯录实现(上)
【C语言】通讯录实现(上)