【C语言】实现通讯录

目录

  • 一、项目整体分析
  • 二、各部分分析
    • 2.1头文件
    • 2.2.cpp文件
  • 三、实现代码
  • 四、效果展示

一、项目整体分析

通讯录项目用于针对c语言初学者练手使用,涉及到数组,指针,结构体,枚举等知识。
通讯录需要实现对用户信息的存储,新增,删除,查找,排序,修改等内容,每位用户的信息包含姓名,性别,年龄,电话号码,住址等信息。因此需要创建一个用户信息结构体,结构体成员包含姓名,性别,年龄,电话号码,住址信息。

(1)在初级阶段由于无法让程序自动开辟内存,因此需要额外创建一个结构体,结构体成员包含用户信息成员变量,当前结构体指针变量(用于指向存储位置),成员信息最大存储能力。

(2)当初级阶段实现后,需要利用动态内存管理的方法,使开辟用户信息的内存可以实现自动开辟。

(3)当完成上述两个阶段后,需要利用文件存储的方式,将已经存储在通讯录中的用户信息存储在磁盘中,当打开通讯录文件后,自动读取数据,同时在关闭通讯录时自动保存通讯录。

二、各部分分析

由于实现通讯录项目需要许多头文件和函数,因此需要将项目分为两大部分:头文件和.cpp文件,头文件用于声明一些函数,引入一些库函数,创建一些宏定义和结构体。.cpp文件用于对函数进行实现。

2.1头文件

需要引入两个头文件:一个公共头文件utili.h 一个通讯录头文件contact.h。其中公共头文件引入一些库函数。通讯录头文件负责声明通讯录中需要用到的函数,创建宏定义和结构体

2.2.cpp文件

需要引入两个.cpp文件:一个函数实现文件Contact.cpp 一个主函数文件MainContact.cpp。

三、实现代码

注:(1)表示这段代码是实现项目整体分析中第一个阶段,(2) (3)相同

//utili.h
#ifndef _UTILI_H_
#define _UTILI_H_
#include
#include
#include
#include
#include
#endif /* _UTILI_H_ */
//
#ifndef _CONTACT_H_
#define _CONTACT_H_


//Contact.h
#include"utili.h"//首先引入公共头文件

enum {QUIT, ADD, DEL, FIND, MODIFY, SHOW, CLEAR, SORT};//定义菜单中的选项

#define MAX_NAME_SIZE 10 		//定义用户姓名最大字符数
#define MAX_SEX_SIZE 3			//定义用户性别最大字符数
#define MAX_AGE_SIZE 100		//定义用户年龄最大数		
#define MAX_TEL_SIZE 12			//定义电话号码最大位数
#define MAX_ADDRESS_SIZE 128	//定义地址信息最大字符数
#define MAX_CONTACT_SIZE 8		//定义最大存储通讯录用户个数(1)
#define DEFAULT_CONTACT_SIZE 2	//定义默认存储通讯录用户个数(2)

//打印菜单
void Menu();

//定义通讯录人员信息
typedef struct PersonInfo
{
	char name[MAX_NAME_SIZE];
	char sex[MAX_SEX_SIZE];
	int age;
	char tel[MAX_TEL_SIZE];
	char address[MAX_ADDRESS_SIZE];
}PersonInfo;

//定义通讯录结构
typedef struct Contact
{
	//PersonInfo cont[MAX_CONTACT_SIZE];(1)
	PersonInfo *cont(2)//需要动态开辟空间,因此设为指针变量
	size_t     capacity;		//通讯录最大存储用户个数
	size_t     size;			//通讯录当前指针指向位置
}Contact;

//初始化通讯录
void InitContact(Contact* pcont);

//查验通讯录是否已满
bool IsFullContact(Contact* pcont);

//增加通讯录
void AddContact(Contact* pcont);

//显示通讯录
void ShowContact(Contact* pcont);

//查找通讯录信息
int FindContact(Contact* pcont);

//清除通讯录
void ClearContact(Contact* pcont);

//删除通讯录成员
void DelContact(Contact* pcont);

//修改通讯录成员
void ModifyContact(Contact* pcont);

//对通讯录成员进行排序(bubble)
void SortContact_bubble(Contact* pcont);

//使用快排函数(qsort)
void SortContact_qsort(Contact* pcont);

#endif /* _UTILI_H_ */





//Contact.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"				//引入通讯录头文件


//打印菜单
void Menu()
{
	printf("********************通 讯 录***********************\n");
	printf("*      [1]Add                       [2]Del        *\n");
	printf("*      [3]Find                      [4]Modif      *\n");
	printf("*      [5]Show                      [6]Clear      *\n");
	printf("*      [7]Sort                      [0]Quit       *\n");
	printf("********************通 讯 录***********************\n");
}

