一、通讯录:
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);//查询联系人函数