C语言程序设计 | 通讯录管理系统

Posted 凌桓丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言程序设计 | 通讯录管理系统相关的知识,希望对你有一定的参考价值。

通讯录可以用来存储个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。而一个通讯录的管理系统,应该至少具备增、删、查、改等几项功能,并要对其进行拓展。
所以我们要实现的功能如下:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 对联系人进行排序
  8. 通讯录应该是可扩容而非定长的
  9. 通讯录的数据应该存储在文件当中,以便多次使用

明确了目标,下面开始实现。

首先我们要选择合适的数据结构,对于这种线性的通讯录,顺序表无疑是最好的选择,在设置结构体的同时,还需要考虑到内存对齐的因素,将占用空间较小的成员尽量集中到一起。
同时为了通讯录的长度合适,我们运用了动态内存管理,当通讯录不够时自动扩容

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语言程序设计 | 通讯录管理系统的主要内容,如果未能解决你的问题,请参考以下文章

用c语言实现通讯录(含文件操作)

C语言 写一个通讯录

C语言实现通讯录(文件操作)

用c语言程序设计一个学生通讯录系统

c语言程序设计——编一个通讯录管理程序:序号 姓名 电话 地址

c语言通讯录程序