在平常生活中,我们几乎每天都要使用通讯录,今天我们就用C语言来模拟实现通讯录。
要求:通讯录可以用来存储1000个人的信息,每个人的信息包括:
姓名、性别、年龄、电话、住址
提供方法:
1.添加联系人信息
2.删除指定联系人信息
3.查找指定联系人信息
4.修改指定联系人信息
5.显示所有联系人信息
6.清空所有联系人
7.以名字排序所有联系人
//头文件 contact.h
#ifndef __CONTACT_
#define __CONTACT_
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>
#include<string.h>
#define SIZE 2 //每次增加容量
#define MEMBER_MAX 5 /通讯录最大的容量
typedef struct{ //建立一个man_t来存储每个人的信息
char name[20];
char sex[10];
int age;
char tel[12];
char addr[128];
}man_t, *man_p;
typedef struct _contact{ //建立一个结构体来存储1000个人的信息
man_p listp;
int size;
int cap;
}contact_t, *contact_p;
enum{ //用枚举变量来做菜单选项
EXIT,
ADD,
ERASE,
FIND,
MODIFY,
SHOW,
EMPTY,
SORT,
};
void init(contact_p phonebook); //初始化通信录
void check_memory(contact_p phonebook); //开辟内存
void Add_Contact(contact_p phonebook); //添加联系人信息
int search(contact_p phonebook); //查找联系人信息
void Delete_Contact(contact_p phonebook); //删除指定联系人信息
void Find_Contact(contact_p phonebook); //查找指定联系人信息
void Modify_Contact(contact_p phonebook); //修改指定联系人信息
void Show_Contact(contact_p phonebook); //显示所有联系人信息
void Empty_Contact(contact_p phonebook); //清空所有联系人
void Sort_Contact(contact_p phonebook); //以名字排序所有联系人
void Save_Contact(contact_p phonebook); //保存所有的联系人
void Load_Contact(contact_p phonebook); //加载通讯录
#endif
//主要功能 contact.c
#include"contact.h"
void init(contact_p phonebook) //初始化通信录
{
phonebook->listp = (man_t*)calloc(MEMBER_MAX, sizeof(man_t));
if (phonebook->listp == NULL)
{
printf("out of memory\n");
exit(0);
}
phonebook->size = 0;
phonebook->cap = SIZE;
}
void check_memory(contact_p phonebook) //开辟内存
{
if (phonebook->size == phonebook->cap)
{
man_p tmp = NULL;
tmp = (man_t*)realloc(phonebook->listp, ((phonebook->cap) + SIZE)*sizeof(man_t));
if (tmp == NULL)
{
printf("out of memory\n");
exit(0);
}
phonebook->listp = tmp;
phonebook->cap += SIZE;
}
}
void Add_Contact(contact_p phonebook) //添加联系人信息
{
check_memory(phonebook);
printf("请输入姓名->:");
scanf("%s", phonebook->listp[phonebook->size].name);
printf("\n请输入性别->:");
scanf("%s", phonebook->listp[phonebook->size].sex);
printf("\n请输入年龄->:");
scanf("%d", &phonebook->listp[phonebook->size].age);
printf("\n请输入电话->:");
scanf("%s", phonebook->listp[phonebook->size].tel);
printf("\n请输入住址->:");
scanf("%s", phonebook->listp[phonebook->size].addr);
printf("\n添加成功!\n");
printf("\n");
phonebook->size++;
}
int search(contact_p phonebook) //查找联系人信息
{
char name[20];
int i = 0;
scanf("%s", &name);
for (i = 0; i < phonebook->size; i++)
{
if (strcmp(phonebook->listp[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void Delete_Contact(contact_p phonebook) //删除指定联系人信息
{
if (phonebook->size == 0)
{
printf("\n当前通讯录为空!\n");
printf("\n");
}
else
{
printf("\n请输入需要删除的联系人姓名->:");
int ret = search(phonebook);
if (ret != -1)
{
phonebook->listp[ret] = phonebook->listp[phonebook->size - 1];
phonebook->size--;
printf("\n删除联系人成功!\n");
printf("\n");
}
else
{
printf("\n没找到该联系人!\n");
printf("\n");
}
}
}
void Find_Contact(contact_p phonebook) //查找指定联系人信息
{
printf("\n请输入需要查找的联系人姓名->:");
int ret = search(phonebook);
if (ret != -1)
{
printf("\n姓名:%s\n",phonebook->listp[ret].name);
printf("\n性别:%s\n", phonebook->listp[ret].sex);
printf("\n年龄:%d\n", phonebook->listp[ret].age);
printf("\n电话:%s\n", phonebook->listp[ret].tel);
printf("\n住址:%s\n", phonebook->listp[ret].addr);
}
else
{
printf("\n不存在该联系人!\n");
printf("\n");
}
}
void Modify_Contact(contact_p phonebook) //修改指定联系人信息
{
char name[20];
printf("\n请输入需要修改信息的联系人姓名->:");
int ret = search(phonebook);
if (ret != -1)
{
char change[20];
int age = 0;
int sel = 0;
printf("\n");
printf("***** 1.姓名 *****\n");
printf("***** 2.性别 *****\n");
printf("***** 3.年龄 *****\n");
printf("***** 4.电话 *****\n");
printf("***** 5.地址 *****\n");
printf("\n请选择需要更改的项目->:");
scanf("%d", &sel);
printf("\n请输入更改后的内容->:");
switch (sel)
{
case 1:
{
scanf("%s", &change);
strcpy(phonebook->listp[ret].name, change);
printf("\n修改成功!\n");
break;
}
case 2:
{
scanf("%s", &change);
strcpy(phonebook->listp[ret].sex, change);
printf("\n修改成功!\n");
break;
}
case 3:
{
scanf("%d", &age);
phonebook->listp[ret].age=age;
printf("\n修改成功!\n");
break;
}
case 4:
{
scanf("%s", &change);
strcpy(phonebook->listp[ret].tel, change);
printf("\n修改成功!\n");
break;
}
case 5:
{
scanf("%s", &change);
strcpy(phonebook->listp[ret].addr, change);
printf("\n修改成功!\n");
break;
}
}
}
}
void Show_Contact(contact_p phonebook) //显示所有联系人信息
{
int i = 0;
if (phonebook->size == 0)
printf("\n该通讯录为空!\n");
else
{
for (i = 0; i < phonebook->size; i++)
{
printf("\n姓名:%s\n", phonebook->listp[i].name);
printf("性别:%s\n", phonebook->listp[i].sex);
printf("年龄:%d\n", phonebook->listp[i].age);
printf("电话:%s\n", phonebook->listp[i].tel);
printf("住址:%s\n", phonebook->listp[i].addr);
}
}
}
void Empty_Contact(contact_p phonebook) //清空所有联系人
{
phonebook->listp = NULL;
phonebook->size = 0;
printf("\n已清空!\n");
printf("\n");
}
void Sort_Contact(contact_p phonebook) //以名字排序所有联系人
{
int i = 0;
int j = 0;
int flag = 0;
for (i = 0; i < phonebook->size - 1; i++)
{
flag = 1;
for (j = 0; j < (phonebook->size-i-1); j++)
{
if (strcmp(phonebook->listp[j].name, phonebook->listp[j + 1].name)>0)
{
man_t tmp = phonebook->listp[j];
phonebook->listp[j] = phonebook->listp[j + 1];
phonebook->listp[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)
break;
}
printf("\n排序已完成!\n");
printf("\n");
}
void Save_Contact(contact_p phonebook) //保存所有的联系人
{
int i = 0;
FILE* pfwrite = fopen("message.txt", "w");
if (pfwrite == NULL)
{
printf("\n文件打开失败!\n");
exit(0);
}
for (i = 0; i < phonebook->size; i++)
{
fwrite(&phonebook->listp[i], sizeof(man_t), 1, pfwrite);
}
printf("\n已保存!\n");
fclose(pfwrite);
}
void Load_Contact(contact_p phonebook) //加载通讯录
{
int i = 0;
man_t tmp;
phonebook->size = 0;
FILE* pfread = fopen("message.txt", "r");
if (pfread == NULL)
{
printf("\n文件打开失败!\n");
exit(0);
}
else
{
while (fread(&tmp, sizeof(man_t), 1, pfread))
{
check_memory(phonebook);
phonebook->listp[i] = tmp;
i++;
phonebook->size++;
}
}
fclose(pfread);
}
//测试代码 test.c
#include"contact.h"
void menu()
{
printf("********************通讯录*********************\n");
printf("*********1.添加联系人 2.删除联系人*********\n");
printf("*********3.查找联系人 4.修改联系人*********\n");
printf("*********5.显示联系人 6.清空联系人*********\n");
printf("*********7.排序联系人 0.退出系统 *********\n");
printf("***********************************************\n");
}
void test()
{
contact_t myContact;
int input = 1;
init(&myContact);
Load_Contact(&myContact);
while (input)
{
menu();
printf("\n请选择->:");
scanf("%d", &input);
switch (input)
{
case ADD:
Add_Contact(&myContact);
break;
case ERASE:
Delete_Contact(&myContact);
break;
case FIND:
Find_Contact(&myContact);
break;
case MODIFY:
Modify_Contact(&myContact);
break;
case SHOW:
Show_Contact(&myContact);
break;
case EMPTY:
Empty_Contact(&myContact);
break;
case SORT:
Sort_Contact(&myContact);
break;
case EXIT:
Save_Contact(&myContact);
break;
default:
break;
}
}
}
int main()
{
test();
system("pause");
}
总结:所有的代码如上所示,在这里和大家分享一下我对通讯录的理解。
1.在“添加联系人”的时候,我们可以用一个while循环来控制,在添加成功后询问是否继续添加,使得整个代码更加人性化。
2.之前的通讯录是静态的,也就是说固定开辟1000个人的大小,当我只存储2,3个人的时候,整个空间都被浪费。在这个代码中,我选择了用动态开辟内存空间,用多少开辟多少,即实现了功能也节约了空间。
3.在主要功能的最后,我添加了两个函数将通信录的信息保存到文件中,每次打开界面都可以找到上次存储的联系人信息。这个功能更贴近我们平常使用的通讯录。
4.在使用库函数时,我们应该是有选择的使用,比如在动态开辟空间的时候,因为之前已经有了信息,此时有malloc可能还需要我们在去实现复制信息这个功能。然而在库函数中,realloc就可以实现开辟空间后,将之前的信息复制过来进行存储。此时,毫无疑问应该选择realloc。
总而言之,当我们模拟实现一个功能的时候,不要只是为了实现功能而实现功能,要考虑如何能更好的实现功能,使代码看起来更加简洁明了。