本文主要展示简要通讯录的实现
主题框架
首先,我们要有一个主体框架,就是显示对于通讯录的各种操作:增添、删去、查找、修正、排序、退出。代码如下
void menu()
{
printf("***************************\n");
printf("***** 1.add 2.del ***\n");
printf("*** 3.search 4.modify *\n");
printf("***** 5.show 6.sort ***\n");
printf("********0.exit ********\n");
printf("***************************\n");
printf("***************************\n");
printf("***************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d",&input);
switch (input)//枚举体里已经定义好每个单词对应的数字,因此单词可以替代数字,同时也提高了代码的可读性
{
case ADD:
break;
case DEL:
break;
case SEARCH:
break;
case MODIFY:
break;
case SHOW:
break;
case SORT:
break;
case EXIT:
break;
default:
printf("选择错误");
break;
}
} while (input);
return 0;
}
这时候,我们该用什么来存储个人的多个信息?----->结构体
我们可以简单地设定两个结构体,
#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,*pContact;
Contact con; //此处声明con这个结构体
接着,我们先实现往通讯录里增加信息,
这里定义一个函数--AddContact
//将结构体的地址传入函数,会比直接传入一整个结构体更省空间,效率更高
//传入地址,就用指针来接收
void AddContact(Contact* pc);//声明
void AddContact(Contact* pc)//定义
{
if (pc->sz == MAX)//pc指向的sz,实则就是当前通讯录里的信息数
{
printf("通讯录已满,无法增加");
return;
}
printf("请输入名字:>");
scanf("%s", pc->data[pc->sz].name);
//pc->data 代表的是在结构体里找到data这个成员变量
//且data是个数组,故要确定其占的位数,故有pc->sz
//随后已经进入到data里的第一个元素,也就是第一个结构体,再指向name这个成员变量
printf("请输入年龄:>");
scanf("%d", &(pc->data[pc->sz].age));//给年龄赋值
//此处的pc->sz,是指的是第几号信息
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++;//记录后+1,为下一个信息留空间
printf("添加成功");
}
此处的重点,其实是如何用结构体表示我们需要的那个信息
pc->sz 其实是Contact结构体里的sz,sz保存的是当前通讯录中信息的个数
pc->data[pc->sz].() 这里的pc指向的是Contact数组里的data数组,而data数组里又存放着PeoInfo这个结构体的的成员变量
接下来展示删除功能的代码---根据姓名删除相关信息,且后边的数据要往前补齐,那么就需要两个函数1.通过名字查找 。 2.进行删除操作
static int FindByName(const Contact *pc, char name[])//const 修饰指针
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
{
return i;
}
}
return -1;//找不到的时候,直接返回值
//若均不成立,则不返回
}
void DelContact(Contact *pc);
void DelContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
if (pc->sz == 0)
{
printf("已无更多信息!无法删除");
return;
}
//删除
//找到要删除的人-位置
printf("输入要删除的名字:>");
scanf("%s", name);
int i = 0;
int pos = FindByName(pc, name); //pos就是记录要被删除元素的位置,从此位置开始,后往前补齐
if (pos == -1)
{
printf("要删除的人不存在");
return;//直接返回,结束这个函数的执行
}
for (i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;//数据量减少,那么sz也需要减少,可以容纳更多的信息
printf("删除成功\n");
}
查找函数
void SearchContact(Contact* pc);
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)
void ModifyContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
printf("请输入要修改的人的名字");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要修改的人不存在");
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);
//pos存储着要修改的人的位置信息
//针对当前的位置的信息进行修改
printf("修改成功\n");
}
排序函数,这里我们需要用到qsort函数,并且自定义一个按照名字,从低到高的函数
//假设按照名字来排序
cmp_by_name(const void* e1, const void* e2)
//传入的指针位置是无类型的
//所以用PeoInfo*来修饰 代表元素是这个结构体里的
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo * )e2)->name);
}
//qsort默认从低到高排序
void SortContact(Contact* pc)
{
qsort(pc->data,pc->sz,sizeof(PeoInfo),cmp_by_name);
printf("排序成功!");
}
除此之外,我们还有一个展示函数,要将当前通讯录里的信息展示出来
void ShowContact(const Contact* pc);
void ShowContact(const Contact* pc)
{
int i = 0;
//姓名 年龄 性别 电话 地址
//zhangsan 20 ...
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);
}
}
初始化函数
void InitContact(Contact* pc)//仅是临时拷贝,改变这里的对主函数里的结构体没有任何改变
//所以应该用指针,且传入的应该是地址
{
pc->sz = 0;
//信息数置为0
//pc->data = 0;//数组不能赋值为0,是一个整体
memset(pc->data, 0, sizeof(pc->data)); //这里用memset函数
//memset(对象,存放内容,存放大小(个数))
}
接着,按照需要,在主函数里引用各个实现定义好的函数即可。