用C语言模拟出来一个通讯录,首先要分头文件和源文件的,我这里分了一个头文件和两个源文件:
test.c这里用于存放主函数和调用其他函数,contacts.c用于存放通讯录的各种功能函数,contacts.h用于存放引用头文件的代码和自定义函数的声明和预处理指令。 首先,我们写的通讯录鸭油7个功能: 添加联系人,删除联系人,修改联系人的信息,查找联系人,展示通讯录联系人,排序通讯录中的联系人,退出通讯录。 test.c
#include "contacts.h"
enum list
{
exit,//默认值为0
add,
del,
modify,
find,
show,
sort
};
void catalogue()
{
printf("*********************************\n");
printf("*** 1.add 2.del ***\n");
printf("*** 3.modify 4.find ***\n");
printf("*** 5.show 6.sort ***\n");
printf("*** 0.exit ***\n");
printf("*********************************\n");
}
int main()
{
int n = 0;
do
{
catalogue();//通讯录菜单
printf("请选择>");
scanf("%d", &n);//选择要做什么
switch (n)
{
case exit://退出程序
printf("退出通讯录");
break;
case add://添加联系人
break;
case del://删除联系人
break;
case find://查找联系人
break;
case modify://修改联系人信息
break;
case show://展示联系人
break;
case sort://排序通讯录
break;
default:
printf("输入错误请重新输入\n");
}
} while (n);
return 0;
}
Contacts.c
#include "contacts.h"
Contacts.h
#include <stdio.h>
运行起来看一下效果:
下面我们就着手安排剩下的功能。
首先我们要想一下,通讯录里面的联系人个人信息都有什么,我自己定义的有,名字,年龄,性别,电话,住址。 因为通讯录里面要储存一些联系人,联系人又分这些信息,那么我们用构造体来定义一个联系人再合适不过。 Contacts.h
//定义的结构体
typedef struct person
{
char name[20];//名字
int age;//年龄
char sex[20];//性别
char phone[20];//电话
char location[20];//住址
}person;
这是联系人的类型,那么一个通讯录我们假设能储存一百个人,那么还需要有一个变量来计算一下通讯录当前有多少人才行。 Contacts.h
typedef struct contacts
{
person data[100];//存放人信息的位置
int count;//记录通讯录的人数
}contacts;
这里因为data和count是维护整个通讯录的关键变量,count是根据date里面的元素数量变化而变化,放在一个结构体里面更方便用。 然后整个程序就是这样子的: Contacts.h
#include <stdio.h>
#include <string.h>
//定义的结构体
typedef struct person
{
char name[20];//名字
int age;//年龄
char sex[20];//性别
char phone[20];//电话
char location[20];//住址
}person;
typedef struct contacts
{
person data[100];//存放人信息的位置
int count;//记录通讯录的人数
}contacts;
//函数声明区
void initialize(contacts* pc);//初始化通讯录
Contacts.c
#include "contacts.h"
void initialize(contacts* pc)
{
pc->count = 0;//将计数的变量初始化为0
memset(pc->data, 0, sizeof(pc->data));//将数组里面的内容都初始化为0
}
test.c
#include "contacts.h"
enum list
{
exit,//默认值为0
add,
del,
modify,
find,
show,
sort
};
void catalogue()
{
printf("*********************************\n");
printf("*** 1.add 2.del ***\n");
printf("*** 3.modify 4.find ***\n");
printf("*** 5.show 6.sort ***\n");
printf("*** 0.exit ***\n");
printf("*********************************\n");
}
int main()
{
int n = 0;
contacts con;//通讯录
initialize(&con);//初始换通讯录
do
{
catalogue();//通讯录菜单
printf("请选择>");
scanf("%d", &n);//选择要做什么
switch (n)
{
case exit://退出程序
printf("退出通讯录");
break;
case add://添加联系人
break;
case del://删除联系人
break;
case find://查找联系人
break;
case modify://修改联系人信息
break;
case show://展示联系人
break;
case sort://排序通讯录
break;
default:
printf("输入错误请重新输入\n");
}
} while (n);
return 0;
}
这里我们初始化完成了。 这里要说一下,我们传结构体就要传结构体的地址,因为能节省内存。 (这里忘记添加assert函数来断言了,下面补上了)。
添加联系人首先要先判断通讯录是不是人数已经满了,然后在contacts结构体中的person data[100]存放联系人的信息,从data[0]开始,那么count就是计算有多少个联系人,一开始也是0,多一个就++,那么count也对应了data数组的下标存放位置。 存放进去之后我们顺便也写一下打印函数,打印就很简单了,定义一个变量来当数组下标,小于count就可以了。 contacts.h
//函数声明区
void initialize(contacts* pc);//初始化通讯录
void addcontact(contacts* pc);//输入联系人信息
void showcontact(const contacts* pc);//打印通讯录,因为打印不需要修改里面的数值,所以用const修饰一下更安全
contacts.c
void addcontact(contacts* pc)
{
assert(pc != NULL);//断言pc指向的位置不是空指针
if (pc->count == MAX)
{
printf("通讯录已满\n");
return 0;
}
printf("姓名:");
scanf("%s", pc->data[pc->count].name);//这里注意一下,数组名是首元素地址,所以不用取地址了
printf("年龄:");
scanf("%d", &(pc->data[pc->count].age));
printf("性别:");
scanf("%s", pc->data[pc->count].sex);
printf("电话号:");
scanf("%s", pc->data[pc->count].phone);
printf("家庭住址:");
scanf("%s", pc->data[pc->count].location);
pc->count++;
printf("增加成功\n");
}
void showcontact(const contacts* pc)
{
assert(pc != NULL);
int i = 0;
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄","性别","电话号","家庭住址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].phone,
pc->data[i].location);
}
}
test.c
int main()
{
int n = 0;
contacts con;//通讯录
initialize(&con);//初始换通讯录
do
{
catalogue();//通讯录菜单
printf("请选择>");
scanf("%d", &n);//选择要做什么
switch (n)
{
case exit://退出程序
printf("退出通讯录");
break;
case add://添加联系人
addcontact(&con);
break;
case del://删除联系人
break;
case find://查找联系人
break;
case modify://修改联系人信息
break;
case show://展示联系人
showcontact(&con);
break;
case sort://排序通讯录
break;
default:
printf("输入错误请重新输入\n");
}
} while (n);
return 0;
}
来看一下效果:
这三个放在一起写比较方便,因为修改和删除需要先查找有没有这个联系人才可以操作,查找功能更不用说。 首先要写一个查找联系人的函数,用strcmp函数来查找你输入的名字在通讯录里有无。 删除联系人的函数: contacts.c
int find_out(char* p1 , contacts* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
int i = 0;
for (i = 0; i < p2->count; i++)
{
if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
return i;
}
return -1;
}
int delcontact(contacts* pc)
{
assert(pc != NULL);
char name[20] = { 0 };
printf("输入此人姓名\n");
scanf("%s", name);
int i = find_out(name, pc);
if (i == -1)
{
printf("无此人信息\n");
return 1;
}
pc->count = pc->count - 1;
while (i < pc->count)
{
pc->data[i] = pc->data[i + 1];//删除的过程
i++;
}
printf("删除成功");
}
其实删除人的过程很简单,你选定的元素是data[i],然后被data[i+1]覆盖,data[i+1]被data[i+2]覆盖以此循环。 因为通过一个查找的逻辑找到了此人,所以通讯录的人就会少一人,那么count就会减一,这样让i<count就不会有问题了,如果count不减少,i=99,count=100,就会造成数组的越界访问,这样不好处理,所以我们直接让count- -,这样i最多也就是98,i+1=99;至于data[99]这个位置的元素怎么办,不用理会,上面的添加联系人和展示通讯录都是count进行很重要的操作,新添加的联系人会覆盖掉原来末尾中没有被位移的联系人信息;如果没有添加展示联系人的话根本不会打印出来末尾的那个联系人。 修改联系人就更容易了,直接将原来联系人的信息覆盖掉就可以了,等于无循环版本添加联系人函数。 修改联系人的函数: contacts.c
int find_out(char* p1 , contacts* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
int i = 0;
for (i = 0; i < p2->count; i++)
{
if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
return i;
}
return -1;
}
int modifycontact(contacts* pc)
{
assert(pc != NULL);
printf("输入此人姓名\n");
char name[20] = { 0 };
scanf("%s", name);
int i = find_out(name, pc);
if (i == -1)
{
printf("无此人信息\n");
return 1;
}
printf("请输入要修改的信息\n");
printf("姓名:");
scanf("%s", pc->data[i].name);
printf("年龄:");
scanf("%d", &(pc->data[i].age));
printf("性别:");
scanf("%s", pc->data[i].sex);
printf("电话号:");
scanf("%s", pc->data[i].phone);
printf("家庭住址:");
scanf("%s", pc->data[i].location);
printf("修改成功\n");
}
查找联系人的函数就是展示通讯录函数的无循环版本。 这是查找联系人的函数: contacts.c
int find_out(char* p1 , contacts* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
int i = 0;
for (i = 0; i < p2->count; i++)
{
if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
return i;
}
return -1;
}
int findcontact(contacts* pc)
{
assert(pc != NULL);
printf("输入此人姓名\n");
char name[20] = { 0 };
scanf("%s", name);
int i = find_out(name, pc);
if (i == -1)
{
printf("无此人信息\n");
return 1;
}
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].phone,
pc->data[i].location);
}
这是代码运行的效果(写一点调试一点,这样就会让代码的bug容易修复):
排序我也按照通讯录中联系人的名字来排序,这就用到了之前的函数,qsort。 contacts.c
int estimate(const void* p1, const void* p2)
{
return strcmp(((person*)p1)->name, ((person*)p2)->name);//比较的是联系人中姓名的大小
}
void sortcontact(contacts* pc)
{
assert(pc != NULL);
qsort(pc->data, pc->count, sizeof(person), estimate);//利用接收estimate函数的返回值然后排序data数组里面的元素
printf("排序成功\n");
}
看看是否有问题:
没问题。
contacts.h
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#define MAX 100//通讯录最大人数
//定义的结构体
typedef struct person
{
char name[20];//名字
int age;//年龄
char sex[20];//性别
char phone[20];//电话
char location[20];//住址
}person;
typedef struct contacts
{
person data[100];//存放人信息的位置
int count;//记录通讯录的人数
}contacts;
//函数声明区
void initialize(contacts* pc);//初始化通讯录
void addcontact(contacts* pc);//输入联系人信息
void showcontact(const contacts* pc);//打印通讯录
int delcontact(contacts* pc);//删除联系人
int modifycontact(contacts* pc);//修改联系人信息
int findcontact(contacts* pc);//查找联系人
void sortcontact(contacts* pc);//排序通讯录
contacts.c
#include "contacts.h"
int find_out(char* p1, contacts* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
int i = 0;
for (i = 0; i < p2->count; i++)
{
if (!strcmp(p1, p2->data[i].name))//如果相等就返回0,前面加了!操作符,所以非零条件不成立
return i;
}
return -1;
}
void initialize(contacts* pc)
{
assert(pc != NULL);
pc->count = 0;//将计数的变量初始化为0
memset(pc->data, 0, sizeof(pc->data));//将数组里面的内容都初始化为0
}
void addcontact(contacts* pc)
{
assert(pc != NULL);//断言pc指向的位置不是空指针
if (pc->count == MAX)
{
printf("通讯录已满\n");
return 0;
}
printf("姓名:");
scanf("%s", pc->data[pc->count].name);
printf("年龄:");
scanf("%d", &(pc->data[pc->count].age));
printf("性别:");
scanf("%s", pc->data[pc->count].sex);
printf("电话号:");
scanf("%s", pc->data[pc->count].phone);
printf("家庭住址:");
scanf("%s", pc->data[pc->count].location);
pc->count++;
printf("增加成功\n");
}
void showcontact(const contacts* pc)
{
assert(pc != NULL);
int i = 0;
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].phone,
pc->data[i].location);
}
}
int delcontact(contacts* pc)
{
assert(pc != NULL);
char name[20] = { 0 };
printf("输入此人姓名\n");
scanf("%s", name);
int i = find_out(name, pc);
if (i == -1)
{
printf("无此人信息\n");
return 1;
}
pc->count = pc->count - 1;
while (i < pc->count)
{
pc->data[i] = pc->data[i + 1];
i++;
}
printf("删除成功\n");
}
int modifycontact(contacts* pc)
{
assert(pc != NULL);
printf("输入此人姓名\n");
char name[20] = { 0 };
scanf("%s", name);
int i = find_out(name, pc);
if (i == -1)
{
printf("无此人信息\n");
return 1;
}
printf("请输入要修改的信息\n");
printf("姓名:");
scanf("%s", pc->data[i].name);
printf("年龄:");
scanf("%d", &(pc->data[i].age));
printf("性别:");
scanf("%s", pc->data[i].sex);
printf("电话号:");
scanf("%s", pc->data[i].phone);
printf("家庭住址:");
scanf("%s", pc->data[i].location);
printf("修改成功\n");
}
int findcontact(contacts* pc)
{
assert(pc != NULL);
printf("输入此人姓名\n");
char name[20] = { 0 };
scanf("%s", name);
int i = find_out(name, pc);
if (i == -1)
{
printf("无此人信息\n");
return 1;
}
printf("%-20s\t%-20s\t%-20s\t%-20s\t%-20\t\n", "姓名", "年龄", "性别", "电话号", "家庭住址");
printf("%-20s\t%-20d\t%-20s\t%-20s\t%-20\t\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].phone,
pc->data[i].location);
}
int estimate(const void* p1, const void* p2)
{
return strcmp(((person*)p1)->name, ((person*)p2)->name);
}
void sortcontact(contacts* pc)
{
assert(pc != NULL);
qsort(pc->data, pc->count, sizeof(person), estimate);
printf("排序成功\n");
}
test.c
#include "contacts.h"
enum list
{
EXIT,
ADD,
DEL,
MODIFY,
FIND,
SHOW,
SORT
};
void catalogue()
{
printf("*********************************\n");
printf("*** 1.add 2.del ***\n");
printf("*** 3.modify 4.find ***\n");
printf("*** 5.show 6.sort ***\n");
printf("*** 0.exit ***\n");
printf("*********************************\n");
}
int main()
{
int n = 0;
contacts con;//通讯录
initialize(&con);//初始换通讯录
do
{
catalogue();//通讯录菜单
printf("请选择>");
scanf("%d", &n);//选择要做什么
switch (n)
{
case EXIT://退出程序
printf("退出通讯录\n");
break;
case ADD://添加联系人
addcontact(&con);
break;
case DEL://删除联系人
delcontact(&con);
break;
case FIND://查找联系人
findcontact(&con);
break;
case MODIFY://修改联系人信息
modifycontact(&con);
break;
case SHOW://展示联系人
showcontact(&con);
break;
case SORT://排序通讯录
sortcontact(&con);
break;
default:
printf("输入错误请重新输入\n");
}
} while (n);
return 0;
}