//初始化通讯录
void InitContact(Contact* pcont)
{
	assert(pcont != NULL);
	//memset(pcont->cont, 0, sizeof(PersonInfo) * MAX_CONTACT_SIZE);(1)
	pcont->cont = (PersonInfo*)malloc(sizeof(PersonInfo)*DEFAULT_CONTACT_SIZE);(2)
	memset(pcont->cont, 0sizeof(PersonInfo) * DEFAULT_CONTACT_SIZE);(2)
	pcont->capacity = MAX_CONTACT_SIZE;(1)
	pcont->capacity = DEFAULT_CONTACT_SIZE;(2)
	pcont->size = 0;
}

static bool _Inc(Contact* pcont)//(2)
{
	PersonInfo* new_cont = (PersonInfo*)realloc(pcont->cont, sizeof(PersonInfo) * 	pcont->capacity * 2);	//使用realloc进行扩容
	if (new_cont == NULL)
	{
		printf("扩容失败,内存不足\n");
		return false;
	}
	pcont->cont = new_cont;//扩容成功,修改cont指针
	pcont->capacity *= 2;//扩容成功,修改容量
	return true;
}

//判断通讯录是否已满
bool IsFullContact(Contact* pcont)
{
	assert(pcont != NULL);
	return pcont->size >= pcont->capacity;
}

//添加通讯录用户
void AddContact(Contact* pcont)
{
	assert(pcont != NULL);
	//if (IsFullContact(pcont))//(1)
	if(IsFullContact(pcont) && !_Inc(pcont))//(2)
	{
		printf("通讯录空间已满,不能新增信息");
		return;
	}

	printf("姓名:>");
	scanf("%s", pcont->cont[pcont->size].name);
	printf("性别:>");
	scanf("%s", pcont->cont[pcont->size].sex);
	printf("年龄:>");
	scanf("%d", &pcont->cont[pcont->size].age);
	printf("电话号码:>");
	scanf("%s", pcont->cont[pcont->size].tel);
	printf("地址:>");
	scanf("%s", pcont->cont[pcont->size].address);

	pcont->size++;
	printf("添加完成!!!\n");
}

