引言
我们常说去用C语言去完成一些项目,实现一些我们想要的功能和搭建一个简单的平台或者完成一个小游戏的代码编写。我想说的是无论你想要用C语言去实现什么,首先得确定你需要实现的哪些些功能,然后通过自己对于这些功能怎么去实现,搭建一个大致的程序结构框架。就如万丈高楼平地起,首先你得有建一座楼的原理图。然后通过对于具体框架的不断细化和完善,让框架更加的饱和和丰满起来。这是一个工程从无到有的基本构建思想。我觉得编程需要也必须需要这种工程思想。这会对于我们之后的程序编写有着巨大的好处。
一、通讯录的代码框架
如上图所示即为通讯录代码编写的基本框架,我们可以参考上图的大致框架理清基本编程思路然后再去不断的细化和完善。
二、通讯录基本结构和功能代码详解
1.通讯录基本结构
通讯录的基本结构可以大致分为两部分,一是联系人的信息的结构体struct PeoInfo,其中包括联系人的各种信息(姓名,性别,年龄,电话,地址),二是通讯录的结构体struct Contact,其中包括联系人信息结构体数组struct PeoInfo data[MAX]和通讯录中录入联系人的个数sz。创建通讯录结构体struct Contact con,每次功能函数调用,传入结构体指针。
2.通讯录功能
通讯录的功能包括初始化通讯录,增加联系人,删除联系人,显示联系人,查找联系人,修改联系人,排序联系人,清空联系人。下面就一个一个来详细介绍和分析。
2.1初始化通讯录
初始化,顾名思义就是将我们所创建的通讯录人信息结构体数组中的成员全部赋予初始值,如果一个一个成员去初始化,那么工程量太大,所以这里我们使用memset函数将100个struct PeoInfo类型的字节大小赋为0实现通讯录的初始化。
初始化代码如下:
void InitContact(struct Contact*pc)
{
assert(pc); //断言,避免输入的pc为空指针
pc->sz = 0;
memset(pc->data, 0, 100 * sizeof(struct PeoInfo)); //用memset函数将100个struct PeoInfo类型的字节大小赋为0;
}
2.2添加通讯录中联系人信息
添加通讯录中联系人信息之前首先得判断通讯录是否已满,即判断pc->sz是否等于MAX,这里MAX方便统一修改,使用宏定义为100,#define MAX 100。即判断通讯录中联系人数是否为100。
如果未满,开始添加联系人,通过联系人结构体成员的一个一个的输入来实现添加,通过所调用struct Contact *pc所指向的联系人信息结构体数组data[],下标为sz的成员pc->data[pc->sz].name来实现数据的输入。注意!!!每次添加通讯录中联系人个数sz++.
添加通讯录中联系人信息代码如下:
void AddContact(struct Contact*pc) //添加通讯录中联系人信息
{
assert(pc); //断言
if (pc->sz == MAX) //添加联系人之前先判断通讯录是否已满
{
printf("通讯录已满\n");
return;
}
//增加联系人信息
printf("请输入名字:\n");
scanf("%s",pc->data[pc->sz].name); //sz即为数组data的下标,每增加一个联系人,sz++
printf("请输入性别:\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:\n");
scanf("%d", &(pc->data[pc->sz].age)); //年龄为变量所以要取地址,其余为数组,不需要取地址。
printf("请输入电话:\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:\n");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++; //每添加一个,sz++,实现sz的更新
printf("成功增加联系人\n");
}
2.3查找通讯录中联系人信息
本次查找函数是通过联系人姓名来实现查找功能,首先输入所要查找联系人的姓名,通过所编写的
FindName()函数来实现查找,该函数通过strcmp实现输入的姓名与通讯录中的姓名符串一个一个比较,相等返回0,如果相等则返回所找到姓名的下标。没找到则返回-1。
如果找到所要查找的联系人则将信息打印显示出来。
查找通讯录中联系人信息代码如下:
int FindName( struct Contact*pc, char name[]) //查找函数
{
int i = 0;
for (i = 0; i < pc->sz;i++)
{
if (strcmp(pc->data[i].name, name) == 0) //用strcmp函数一个一个与输入的名字字符串比较,相等返回0。
return i; //存在则将所找到的名字的下标返回
}
return -1;
}
void SearchContact(const struct Contact*pc) //查找通讯录中联系人信息
{
char name[MAX_NAME];
printf("请输入要查找联系人名字:>\n");
scanf("%s", name);
//先查找要查找联系人在通讯录中是否存在
int ret = FindName(pc, name);
if (ret == -1)
{
printf("所要查找的联系人不存在\n");
}
else //找到了并打印出来
{
printf("%-20s\t%-6s\t%-6s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-6s\t%-6d\t%-12s\t%-30s\n", pc->data[ret].name,
pc->data[ret].sex, pc->data[ret].age,
pc->data[ret].tele, pc->data[ret].addr);
}
}
2.4显示通讯录中联系人信息
显示通讯录中联系人信息就是将通讯录中sz个联系人信息一个一个打印出来,可以先打印一行显示数据标题,显示所录入联系人信息每列的标题。注意!!!标题上是字符串年龄,用%s打印,打印联系人信息中pc->data[i].age是int型,用%d打印。其中%-20s是最多打印20个字符,向左对齐,不够用0填充,\t为水平制表符tab。
显示通讯录中联系人信息代码如下:
void ShowContact(const struct Contact*pc) //显示通讯录中联系人信息
{
int i = 0;
printf("%-20s\t%-6s\t%-6s\t%-12s\t%-30s\n","名字","性别","年龄","电话","地址");
//先打印一行显示数据标题(%-20s,最多打印20个字符,向左对齐,不够用0填充)
//\t为水平制表符tab
for (i = 0; i < pc->sz;i++)
{
printf("%-20s\t%-6s\t%-6d\t%-12s\t%-30s\n", pc->data[i].name,
pc->data[i].sex, pc->data[i].age,
pc->data[i].tele, pc->data[i].addr);
}
}
2.5删除通讯录中联系人信息
要删除通讯录中联系人信息首先得查找所要删除的联系人是否在通讯录中,通过FindName()函数来实现查找,找到则开始删除,通过FindName()函数所找到的返回找到联系人数组下标ret,ret即为所找到的要删除联系人的下标,赋予j,将data[j+1]赋予data[j], 即将后一个联系人数据覆盖到前一个联系人数据上,实现删除。注意!!!每次删除通讯录中联系人个数sz--.
删除通讯录中联系人信息代码如下:
void DelContact( struct Contact*pc) //删除通讯录中联系人信息
{
char name[MAX_NAME];
printf("请输入要删除联系人名字:>\n");
scanf("%s",name);
//先查找要删除联系人在通讯录中是否存在
int ret = FindName(pc,name);
if (ret==-1)
{
printf("所要删除的联系人不存在\n");
}
else //存在,开始删除
{
int j = 0;
for (j = ret; j < pc->sz - 1;j++)
{
pc->data[j] = pc->data[j + 1];//ret即为所找到的要删除联系人的下标,赋予j,将data[j+1]赋予data[j],
//即将后一个联系人数据覆盖到前一个联系人数据上,实现删除
}
pc->sz--; //每删除一个,sz--,实现sz的更新
printf("删除联系人成功!\n");
}
}
2.6修改通讯录中联系人信息
想要修改通讯录中联系人信息,还是得先找到想要修改的联系人,如上一样,通过FindName()函数来实现查找,找到则开始修改。找到则返回找到联系人数组下标ret。本次修改程序只能通过重新录入所要修改人的全部信息,不能单一的修改某个信息,这是需要优化和改进的地方。
修改通讯录中联系人信息代码如下:
void ModifyContact(struct Contact*pc) //修改通讯录中联系人信息
{
char name[MAX_NAME];
printf("请输入要修改联系人名字:>\n");
scanf("%s", name);
//先查找要修改联系人在通讯录中是否存在
int ret = FindName(pc, name);
if (ret == -1)
{
printf("所要修改的联系人不存在\n");
}
else
{
printf("请输入名字:\n");
scanf("%s", pc->data[ret].name); //sz即为数组data的下标,每增加一个联系人,sz++
printf("请输入性别:\n");
scanf("%s", pc->data[ret].sex);
printf("请输入年龄:\n");
scanf("%d", &(pc->data[ret].age)); //年龄为变量所以要取地址,其余为数组,不需要取地址。
printf("请输入电话:\n");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:\n");
scanf("%s", pc->data[ret].addr);
printf("修改成功!\n");
}
}
2.7排序通讯录中联系人信息
本次程序是通过qsort函数来排序通讯录中联系人信息,其中可以通过联系人姓名,年龄等一些系类信息进行排序,使用什么信息进行排序决定了qsort中自己所要编写的比较函数。因为qsort函数大家早已熟悉,这里就不一一叙述了。
排序通讯录中联系人信息代码如下:
int CmpByName(const void*e1, const void*e2) //qsort排序函数
{
return strcmp((struct PeoInfo*)e1, (struct PeoInfo*)e2);
}
void SortContact(struct Contact*pc) //排序通讯录中联系人信息
{
qsort(pc->data, pc->sz, sizeof(struct PeoInfo),CmpByName);
printf("排序成功!!\n");
}
2.8清空通讯录中联系人信息
怎么清空通讯录中联系人信息,这里我想的是就和初始化通讯录一样的操作,就是用memset函数将100个struct PeoInfo类型的字节大小赋为0。清空就意味着重新初始化嘛。
清空通讯录中联系人信息如下:
void ClearContact(struct Contact*pc) //清空通讯录中联系人信息
{
assert(pc); //断言,避免输入的pc为空指针
pc->sz = 0;
memset(pc->data, 0, 100 * sizeof(struct PeoInfo)); //用memset函数将100个struct PeoInfo类型的字节大小赋为0;
printf("清除通讯录联系人信息成功!!!\n");
}
三、代码结果演示
添加:
删除:
查找:
修改:
排序:
四、结语
通过本次通讯录的知识学习和代码编写,我对于结构体的了解和应用又提升了一个档次,有了更深刻的认识,我觉得通过自己看别人怎么写,然后自己再跟着一步一步模拟,最后通过自己独立的思考去单独完成代码的编写是一个学习编程的一个比较好的习惯,从走到跑再到飞,一步一个脚印来。虽然可能花费比较多的时间,但是熟能生巧。多次的思考和动手编写会让你不断的进步。