C/C++版动态通讯录(可保存信息)

2023-04-12 13:56:02 浏览数 (1)

1、思路以及要实现的功能

通讯录就是为了存储许多联系人的不同方面的信息如名字、电话、地址、年龄、性别等,除此之外,还要实现增删查改还有打印通讯录等功能,所以我们先把要实现的功能列出来:

  • 增加联系人
  • 删除联系人
  • 搜索联系人
  • 修改联系人信息
  • 按年龄大小排序联系人
  • 打印联系人信息

2、详细步骤

2.1 打印菜单界面(建一个源文件test.c)
代码语言:javascript复制
void menu()
{
	printf("********************************n");
	printf("******  1.add    2.delete ******n");
	printf("******  3.search 4.modify ******n");
	printf("******  5.sort   6.print  ******n");
	printf("************ 0.exit  ***********n");
	printf("*******************************n");
}
2.2 写出我们的主函数,利用do-while循环,并把即将要实现的功能先放在主函数内

在写函数之前,我们也要先定义一个结构体来存放联系人的信息还有联系人个数以及通讯录的最大容量,所以我们建一个头文件,称为contact.h,用来存放这些信息。

代码语言:javascript复制
#pragma once
#include<stdio.h>

#define NAME_MAX 20//名字的最大长度
#define SEX_MAX 6
#define TELE_MAX 12//号码的最大位数
#define ADDR_MAX 30//地址的最大位数
#define ADD_PEO 1//每次拓展通讯录的人数
#define PEO_NUM 3//通讯录的初始容量

//类型的定义
typedef struct Peoinfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}Peoinfo;

typedef struct Contact
{
	Peoinfo *data;//指向动态申请的空间,存放联系人的信息
	int sz;//记录通讯录中有效信息的个数
	int capacity;//记录当前通讯录的最大容量
}Contact

除此之外,我们可以利用枚举将函数的选项封装一下!(存放在test.c)

代码语言:javascript复制
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
}

这样子我们就可以写主函数啦!

代码语言:javascript复制
#include "contact.h"

int main()
{
	Contact con;//创建通讯录
	InitContact(&con);//初始化通讯录
	int input=0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d",&input);
		switch(input)
		{
			case ADD:
			AddContact(&con);//增加人的信息
			break;
		case DEL:
			DelContact(&con);//删除人的信息
			break;
		case SEARCH:
			SearchContact(&con);//查找联系人
			break;
		case MODIFY:
			ModifyContact(&con);//修改信息
			break;
		case SORT:
			SortContact(&con);//排序
			break;
		case PRINT:
			PrintContact(&con);//打印通讯录
			break;
		case EXIT:
			SaveContact(&con);//保存通讯录
			DestoryContact(&con);//销毁信息
			printf("退出通讯录!n");
			break;
		default:
			printf("选择错误!n");
			break;
		}
	}while(input);
	return 0;
}

好啦!这样子我们就把轮廓写好了,现在就要一个个的实现每个函数的功能了!

2.3初始化函数InitContact与加载函数LoadContact

这里我们要先利用动态内存函数位信息开辟内存,然后用文件操作打开我们保存信息的文件中读取信息。

代码语言:javascript复制
void InitContact(Contact* pc)
{
	pc->data=(Peoinfo*)malloc(PEO_NUM * sizeof(Peoinfo));
	if(pc->data==NULL)
	{
		perror("InitContact");
		return;
	}
	pc->sz=0;
	pc->capacity=PEO_NUM;

	LoadContact(pc);//加载已有的通讯录
}
代码语言:javascript复制
void LoadContact(Contact* pc)
{
	File* pf = fopen("contact.txt","r");//创建或访问contact.txt读取信息
	if(pf == NULL)
	{
		perror("LoadContact");
		return;
	} 
	Peoinfo tmp={0};
	while(fread(&tmp,sizeof(Peoinfo),1,pf))
	{
		if(pc->sz==pc->capacity)
		{
			Peoinfo* ptr=(Peoinfo*)realloc(pc,(ADD_PEO pc->capacity)sizeof(Peoinfo));
			if(ptr!=NULL)
			{
				pc->data=ptr;
				pc->capacity =ADD_PEO;
			}
			else
			{
				perror("AddContact");
				printf("读取通讯录失败!n");
				return;
			}
		}
		pc->data[pc->sz]=tmp;
		pc->sz  ;
	}

	fclose(pf);
	pf=NULL;
}

