实现思路
让我们首先来想想通讯录一般需要哪些功能,最主要的无非6种:增加联系人,删除联系人,搜索联系人,修改联系人,打印通讯录,将联系人分类。这就是我们要实现的几种基本功能,接下来我们就可以开始上手实现代码了
通讯录菜单
这是非常经典的一步,我们创建一个名为test.c的文件,用来完成对通讯录大致流程的编写,首先咱先完成菜单函数
void menu()
{
printf("*******************************");
printf("**** 1.Add 2.Del ******");
printf("**** 3.Search 4.Modify ******");
printf("**** 5.Show 6.Sort ******");
printf("**** 0.Exit ******");
printf("*******************************");
}
我希望当我们在键盘上敲击一个数字时,该程序就可以实现对应的功能,所以我们就要在添加下列代码
int main()
{
do
{
int input = 0;
menu();
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
}
} while()
return 0;
}
我们用input变量接收一个值,根据input的值来实现对应的功能,我们或许觉得输入123来实现对应功能不够直观,我们为什么不能直接输入ADD,DEL···呢?所以我可以在创建一个枚举
enum Option
{
EXIT,//代表0
ADD,//代表1
DEL,//代表2
SEARCH,//```
MODIFY,
SHOW,
SORT
};
这样我们就可以将上面的代码修改为
int main()
{
do
{
int input = 0;
menu();
scanf("%d", &input);
switch (input)
{
case ADD:
break;
case DEL:
break;
case SEARCH:
break;
case MODIFY:
break;
case SHOW:
break;
case SORT:
break;
}
} while()
return 0;
}
通讯录的创建
我们再创建第二个文件“contact.h”这是一个头文件,主要用来存放函数的声明,我们把通讯录的创建也放在这里实现,假设我们要创建一个能存放1000人的通讯录,那么显然我们需要一个容量为1000的数组,那么这个数组中的变量类型应该是什么呢?对于联系人这样的复杂对象,用结构体显然是更加合适的。所以让我们先来创建一个结构体,用来存放联系人信息,
struct PeoInfo
{
char name[NAME];
int age;
char sex[SEX];
char tele[TELE];
char addr[ADDR];
};
为了增强代码可读性,并且方便代码日后的维护,我把数组大小的数字用具有实际意义的字母来代替,所以我们要增加如下定义
#define NAME 20
#define SEX 5
#define TELE 12
#define ADDR 30
以上的代码已经足以描述一位联系人了,但是在实际操作中我们会发现其实联系人的数量也极其重要,所以我们还应该将用户信息和他的编号一起分装在另一个结构体中
struct contact
{
struct PeoInfo data[MAX];
int sz;
};
这里我依然用字母来代替数字,所以我们还得加上一个定义,
#define MAX 1000
接着我们在test.c文件中创建一个通讯录
struct contact con;
很遗憾的是,当我们创建完这个通讯录后,通讯录con中储存的仍然是一堆随机值,所以我们得先初始化这个通讯录
初始化通讯录
我们需要创建一个函数,而对于函数的实现,我们可以在"contact.c"源文件中进行,让我们创建一个名为ContactInit的函数来完成初始化,那么我们应该给这个函数传递什么参数呢?因为我们希望对这个通讯录本身进行改变,所以我们不希望改变的只是一个形参,因此此时将结构体的地址传过去是合适的,现在让我们来看看代码的实现,我们先在test.c文件中对函数传参
ContactInit(&con);
接着去contact.h中进行函数声明
void ContactInit(struct contact* pc);
然后在contact.c中完成函数的实现
void ContactInit(struct contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
}
这样我们就可以把通讯录中的数值初始化了,接下来我们要开始编写通讯录的功能
添加联系人
我们在contact.c文件中进行添加联系人函数的编写,并将此函数命名为AddContact
void AddContact(struct contact* pc)
{
if (pc -> sz == MAX)
{
printf("通讯录满了\n");
}
else
{
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);
prinitf("请输入地址:>");
scanf("%s", pc->data[pc->sz].addr);
printf("添加成功\n");
pc->sz++;
}
}
以此思路,我们可以很简单的将剩下的功能全部写完,接着让我们先来看看通讯录打印
打印通讯录
void ShowContact(struct contact* pc)
{
int i = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
for (i = 0; i < pc->sz; i++)
{
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
这里我们使用for循环遍历通讯录的所有联系人并打印
删除联系人
此功能的思路与其它的稍有不同,因为我们希望删除此联系人后,该联系人后面的联系人整体位置向前移动一格
void DelContact(struct contact* pc)
{
char name[NAME] = { 0 };
printf("请输入要删除人的名字");
scanf("%s", &name);
//查找
//删除
}
这是该函数的大致框架,我们为了完成这个函数,其核心就是查找和删除两个功能,而对于查找功能,我们会发现在之后的查找和修改功能中都是会用到的,所以我们完全可以将其分装成一个函数
int FindContactByName(struct contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcpy(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;
}
当程序找到该联系人时,它返回的i就是该数组元素的下标,下面我们用pos来接收它
void DelContact(struct contact* pc)
{
char name[NAME] = { 0 };
printf("请输入要删除人的名字");
scanf("%s", &name);
//查找
int pos = FindContactByName(pc, name);
//删除
if (pos == -1)
{
printf("该联系人不存在\n");
}
else
{
int i = 0;
for (i = 0; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
当然,这个程序仍有一点缺陷,当这个通讯录中,没有联系人时,程序应该提示我们当前无法删除,所以我们可以加一行代码
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
修改通讯录
void ModifyContact(struct contact* pc)
{
char name[NAME] = { 0 };
printf("输入要修改人的名字\n");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (-1 == pos)
{
printf("要输入的人不存在\n");
}
else
{
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);
}
}
完整代码
test.c
#include "contact.h"
void menu()
{
printf("*******************************\n");
printf("**** 1.Add 2.Del ******\n");
printf("**** 3.Search 4.Modify ******\n");
printf("**** 5.Show 0.Exit ******\n");
printf("*******************************\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW
};
int main()
{
struct contact con;
ContactInit(&con);
int input = 0;
do
{
menu();
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;
default:
printf("选择错误\n");
}
} while (input);
return 0;
}
contact.c
#include "contact.h"
void ContactInit(struct contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
void AddContact(struct contact* pc)
{
if (pc->sz == MAX)
{
printf("通讯录满了\n");
}
else
{
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);
printf("添加成功\n");
pc->sz++;
}
}
void ShowContact(struct contact* pc)
{
int i = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
for (i = 0; i < pc->sz; i++)
{
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
int FindContactByName(const struct contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(struct contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME] = { 0 };
printf("请输入要删除人的名字");
scanf("%s", name);
//查找
int pos = FindContactByName(pc, name);
//删除
if (pos == -1)
{
printf("该联系人不存在\n");
}
else
{
int i = 0;
for (i = 0; i < pc->sz-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
void SearchContact(const struct contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空\n");
return;
}
printf("请输入联系人名字");
int pos = 0;
char name[NAME] = { 0 };
scanf("%s", name);
pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("查无此人\n");
}
else
{
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tele", "addr");
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
}
void ModifyContact(struct contact* pc)
{
char name[NAME] = { 0 };
printf("输入要修改人的名字\n");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (-1 == pos)
{
printf("要输入的人不存在\n");
}
else
{
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);
}
}
contact.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define NAME 20
#define SEX 5
#define TELE 12
#define ADDR 30
#define MAX 1000
struct PeoInfo
{
char name[NAME];
int age;
char sex[SEX];
char tele[TELE];
char addr[ADDR];
};
struct contact
{
struct PeoInfo data[MAX];
int sz;
};
void ContactInit(struct contact* pc);
void AddContact(struct contact* pc);
void ShowContact(struct contact* pc);
void DelContact(struct contact* pc);
void SearchContact(const struct contact* pc);
void ModifyContact(struct contact* pc);