//展示当前通讯录已存用户信息
void ShowContact(Contact* pcont)
{
	assert(pcont != NULL);
	printf("***************************************************\n");
	printf("*%-8s%-7s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < pcont->size; i++)
	{
		printf("*%-8s%-7s%-6d%-13s%s\n",pcont->cont[i].name,  
										pcont->cont[i].sex, 
										pcont->cont[i].age, 
										pcont->cont[i].tel, 
										pcont->cont[i].address);
	} 
}

//查找通讯录成员
int FindContact(Contact* pcont)
{
	assert(pcont != NULL);
	printf("请输入要查找的姓名:>");
	char name[MAX_NAME_SIZE] = {0};
	scanf("%s", name);
	for (int i = 0; i < pcont->size; i++)
	{
		if (strcmp(pcont->cont[i].name, name) == 0)
		{
			printf("*%-8s%-7s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "地址");
			printf("*%-8s%-7s%-6d%-13s%s\n",pcont->cont[i].name,
											pcont->cont[i].sex,
											pcont->cont[i].age,
											pcont->cont[i].tel,
											pcont->cont[i].address);
			return i;
		}
	}
	printf("对不起,没找到\n");
	return -1;
}

//清除通讯录
void ClearContact(Contact* pcont)
{
	assert(pcont != NULL);
	pcont->size = 0;
	printf("清除完成!!!\n");
}

//删除通讯录成员
void DelContact(Contact* pcont)
{
	assert(pcont != NULL);
	printf("请输入要删除的名字:>");
	char name[MAX_NAME_SIZE] = { 0 };
	scanf("%s", name);
	int i;
	for (i = 0; i < pcont->size; i++)
	{
		if (strcmp(pcont->cont[i].name, name) == 0)
			break;
	}
	if (i >= pcont->size)
	{
		printf("对不起,您所删除的名字不存在\n");
		return;
	}
	for (int k = i; k < pcont->size - 1; k++)
		pcont->cont[k] = pcont->cont[k + 1];
	pcont->size--;
	printf("删除完成!!!\n");
}

//修改通讯录成员
void ModifyContact(Contact* pcont)
{
	assert(pcont != NULL);
	printf("请输入要修改的名字:>");
	char name[MAX_NAME_SIZE] = { 0 };
	scanf("%s", name);
	int i;
	for (i = 0; i < pcont->size; i++)
	{
		if (strcmp(pcont->cont[i].name, name) == 0)
			break;
	}
	if (i >= pcont->size)
	{
		printf("对不起,您所要修改的名字不存在\n");
		return;
	}
	printf("你要修改什么信息(1-姓名 2-性别 3-年龄 4-电话 5-住址)\n");
	int select;
	scanf("%d", &select);
	switch (select)
	{
	case 1:
		printf("请输入要修改的名字:>");
		scanf("%s", pcont->cont[i].name);
		break;
	case 2:
		printf("请输入要修改的性别:>");
		scanf("%s", pcont->cont[i].sex);
		break;
	case 3:
		printf("请输入要修改的年龄:>");
		scanf("%d", &pcont->cont[i].age);
		break;
	case 4:
		printf("请输入要修改的电话:>");
		scanf("%s", pcont->cont[i].tel);
		break;
	case 5:
		printf("请输入要修改的住址:>");
		scanf("%s", pcont->cont[i].address);
		break;
	}
	printf("修改完成!!!\n");
}

//对通讯录成员进行排序
//方法一利用冒泡排序
void SortContact_bubble(Contact* pcont)
{	
	//采用冒泡排序
	assert(pcont != NULL);
	//qsort(pcont, pcont->size, sizeof(pcont->cont[0]), compar);
	for (int i = 0; i < pcont->size-1; i++)
	{
		for (int j = 0; j < pcont->size - 1 - i; j++)
		{
			if (strcmp(pcont->cont[j].name, pcont->cont[j + 1].name) > 0 )
			{
				PersonInfo tmp = pcont->cont[j];
				pcont->cont[j] = pcont->cont[j + 1];
				pcont->cont[j + 1] = tmp;
			}
		}
	}
	printf("排序完成!!!\n");
}

//方法二利用快排函数
int compar_name(Contact* pcont->cont.name1, pcont->cont.name2)
{
	return strcmp(pcont->cont.name1, pcont->cont.name2);
}

void SortContact_qsort(Contact* pcont)
{
	assert(pcont != NULL);
	qsort(pcont, pcont->size, sizeof(pcont->cont[0]), compar_name);
}

//摧毁通讯录目的是为了防止内存泄漏
void DestoryContact(Contact* pcont)
{
	assert(pcont != NULL);
	free(pcont->cont);//释放内存
	pcont->cont = NULL;//预防野指针

	pcont->capacity = pcont->size = 0;

}

//存储通讯录(3)
void SaveContact(Contact* pcont)
{
	assert(pcont != NULL);
	FILE* fp = fopen("cont.dat", "w");
	if (fp == NULL)
	{
		printf("写入通讯录文件失败\n");
		return;
		
	}
	for (int i = 0; i < pcont->size; i++)
	{
		fprintf(fp, "*%-8s%-7s%-6d%-13s%s\n", pcont->cont[i].name,
			pcont->cont[i].sex,
			pcont->cont[i].age,
			pcont->cont[i].tel,
			pcont->cont[i].address);
	}
	fclose(fp);
}

//数据的加载(3)
void LoadContact(Contact* pcont)
{
	assert(pcont != NULL);

	FILE* fp = fopen("\cont.dat", "r");
	if (fp == NULL);
	{
		printf("读取通讯录文件失败\n");
		return;
	}
	int idx = 0;
	while(1)
	{
		if (IsFullContact(pcont) && !_Inc(pcont))
			break;
		int res = fscanf(fp, "*%s %s %d %s %s\n", pcont->cont[idx].name,
										pcont->cont[idx].sex,
										&pcont->cont[idx].age,
										pcont->cont[idx].tel,
										pcont->cont[idx].address);
		if (res == EOF)
			break;
		idx++;
		pcont->size++;
	}
	fclose(fp);
}


//MainContact.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"//引入通讯录头文件

void main()
{
	Contact cont;//先进行通讯录的创建和初始化
	InitContact(&cont);

	int select = 1;
	while (select)
	{
		Menu();				//打印开始菜单
		printf("请选择:>");
		scanf("%d", &select);

		if (select == QUIT)
			break;
		switch (select)
		{
		case ADD:
			IsFullContact(&cont); //判断通讯录是否已满
			AddContact(&cont);	  //添加用户信息
			break;
		case DEL:
			DelContact(&cont);	  //删除用户信息
			break;
		case FIND:
			FindContact(&cont);		//查找用户信息
			break;
		case MODIFY:
			ModifyContact(&cont);	//修改用户信息
			break;
		case SHOW:
			ShowContact(&cont);     //展示通讯录内容
			break;
		case CLEAR:
			ClearContact(&cont);	//清除通讯录
			break;
		case SORT:
			SortContact_bubble(&cont);	//对通讯录进行排序
			break;

		}
	}
	SaveContact(&cont);
	DestoryContact(&cont);
}

四、效果展示

开始运行
【C语言】实现通讯录_第1张图片

选择1,添加用户
【C语言】实现通讯录_第2张图片
选择5,展示
【C语言】实现通讯录_第3张图片
选择4,修改用户信息
【C语言】实现通讯录_第4张图片
选择2,删除用户信息
【C语言】实现通讯录_第5张图片
选择7,对用户信息进行排序,注意(这里的排序是通过冒泡排序对用户姓名进行排序,用户姓名排序的原理是利用其对应的ASCII码值进行排序),通过对排序函数的修改,可以实现通过年龄,电话住址等信息进行排序。
【C语言】实现通讯录_第6张图片
选择3,进行信息查找
【C语言】实现通讯录_第7张图片
如果查找的姓名不存在,会报找不到的错误【C语言】实现通讯录_第8张图片

你可能感兴趣的:(c语言,c语言,开发语言)