这里我们创建一个Contact.c源文件来存放各自函数的功能,然后将函数的各个声明放到Contact.h中,以下也如此。

2.4 增加联系人函数AddContact
代码语言:javascript复制
void AddContact(Contact* pc)
{
	if(pc->sz==pc->capacity)
	{
		(Peoinfo*)ptr=(Peoinfo*)realloc(pc,(ADD_PEO pc->capacity) * sizeof(Peoinfo));
		if(ptr!=NULL)
		{
			pc->data=ptr;
			pc->capacity =ADD_PEO;
		}
		else
		{
			perror("AddContact");
			printf("读取通讯录失败!n");
			return;
		}
	}
	printf("请输入名字:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz  ;
	printf("增加成功!n");
}
2.5删除联系人函数DelContact

在实现该函数之前,我们发现,删除联系人函数与接下来的查找联系人、修改信息等函数有个共同的特点,那就是要先判断这个要做动作的联系人存不存在,所以考虑这点我们决定先封装一个FindByName函数用来判断这个人以及返回这个人信息的位置。

代码语言:javascript复制
#include <string.h>	

static int FindByName(Contact* pc,char*name)
{
	int i=0;
	for(i=0;i<pc->sz;i  )
	{
		if(strcmp(pc->data[i].name,name)==0)
			return i;
	}
	return -1;
}

接下来我们就来实现删除联系人函数:

代码语言:javascript复制
void DelContact(Contact* pc)
{
	char delname[NAME_MAX]={0};
	if (pc->sz == 0)
	{
		printf("通讯录为空,无须删除!n");
		return;
	}
	printf("请输入要删除人的名字:");
	scanf("%s", delname);
	//查找要删除的人
	int pos=FindByName(pc,delname);
	if(pos==-1)
	{
		printf("查无此人的信息!n");
		return;
	}
	else
	{
		int i=0;
		for(i=pos;i<pc->sz-1;i  )
		{
			pc->data[i]=pc->data[i 1];
		}
		pc->sz--;
		printf("删除联系人成功!n");
	}
}
2.6 查找联系人函数SearchContact与打印函数PrintContact

查找函数的功能是查找通讯录中是否有此人,并将其打印出来,所以我们可以顺便的把打印函数PrintContact实现。

代码语言:javascript复制
void PrintContact(Contact* pc)
{
	//打印标题
	printf("****************************************************************************n");
	printf("|姓名                |性别  |年龄  |电话号码    |地址                      |n");
	if (pc->sz == 0)
	{
		printf("通讯录无信息!n");
		printf("****************************************************************************n");
		return;
	}
	for (int i = 0; i < pc->sz; i  )
	{
		printf("|%-20s|%-6s|%-6d|%-12s|%-26s|n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
	}
	printf("****************************************************************************n");
	printf("n");
}

接下来实现查找联系人函数:

代码语言:javascript复制
void SearchContact(Contact* pc)
{
	char findname[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无须删除!n");
		return;
	}
	printf("请输入要查找的人的名字:");
	scanf("%s", findname);
	int pos=FindByName(pc,findname);
	if (pos == -1)
	{
		printf("查无此人的信息!n");
		return;
	}
	printf("****************************************************************************n");
	printf("|姓名                |性别  |年龄  |电话号码    |地址                      |n");
	printf("|%-20s|%-6s|%-6d|%-12s|%-26s|n", pc->data[pos].name, pc->data[pos].sex, pc->data[pos].age, pc->data[pos].tele, pc->data[pos].addr);
	printf("****************************************************************************n");
	printf("n");
}
2.7 修改信息函数ModifyContact
代码语言:javascript复制
void ModifyContact(Contact* pc)
{
	char findname[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无须删除!n");
		return;
	}
	printf("请输入要查找的人的名字:");
	scanf("%s", findname);
	int pos=FindByName(pc,findname);
	if (pos == -1)
	{
		printf("查无此人的信息!n");
		return;
	}
	printf("请输入名字:");
	scanf("%s", pc->data[pos].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pos].sex);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入电话:");
	scanf("%s", pc->data[pos].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pos].addr);
	printf("修改成功!n");
}
2.8 排序函数SortContact

这里使用的是按年龄排序(冒泡排序),读者可按自己的需求实现不同的方法函数。

