自学内容网 自学内容网

通讯录(C 语言)

一、通讯录设计思路

1. 伪代码设计思路

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

提供方法:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 以名字排序所有联系人

2. 代码设计思路

通过对上述伪代码的分析,我们使用结构体 info_person 来表示个人信息。

// 个人信息结构声明
typedef struct info_person
{
char name[20];  // 姓名
char sex[5];  // 性别
size_t age;  // 年龄
char phone[12];  // 电话
char address[40];  // 住址
}info_person;

接着再使用一个结构体 ContacksList 来表示通讯录,该通讯录包含一个结构体 info_person 数组,大小为 100,用来存储 100 个人的信息。此外还应该包含一个 size_t 类型的成员 size 用来表示当前存储个人信息的数量,这也方便了上述伪代码中要求的方法设计。

// 常量声明
#define SIZE_INFO 100

// 通讯录结构声明
typedef struct ContacksList
{
info_person infos[SIZE_INFO];
size_t size;
}ContacksList;

下面就是使用有意义的函数名来表示上述方法。

// 方法

// 1. 添加联系人信息
void AddContack(ContacksList* cl);

// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl, char* name);

// 3. 查找指定联系人信息
void FindContack(const ContacksList* cl, char* name);

// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl, char* name);

// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl);

// 6. 清空所有联系人
void ClearContack(ContacksList* cl);

// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl);

以上就是头文件 ContacksList.h 包含的基本内容,剩下的就是方法的实现和代码的测试。

二、代码实现

整体代码分成三个文件:头文件 ContacksList.h,方法定义文件 ContacksList.c,测试文件 test.c。由于头文件在前面已经给出,下面就只给出剩下两个文件。

方法定义文件 ContacksList.c

// 头文件
#include "ContacksList.h"
#include <assert.h>
#include <string.h>

// 方法

// 1. 添加联系人信息
void AddContack(ContacksList* cl)
{
assert(cl);
// 通讯录已满
if (CAPACITY == cl->size)
{
printf("通讯录已满,添加失败!\n");
return;
}
// 添加
// 
// 输入联系人的相关信息
info_person tmp;
printf("请输入联系人的信息->");
printf("姓名: ");
scanf("%s", tmp.name);
printf("性别: ");
scanf("%s", tmp.sex);
printf("年龄: ");
scanf("%zd", &tmp.age);
printf("电话: ");
scanf("%s", tmp.phone);
printf("地址: ");
scanf("%s", tmp.address);
// 拷贝
cl->infos[cl->size] = tmp;
// 人数 +1
++cl->size;
printf("添加成功!\n");
}

// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl)
{
assert(cl);
// 删除
//
// 查找指定联系人
char name[20];
printf("请输入删除人的姓名: ");
scanf("%s", name);
int i = FindContack(cl, name);
// 找到了
if (-1 != i)
{
// 把该位置往后的联系人往前移
while (i < cl->size - 1)
{
// 前移
cl->infos[i] = cl->infos[i + 1];
// 下一个
++i;
}
// 联系人 -1
--cl->size;
printf("删除成功!\n");
}
else
{
printf("删除失败!\n");
}
}

// 3. 查找指定联系人信息
int FindContack(const ContacksList* cl, char* name)
{
assert(cl);
// 通讯录为空
if (0 == cl->size)
return -1;

// 输入查找人的姓名
char tmp[20] = { 0 };
if (NULL == name)
{
name = tmp;
printf("请输入查找人的姓名: ");
scanf("%s", name);
}

// 查找
int i;
for (i = 0; i < cl->size; ++i)
{
// 找到
if (strcmp(cl->infos[i].name, name) == 0)
{
return i;
}
}
// 没找到
return -1;
}

// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl)
{
assert(cl);
// 查找指定联系人
char name[20];
printf("请输入修改人的姓名: ");
scanf("%s", name);
int i = FindContack(cl, name);
// 找到了
if (-1 != i)
{
// 输入联系人修改后的相关信息
info_person tmp;
printf("请输入联系人的信息->");
printf("姓名: ");
scanf("%s", tmp.name);
printf("性别: ");
scanf("%s", tmp.sex);
printf("年龄: ");
scanf("%zd", &tmp.age);
printf("电话: ");
scanf("%s", tmp.phone);
printf("地址: ");
scanf("%s", tmp.address);
// 修改
cl->infos[i] = tmp;
printf("修改成功!\n");
}
else
{
printf("修改失败!\n");
}
}

// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl)
{
assert(cl);
// 标题行
printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");
// 输出
int i;
for (i = 0; i < cl->size; ++i)
{
printf("%-10s%-8s%-8zd%-15s%-10s\n", cl->infos[i].name, cl->infos[i].sex, cl->infos[i].age, cl->infos[i].phone, cl->infos[i].address);
}
}

// 6. 清空所有联系人
void ClearContack(ContacksList* cl)
{
assert(cl);
// 清空
cl->size = 0;
}

// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl)
{
assert(cl);
// 冒泡排序
int i;
for (i = 0; i < cl->size - 1; ++i)
{
int j;
for (j = 0; j < cl->size - 1 - i; ++j)
{
// 相邻比较
if (strcmp(cl->infos[j].name, cl->infos[j + 1].name) > 0)
{
// 交换
info_person tmp = cl->infos[j];
cl->infos[j] = cl->infos[j + 1];
cl->infos[j + 1] = tmp;
}
}
}
printf("按名字身升序排序成功!\n");
}

测试文件 test.c

// 头文件
#include "ContacksList.h"

// 菜单
void menu()
{
printf("****************************************************\n");
printf("***********1. Add          2. Delete   *************\n");
printf("***********3. Find         4. Modify   *************\n");
printf("***********5. Print        6. Clear    *************\n");
printf("***********7. Sort         0. Exit     *************\n");
printf("****************************************************\n");
}

int main()
{
// 创建通讯录
ContacksList cl = { {0}, 0 };
// 选择操作
int select = 0;
int i = 0;
do
{
// 菜单
menu();
// 选择
printf("请选择: ");
scanf("%d", &select);
switch (select)
{
case 1:
AddContack(&cl);
break;
case 2:
DeleteContack(&cl);
break;
case 3:
i = FindContack(&cl, NULL);
printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-10s%-8s%-8zd%-15s%-10s\n", cl.infos[i].name, cl.infos[i].sex, cl.infos[i].age, cl.infos[i].phone, cl.infos[i].address);
break;
case 4:
ModifyContack(&cl);
break;
case 5:
PrintContack(&cl);
break;
case 6:
ClearContack(&cl);
break;
case 7:
SortByName(&cl);
break;
case 0:
printf("退出通讯录!\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (select);

return 0;
}

三、程序运行演示

在这里插入图片描述

四、整体分析

该通讯录是一个静态通讯录,容量是固定的,当数据超出容量时不够存储,当数据少于容量时造成空间的浪费。后面作者会把该通讯录升级为动态通讯录,当容量不够的时候会进行增容。

在方法实现中,删除指定联系人函数 DeleteContack() 和修改指定联系人函数 ModifyContack() 都需要先找到指定的联系人,所以可以稍微修改一下查找指定联系人函数 FindContack(),然后再前面两个函数中调用该函数,这样就减少了代码的冗余。删除操作需要判断通讯录是否为空,插入操作需要判断通讯录是否已满。

当然读者可以自行根据需要进行修改,这里只提供一个大概思路和基础功能的实现。


原文地址:https://blog.csdn.net/weixin_70742989/article/details/143527460

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!