C语言程序设计 | 通讯录管理系统
Posted 凌桓丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言程序设计 | 通讯录管理系统相关的知识,希望对你有一定的参考价值。
通讯录可以用来存储个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。而一个通讯录的管理系统,应该至少具备增、删、查、改等几项功能,并要对其进行拓展。
所以我们要实现的功能如下:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 对联系人进行排序
- 通讯录应该是可扩容而非定长的
- 通讯录的数据应该存储在文件当中,以便多次使用
明确了目标,下面开始实现。
首先我们要选择合适的数据结构,对于这种线性的通讯录,顺序表无疑是最好的选择,在设置结构体的同时,还需要考虑到内存对齐的因素,将占用空间较小的成员尽量集中到一起。
同时为了通讯录的长度合适,我们运用了动态内存管理,当通讯录不够时自动扩容
typedef struct info
char name[NAME_MAX_SIZE];
char tel[TEL_MAX_SIZE];
char addr[ADDR_MAX_SIZE];
char gender[GENDER_MAX_SIZE];
int age;
//先存放四个字符型再存放整形,利用内存对齐来达到空间利用最大化
info;
typedef struct
info* data;
int capacity;
int size;
contact, *pcontact;
//采用顺序表的数据类型来存放数据
首先我们要对通讯录进行初始化
void InitContact(pcontact p)
p->data = (info*)malloc(CONTACT_SIZE * sizeof(info));
if (NULL == p->data)
printf("初始化失败!!!\\n");
exit(0);
p->capacity = CONTACT_SIZE;
p->size = 0;
通讯录扩容
int CheckCapacity(pcontact p)
assert(p);
if (p->size == p->capacity)
printf("通讯录已满,进行扩容\\n");
;
info *temp = realloc(p->data, (p->capacity + CONTACT_SIZE) * sizeof(info));
if (NULL == temp)
printf("扩容失败\\n");
return 0;
else
p->data = temp;
p->capacity += CONTACT_SIZE;
printf("扩容成功!!!\\n");
return 1;
添加联系人信息
void AddContact(pcontact p)
assert(p); //防止传入空指针,后面会一直使用
system("cls"); //清空之前的屏幕,防止画面太过杂乱
if (0 == CheckCapacity(p)) //判断通讯录是否已满,如果通讯录满且扩容失败将返回
printf("通讯录已满,添加失败\\n");
return;
printf("请输入姓名:\\n");
scanf("%s", p->data[p->size].name);
printf("请输入电话:\\n");
scanf("%s", p->data[p->size].tel);
printf("请输入性别:\\n");
scanf("%s", p->data[p->size].gender);
printf("请输入地址:\\n");
scanf("%s", p->data[p->size].addr);
printf("请输入年龄:\\n");
scanf("%d", &(p->data[p->size].age));
printf("添加成功!!!\\n");
p->size++;
添加联系人信息
void DelContact(pcontact p)
assert(p);
system("cls");
int pos, i;
char name[NAME_MAX_SIZE];
if (!p->size)
printf("通讯录为空\\n");
return;
printf("请输入要删除的人的姓名:\\n");
scanf("%s", name);
pos = GetPosition(name, p);
if (-1 == pos)
printf("此人不存在\\n");
else
for (i = pos; pos < p->size - 1; i++)
p->data[i] = p->data[i + 1];
p->size--;
printf("删除成功!!!\\n");
按照名字获取通讯录的位置
这一个是为了给后面的查找和删除模块获取位置
int GetPosition(char* name, pcontact p)
assert(p);
int pos;
for (pos = 0; pos < p->size; pos++)
if (0 == strcmp(name, p->data[pos].name))
return pos;
return -1;
查找联系人信息
void SearchContact(pcontact p)
assert(p);
system("cls");
char name[NAME_MAX_SIZE];
int pos;
printf("请输入要查找的人的姓名:\\n");
scanf("%s", name);
pos = GetPosition(name, p);
if (-1 == pos)
printf("此人不存在:\\n");
else
printf("*******************************************\\n");
printf("姓名:%s \\n", p->data[pos].name);
printf("性别:%s \\n", p->data[pos].gender);
printf("年龄:%d \\n", p->data[pos].age);
printf("地址:%s \\n", p->data[pos].addr);
printf("电话:%s \\n", p->data[pos].tel);
printf("*******************************************\\n");
printf("查找成功!!!\\n");
修改联系人信息
void ModifyContact(pcontact p)
assert(p);
system("cls");
char name[NAME_MAX_SIZE];
int pos;
printf("请输入要修改的人的姓名:\\n");
scanf("%s", name);
pos = GetPosition(name, p);
if (-1 == pos)
printf("此人不存在\\n");
else
printf("请输入修改后的姓名:\\n");
scanf("%s", p->data[pos].name);
printf("请输入修改后的电话:\\n");
scanf("%s", p->data[pos].tel);
printf("请输入修改后的性别:\\n");
scanf("%s", p->data[pos].gender);
printf("请输入修改后的年龄:\\n");
scanf("%d", &(p->data[pos].age));
printf("请输入修改后的地址:\\n");
scanf("%s", p->data[pos].addr);
printf("修改成功!!!\\n");
显示所有联系人信息
void ShowContact(pcontact p)
assert(p);
system("cls");
int i;
if (!p->size)
printf("通讯录为空\\n");
return;
for (i = 0; i < p->size; i++)
printf("*******************************************\\n");
printf("********** 第 %d 位联系人 **********\\n", i + 1);
printf("姓名:%s \\n", p->data[i].name);
printf("性别:%s \\n", p->data[i].gender);
printf("年龄:%d \\n", p->data[i].age);
printf("地址:%s \\n", p->data[i].addr);
printf("电话:%s \\n", p->data[i].tel);
printf("*******************************************\\n");
清空通讯录
void EmptyContact(pcontact p)
assert(p);
system("cls");
if (!p->size)
printf("通讯录为空\\n");
return;
else
free(p->data);
p->data = NULL;
p->size = 0;
p->capacity = 0;
printf("通讯录清空成功!!!\\n");
为了通讯录方便我们查看,我们还需要排序,因为数据量过少以及排序不是这里的主体,所以采用最简单的冒泡排序
void SortContact(pcontact p)
assert(p);
system("cls");
int i, j, flag = 1;
info temp = 0 ;
for (i = p->size; i > 0 && flag; i--)
flag = 0;
for (j = 1; j < p->size; j++)
if (strcmp(p->data[j].name, p->data[j - 1].name) < 0)
temp = p->data[j];
p->data[j] = p->data[j - 1];
p->data[j - 1] = temp;
flag = 1;
printf("排序成功!!!\\n");
同时,一个通讯录不可能每次使用都要重新输入数据,并且数据在关闭的时候会清空,所以我们要将数据的内容进行保存,而保存的方式我选择用二进制的形式保存,因为二进制的存储方式比ascii的存储方式操作更加简单和安全。唯一的缺点就是不方便查看。
保存数据
void SaveContact(pcontact p)
assert(p);
system("cls");
FILE* pf = fopen("contact.dat", "wb");
int i;
if (NULL == pf)
printf("文件打开失败\\n");
return;
for (i = 0; i < p->size; i++)
fwrite(&(p->data[i]), sizeof(info), 1, pf);
printf("通讯录保存成功\\n");
fclose(pf);
pf = NULL;
读取数据
void LoadContact(pcontact p)
assert(p);
system("cls");
FILE* pf = fopen("contact.dat", "rb");
if (NULL == pf)
printf("文件打开失败\\n");
return;
while (fread(&(p->data[p->size]), sizeof(info), 1, pf))
if (CheckCapacity(p))
p->size++;
printf("通讯录读取成功\\n");
fclose(pf);
pf = NULL;
同时,在结束时还要进行内存的释放,防止内存溢出
void EndContact(pcontact p)
free(p->data);
p->data = NULL;
p->size = 0;
p->capacity = 0;
exit(0);
在主函数方面,为了简化代码和去掉重复代码,我选择用函数指针数组来实现菜单
void Test()
int input;
contact book;
void (*p[10])(pcontact p) =
EndContact,
AddContact,
DelContact,
ModifyContact,
SearchContact,
SortContact,
ShowContact,
EmptyContact,
SaveContact,
LoadContact,
;
//利用函数指针数组简化不必要的代码
InitContact(&book);
//初始化
do
Menu();
printf("请输入要进行的操作:");
scanf("%d", &input);
if ((input <= 9 && input >= 0))
(*p[input])(&book);
else
printf("输入错误:\\n");
while (input);
就这样,一个简单的通讯录管理系统就完成了
简单演示一下,剩下的部分就不再演示了
完整代码如下:
头文件部分Contact book.h
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<Windows.h>
#define NAME_MAX_SIZE 20
#define TEL_MAX_SIZE 20
#define ADDR_MAX_SIZE 30
#define GENDER_MAX_SIZE 10
#define CONTACT_SIZE 10
typedef struct info
char name[NAME_MAX_SIZE];
char tel[TEL_MAX_SIZE];
char addr[ADDR_MAX_SIZE];
char gender[GENDER_MAX_SIZE];
int age;
//先存放四个字符型再存放整形,利用内存对齐来达到空间利用最大化
info;
typedef struct
info* data;
int capacity;
int size;
contact, *pcontact;
//采用顺序表的数据类型来存放数据
void InitContact(pcontact p);
void AddContact(pcontact p);
void DelContact(pcontact p);
void SearchContact(pcontact p);
void SortContact(pcontact p);
void ShowContact(pcontact p);
void ModifyContact(pcontact p);
void EmptyContact(pcontact p);
int CheckCapacity(pcontact p);
int GetPosition(char* name, pcontact p);
void SaveContact(pcontact p);
void LoadContact(pcontact p);
void EndContact(pcontact p);
函数实现部分Contact book.c:
#include "Contact Book.h"
void InitContact(pcontact p)
p->data = (info*)malloc(CONTACT_SIZE * sizeof(info));
if (NULL == p->data)
printf("初始化失败!!!\\n");
exit(0);
p->capacity = CONTACT_SIZE;
p->size = 0;
void AddContact(pcontact p)
assert(p);
system("cls");
if (0 == CheckCapacity(p))
printf("通讯录已满,添加失败\\n");
return;
printf("请输入姓名:\\n");
scanf("%s", p->data[p->size].name);
printf("请输入电话:\\n");
scanf("%s", p->data[p->size].tel);
printf("请输入性别:\\n");
scanf("%s", p->data[p->size].gender);
printf("请输入地址:\\n");
scanf("%s", p->data[p->size].addr);
printf("请输入年龄:\\n");
scanf("%d", &(p->data[p->size].age));
printf("添加成功!!!\\n");
p->size++;
void DelContact(pcontact p)
assert(p);
system("cls");
int pos, i;
char name[NAME_MAX_SIZE];
if (!p->size)
printf("通讯录为空\\n");
return;
printf("请输入要删除的人的姓名:\\n");
scanf("%s", name);
pos = GetPosition(name, p);
if (-1 == pos)
printf("此人不存在\\n");
else
for (i = pos; pos < p->size - 1; i++)
p->data[i] = p->data[i + 1];
p->size--;
printf("删除成功!!!\\n");
void ShowContact(pcontact p)
assert(p);
system("cls");
int i;
if (!p->size)
printf("通讯录为空\\n");
return;
for (i = 0; i < p->size; i++)
printf("*******************************************\\n");
printf("********** 第 %d 位联系人 **********\\n", i + 1);
printf("姓名:%s \\n", p->data[i].name);
printf("性别:%s \\n", p->data[i].gender);
printf("年龄:%d \\n", p->data[i].age);
printf("地址:%s \\n", p->data[i].addr);
printf("电话:%s \\n", p->data[i].tel);
printf("*******************************************\\n");
void ModifyContact(pcontact p)
assert(p);
system("cls");
char name[NAME_MAX_SIZE];
int pos;
printf("请输入要修改的人的姓名:\\n");
scanf("%s", name);
pos = GetPosition(name, p);
if (-1 == pos)
printf("此人不存在\\n");
else
printf("请输入修改后的姓名:\\n");
scanf("%s", p->data[pos].name);
printf("请输入修改后的电话:\\n");
scanf("%s", p->data[pos].tel);
printf("请输入修改后的性别:\\n");
scanf("%s", p->data[pos].gender);
printf("请输入修改后的年龄:\\n");
scanf("%d", &(p->data[pos].age));
printf("请输入修改后的地址:\\n");
scanf("%s", p->data[pos].addr);
printf("修改成功!!!\\n");
void SearchContact(pcontact p)
assert(p);
system("cls");
char name[NAME_MAX_SIZE];
int pos;
printf("请输入要查找的人的姓名:\\n");
scanf("%s", name);
pos = GetPosition(name, p);
if (-1 == pos)
printf("此人不存在:\\n");
else
printf("*******************************************\\n");
printf("姓名:%s \\n", p->data[pos].name);
printf("性别:%s \\n", p->data[pos].gender);
printf("年龄:%d \\n", p->data[pos].age);
printf("地址:%s \\n", p->data[pos].addr);
printf("电话:%s \\n", p->data[pos].tel);
printf("*******************************************\\n");
printf("查找成功!!!\\n");
int GetPosition(char* name, pcontact p)
assert(p);
int pos;
for (pos = 0; pos < p->size; pos++)
if (0 == strcmp(name, p->data[pos].name))
return pos;
return -1;
void EmptyContact(pcontact p)
assert(p);
system("cls");
if (!p->size)
printf("通讯录为空\\n");
return;
else
free(p->data);
p->data = NULL;
p->size = 0;
p->capacity = 0;
printf("通讯录清空成功!!!\\n");
int CheckCapacity(pcontact p)
assert(p);
if (p->size == p->capacity)
printf("通讯录已满,进行扩容\\n");
;
info *temp = realloc(p->data, (p->capacity + CONTACT_SIZE) * sizeof(info));
if (NULL == temp)
printf("扩容失败\\n");
return 0;
else
p->data = temp;
p->capacity += CONTACT_SIZE;
printf("扩容成功!!!\\n");
return 1;
void SortContact(pcontact p)
assert(p);
system("cls");
int i, j, flag = 1;
info temp = 0 ;
for (i = p->size; i > 0 && flag; i--)
flag = 0;
for (j = 1; j < p->size; j++)
if (strcmp(p->data[j].name, p->data[j - 1].name) < 0)
temp = p->data[j];
p->data[j] = p->data[j - 1];
p->data[j - 1] = temp;
flag = 1;
printf("排序成功!!!\\n");
void SaveContact(pcontact p)
assert(p);
system("cls");
FILE* pf = fopen("contact.dat", "wb");
int i;
if (NULL == pf)
printf("文件打开失败\\n");
return;
for (i = 0; i < p->size; i++)
fwrite(&(p->data[i]), sizeof(info), 1, pf);
printf("通讯录保存成功\\n");
fclose(pf);
pf = NULL;
void LoadContact(pcontact p)
assert(p);
system("cls");
FILE* pf = fopen("contact.dat", "rb");
if (NULL == pf)
printf("文件打开失败\\n");
return;
while (fread(&(p->data[p->size]), sizeof(info), 1, pf))
if (CheckCapacity(p))
p->size++;
printf("通讯录读取成功\\n");
fclose(pf);
pf = NULL;
void EndContact(pcontact p)
free(p->data);
p->data = NULL;
p->size = 0;
p->capacity = 0;
exit(0);
测试部分:
test.c
#include "Contact Book.h"
void Menu()
printf("************************************************\\n");
printf("** 0.退出程序 1.添加联系人 **\\n");
printf("** 2.删除联系人 3.修改联系人 **\\n");
printf("** 4.查找联系人 5.通讯录排序 **\\n");
printf("** 6.显示所有联系人 7.删除所有联系人 **\\n");
printf("** 8.保存通讯录 9.读取通讯录 **\\n");
printf("************************************************\\n");
void Test()
int input;
contact book;
void (*p[10])(pcontact p) =
EndContact,
AddContact,
DelContact,
ModifyContact,
SearchContact,
SortContact,
ShowContact,
EmptyContact,
SaveContact,
LoadContact,
;
//利用函数指针数组简化不必要的代码
InitContact(&book);
//初始化
do
Menu();
printf("请输入要进行的操作:");
scanf("%d", &input);
if ((input <= 9 && input >= 0))
(*p[input])(&book);
else
printf("输入错误:\\n");
while (input);
int main()
Test();
return 0;
github链接:https://github.com/HONGYU-LEE/test/tree/master/project/Contact%20Book
以上是关于C语言程序设计 | 通讯录管理系统的主要内容,如果未能解决你的问题,请参考以下文章