代码语言:javascript复制
void SortContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录无信息,无法排序!n");
		return;
	}
	int i=0,j=0;
	for(i=0;i<pz->sz-1;i  )
	{
		int flag=1;
		for(j=0;j<pz->sz-1-i;j  )
		{
			if(pz->data[j].age>pz->data[[j 1].age)
			{
				Peoinfo tmp[2];
				tmp[0] = pc->data[j];
				pc->data[j] = pc->data[j   1];
				pc->data[j   1] = tmp[0];
				flag=0;
			}
		}
		if(flag==1)
			break;
	}
	printf("排序完成!n");
}
2.9 保存信息函数SaveContact与销毁数据函数DestoryContact

通讯录的大体功能我们都实现了,剩下的就是保存我们的信息到文本中与将各个数据置零了。我们先实现保存函数SaveContact:

代码语言:javascript复制
void SaveContact(Contact* pc)
{
	File* pf=fopen("contact.txt","w");
	if(pf==NULL)
	{
		perror("SaveContact");
		return;
	}
	int i=0;
	for(i=0;i<pc->sz;i  )
	{
		fwrite(pc->data i,sizeof(Peoinfo),1,pf);
	}
	fclose(pf);
	pf=NULL;
}

实现下面的销毁数据函数DestoryContact

代码语言:javascript复制
void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc->data=NULL;
	pc->sz=0;
	pc->capacity=0;
}

完结撒花!!

3、源码

test.c

代码语言:javascript复制
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
	printf("********************************n");
	printf("******  1.add    2.delete ******n");
	printf("******  3.search 4.modify ******n");
	printf("******  5.sort   6.print  ******n");
	printf("************ 0.exit  ***********n");
	printf("*******************************n");
}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};
int main()
{
	Contact con;//创建通讯录
	InitContact(&con);//初始化通讯录
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);//增加人的信息
			break;
		case DEL:
			DelContact(&con);//删除人的信息
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case PRINT:
			PrintContact(&con);//打印通讯录
			break;
		case EXIT:
			SaveContact(&con);//保存通讯录
			DestoryContact(&con);
			printf("退出通讯录!n");
			break;
		default:
			printf("选择错误!n");
			break;
		}
	} while (input);
	return 0;
}

contact.h

代码语言:javascript复制
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 6
#define TELE_MAX 12
#define ADDR_MAX 30
#define ADD_PEO 1
#define PEO_NUM 3
//#define PEO_MAX 1000

//类型的定义
typedef struct Peoinfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}Peoinfo;

//动态版本
typedef struct Contact
{
	Peoinfo *data;//指向动态申请的空间,存放联系人的信息
	int sz;//记录通讯录中有效信息的个数
	int capacity;//记录当前通讯录的最大容量
}Contact;

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

//增加人的信息
void AddContact(Contact* pc);

//打印通讯录
void PrintContact(const Contact* pc);

//输出人的信息
void DelContact(Contact* pc);

//按名字查找
int FindByName(Contact* pc, char* name);

//查找信息
void SearchContact(Contact* pc);

//修改信息
void ModifyContact(Contact* pc);

//排序信息
void SortContact(Contact* pc);

//销毁通讯录
void DestoryContact(Contact* pc);

//保存通讯录
void SaveContact(Contact* pc);

//加载通讯录
void LoadContact(Contact* pc);

contact.c

代码语言:javascript复制
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"

void LoadContact(Contact* pc)
{
	FILE* pf = fopen("contact.txt", "r");
	if (pf == NULL)
	{
		perror("LoadContact");
		return;
	}
	Peoinfo tmp = { 0 };
	while (fread(&tmp, sizeof(Peoinfo), 1, pf))
	{
		if (pc->sz == pc->capacity)
		{
			Peoinfo* ptr = (Peoinfo*)realloc(pc->data, (pc->capacity   ADD_PEO) * sizeof(Peoinfo));
			if (ptr != NULL)
			{
				pc->data = ptr;
				pc->capacity =ADD_PEO;
			}
			else
			{
				perror("AddContact");
				printf("读取通讯录失败!n");
				return;
			}
		}
		pc->data[pc->sz] = tmp;
		pc->sz  ;
	}

	fclose(pf);
	pf = NULL;
}

void InitContact(Contact* pc)
{
	pc->data = (Peoinfo*)malloc(PEO_NUM * sizeof(Peoinfo));
	if (pc->data == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->sz = 0;
	pc->capacity = PEO_NUM;
	//加载通讯录
	LoadContact(pc);
}

void AddContact(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		Peoinfo* ptr = (Peoinfo*)realloc(pc->data, (pc->capacity   ADD_PEO) * sizeof(Peoinfo));
		if (ptr != NULL)
		{
			pc->data=ptr;
			pc->capacity  = ADD_PEO;
			printf("增加容量成功!n");
		}
		else
		{
			perror("AddContact");
			printf("增加联系人失败!n");
			return;
		} 
	}
	printf("请输入名字:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz  ;
	printf("增加成功!n");
}

void PrintContact(const Contact* pc)
{
	//打印标题
	printf("****************************************************************************n");
	printf("|姓名                |性别  |年龄  |电话号码    |地址                      |n");
	if (pc->sz == 0)
	{
		printf("通讯录无信息!n");
		printf("****************************************************************************n");
		return;
	}
	for (int i = 0; i < pc->sz; i  )
	{
		printf("|%-20s|%-6s|%-6d|%-12s|%-26s|n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
	}
	printf("****************************************************************************n");
	printf("n");
}

static int FindByName(Contact* pc,char* name)
{
	for (int i = 0; i < pc->sz; i  )
	{
		if (strcmp( pc->data[i].name,name) == 0)
			return i;
	}
	return -1;
}

void DelContact(Contact* pc)
{
	char delname[NAME_MAX]={0};
	if (pc->sz == 0)
	{
		printf("通讯录为空,无须删除!n");
		return;
	}
	printf("请输入要删除人的名字:");
	scanf("%s", delname);
	//查找要删除的人
	int pos =FindByName(pc, delname);
	if (pos == -1)
	{
		printf("查无此人的信息!n");
		return;
	}
	for (int i = pos; i < pc->sz-1; i  )
	{
		pc->data[i] = pc->data[i   1];
	}
	pc->sz--;
	printf("删除成功!n");
}

void SearchContact(Contact* pc)
{
	char findname[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无须删除!n");
		return;
	}
	printf("请输入要查找的人的名字:");
	scanf("%s", findname);
	int pos = FindByName(pc, findname);
	if (pos == -1)
	{
		printf("查无此人的信息!n");
		return;
	}
	printf("****************************************************************************n");
	printf("|姓名                |性别  |年龄  |电话号码    |地址                      |n");
	printf("|%-20s|%-6s|%-6d|%-12s|%-26s|n", pc->data[pos].name, pc->data[pos].sex, pc->data[pos].age, pc->data[pos].tele, pc->data[pos].addr);
	printf("****************************************************************************n");
	printf("n");
}

void ModifyContact(Contact* pc)
{
	char findname[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无须删除!n");
		return;
	}
	printf("请输入要查找的人的名字:");
	scanf("%s", findname);
	int pos = FindByName(pc, findname);
	if (pos == -1)
	{
		printf("查无此人的信息!n");
		return;
	}
	printf("请输入名字:");
	scanf("%s", pc->data[pos].name);
	printf("请输入性别:");
	scanf("%s", pc->data[pos].sex);
	printf("请输入年龄:");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入电话:");
	scanf("%s", pc->data[pos].tele);
	printf("请输入住址:");
	scanf("%s", pc->data[pos].addr);
	printf("修改成功!n");
}

void SortContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录无信息,无法排序!n");
		return;
	}
	for (int i = 0; i < pc->sz - 1; i  )
	{
		int flag = 1;
		for (int j = 0; j < pc->sz - 1 - i; j  )
		{
			if (pc->data[j].age > pc->data[j   1].age)
			{
				Peoinfo tmp[2];
				tmp[0] = pc->data[j];
				pc->data[j] = pc->data[j   1];
				pc->data[j   1] = tmp[0];
				flag = 0;
			}
		}
		if (flag == 1)
			break;
	}
	printf("排序完成!n");
}

void DestoryContact(Contact* pc)
{
	free(pc->data);
	pc -> data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

void SaveContact(Contact* pc)
{
	FILE* pf = fopen("contact.txt", "w");
	if (pf == NULL)
	{
		perror("SaveContact");
		return;
	}
	for (int i = 0; i < pc->sz; i  )
	{
		fwrite(pc->data   i, sizeof(Peoinfo), 1, pf);
	}
	fclose(pf);
	pf = NULL;
}

0 人点赞