C语言实现通讯录程序

通讯录程序:

语言:c

设计实现功能:
1、添加联系人(重名检测)
2、删除联系人
3、修改联系人信息
4、查询联系人
5、显示全部联系人
6、对联系人进行排序
7、保存通讯录数据,下次打开程序原始数据依旧存在
8、清空联系人
9、通讯录空间不足时,进行自动扩容

根据需要实现的功能,设计以下结构体类型存放信息,设计一下功能函数。

#ifndef _CONTACT_H_
#define _CONTACT_H_

#include <stdio.h>
#include <malloc.h>
#include <windows.h>
#pragma warning (disable:4996)

//名字大小
#define NAME_SIZE 15
//性别大小
#define SEX_SIZE 10
//电话号大小
#define PHONE_SIZE 15
//地址大小
#define ADDRESS_SIZE 20
//初始化空间大小
#define DEFAULT 1
//空间扩容倍数
#define FOLD 2
//保存通讯录的文件
#define SAVE_FILE "save.bin"

//个人信息结构体类型
typedef struct person{
	char name[NAME_SIZE];
	char sex[SEX_SIZE];
	int age;
	char phone[PHONE_SIZE];
	char address[ADDRESS_SIZE];
}person_t, *person_p;//个人信息结构体类型

//通讯录结构体类型
typedef struct book{
	int max;//通讯录总空间
	int size;//通讯录现已使用空间
	/**个人信息结构体类型的,柔性数组*/
	person_t porsen[0];
}book_t, *book_p;//通讯录结构体类型


void InitContact(book_p * p);//初始化通讯录
void AddContact(book_p * p);//插入人员信息
void ShowContact(book_p p);//显示通讯录内容
void DelContact(book_p p);//删除人员信息
void FindContact(book_p p);//查找人员
void ClearContact(book_p p);//清空通讯录
void SortContact(book_p p);//人员排序
void SaveContact(book_p p);//保存通讯录
void ChangeContact(book_p p);//修改人员信息

#endif

程序执行流程如下:

#include "contact.h"

//主菜单
void Menu()
{
	printf("\n\n############################################\n");
	printf("## 1、增添        2、删除        3、修改  ##\n");
	printf("## 4、查询        5、显示        6、排序  ##\n");
	printf("## 7、保存        8、清空        0、退出  ##\n");
	printf("############################################\n");
	printf("请输入选择#\n");
}

int CheckInput(char a)//检查输入选项
{
	if (a < '0' || a > '8')
		return 1;
	else
		return 0;
}

int main()
{ 
	book_p contact = NULL;//通讯录主体
	InitContact(&contact);//传入二级指针
	int flag = 0;
	char select = 0;//用户输入的选项
	while (!flag)
	{
		Menu();
		scanf(" %c", &select);
		if (CheckInput(select))//检查输入选项
		{
			printf("输入错误!请重新输入!");
			fflush(stdin);
			continue;
		}
		switch (select-48){
		case 1:
			AddContact(&contact);//插入人员信息
			break;
		case 2:
			DelContact(contact);//删除人员信息
			break;
		case 3:
			ChangeContact(contact);//修改人员信息
			break;
		case 4:
			FindContact(contact);//查找人员
			break;
		case 5:
			ShowContact(contact);//显示通讯录内容
			break;
		case 6:
			SortContact(contact);//人员排序
			break;
		case 7:
			SaveContact(contact);//保存通讯录
			break;
		case 8:
			ClearContact(contact);//清空通讯录
			break;
		case 0:
			flag = 1;
			break;
		}
	}

	return 0;
}

函数详细实现:

#include "contact.h"

//初始化通讯录
void InitContact(book_p * p)
{
	FILE *fp = fopen(SAVE_FILE, "rb");
	if (fp == NULL)
	{
		*p = (book_p)malloc(sizeof(book_t)+sizeof(person_t)* DEFAULT);
		if (*p == NULL)
		{
			perror("malloc开辟空间失败!\n");
			exit(1);
		}
		(*p)->max = DEFAULT;
		(*p)->size = 0;
		printf("初始化完成,新建空文档!\n");
		return;
	}
	book_t ct;
	fread(&ct, sizeof(book_t), 1, fp);
	*p = (book_p)malloc(sizeof(book_t)+sizeof(person_t)* (ct.size));
	if (*p == NULL)
	{
		perror("malloc开辟空间存放文件失败!\n");
		exit(1);
	}
	//memcpy(*p, &ct, sizeof(ct));
	(*p)->max = ct.max;//p2
	(*p)->size = ct.size;
	fread((*p)->porsen, sizeof(person_t), ct.size, fp);
	printf("初始化完成,已读取历史文档!\n");
	fclose(fp);
}

//判断通讯录是否满了
static int IsFull(book_p p)
{
	return p->size == p->max ? 1 : 0;
}

//通讯录扩容
static int Inc(book_p *p)
{
	printf("空间不足,准备扩容!%d\n", (*p)->max);
	int new_max = (*p)->max * FOLD;
	book_p new_book = (book_p)realloc(*p, sizeof(book_t)+sizeof(person_t)* new_max);
	if (NULL == new_book)
	{
		printf("扩容失败!\n");
		return 0;
	}
	*p = new_book;
	(*p)->max = new_max;
	printf("扩容成功!%d\n",(*p)->max);
	return 1;

}

//插入人员信息
void AddContact(book_p *p)
{ 
	if (IsFull(*p) && !Inc(p))//1、空间没满 2、空间满了,但是扩容成功
	{//如果满了,进行扩容,如果扩容失败,出错返回
		printf("空间不足且扩容失败!\n");
		return;
	}
	//插入当前要添加人员的信息,指针
	char _name[NAME_SIZE];
	int i = 0;
	printf("请输入联系人姓名# ");
	scanf("%s", _name);
	//判断姓名是否已经存在
	for (; i < (*p)->size; i++)
	{
		person_p sp = &(*p)->porsen[i];
		if (!strcmp(sp->name, _name))//判断两个字符串大小,相等返回0
		{
			printf("此人已存在!不可重复添加!\n");
			printf("| %s | %s | %d | %s | %s |\n", \
				sp->name, sp->sex, sp->age, sp->phone, sp->address);
			return;
		}
	}
	person_p cp = &((*p)->porsen[(*p)->size]);
	memcpy(&cp->name, _name, NAME_SIZE);
	printf("请输入联系人性别# ");
	scanf(" %s", cp->sex);
	printf("请输入联系人年龄# ");
	scanf("%d", &cp->age);
	printf("请输入联系人电话# ");
	scanf("%s", cp->phone);
	printf("请输入联系人地址# ");
	scanf("%s", cp->address);
	//拷贝
	//memcpy(&(*p)->porsen[(*p)->size], &pp, sizeof(person_t));
	(*p)->size++;
}
void ShowContact(book_p p)//显示通讯录内容
{
	if (p->size == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	printf("----------------------------------------------------\n");
	int i = 0;
	for (; i < p->size; i++)
	{
		person_p cp = &p->porsen[i];
		printf("| %s | %s | %d | %s | %s |\n", \
			cp->name, cp->sex, cp->age, cp->phone, cp->address);
		printf("----------------------------------------------------\n");
	}
}

void FindContact(book_p p)//查找人员,找到返回1
{
	char _name[NAME_SIZE];
	printf("请输入要查询的人的姓名# ");
	scanf("%s", _name);
	int i = 0;
	printf("----------------------------------------------------\n");
	for (; i < p->size; i++)
	{
		person_p cp = &p->porsen[i];
		if (!strcmp(cp->name, _name))//判断两个字符串大小,相等返回0
		{
			printf("| %s | %s | %d | %s | %s |\n", \
				cp->name, cp->sex, cp->age, cp->phone, cp->address);
			printf("----------------------------------------------------\n");
			return;
		}
	}
	printf("暂无此人!\n");
	return;
}

static int IsEmpty(book_p p)
{
	return p->size == 0;
}

void DelContact(book_p p)//删除人员信息
{
	if (!p->size)
	{
		printf("通讯录为空!\n");
		return;
	}
	char _name[NAME_SIZE];
	printf("请输入你要删除的人的姓名# ");
	scanf("%s", _name);
	int i = 0;
	for (; i < p->size; i++)
	{
		person_p cp = &p->porsen[i];
		if (!strcmp(cp->name, _name))
		{
			printf("----------------------------------------------------\n");
			printf("| %s | %s | %d | %s | %s |\n", \
				cp->name, cp->sex, cp->age, cp->phone, cp->address);
			printf("----------------------------------------------------\n");
			memcpy(cp, &p->porsen[p->size - 1], sizeof(person_t));//结构体不能直接赋值,所以使用内存拷贝
			printf("此人已删除成功!\n");
			break;
		}
	}
	p->size--;
}
void ClearContact(book_p p)//清空通讯录
{
	p->size = 0;
}

static int CompName(const void *x, const void *y)
{
	person_p xp = (person_p)x;
	person_p yp = (person_p)y;
	return strcmp(xp->name, yp->name);
}

void SortContact(book_p p)//人员排序
{
	if (p->size < 2) 
	{
		printf("不需要排序!\n");
		return;
	}
	qsort(p->porsen, p->size, sizeof(person_t), CompName);
	printf("排序已完成!\n");
}

void ChangeContact(book_p p)//修改人员信息
{
	char _name[NAME_SIZE];
	int i = 0;
	printf("请输入要修改人姓名# ");
	scanf("%s", _name);
	//找到此人
	for (; i < (p)->size; i++)
	{
		person_p sp = &(p)->porsen[i];
		if (!strcmp(sp->name, _name))//判断两个字符串大小,相等返回0
		{
			printf("已找到此人!\n");
			printf("| %s | %s | %d | %s | %s |\n", \
				sp->name, sp->sex, sp->age, sp->phone, sp->address);
			printf("请输入要修改属性#\n");
			printf("1、姓名	 2、性别  3、年龄  4、电话  5、地址\n");
			int choose = 0;
			scanf("%d", &choose);
			switch (choose){
			case 1:{
					   printf("请进行更改#");
					   char new_name[NAME_SIZE];
					   scanf("%s", new_name);
					   memcpy(&sp->name, new_name, NAME_SIZE);
			}
				break;
			case 2:{
					   printf("请进行更改#");
					   char new_sex[SEX_SIZE];
					   scanf("%s", new_sex);
					   memcpy(&sp->sex, new_sex, SEX_SIZE);
			}
				break;
			case 3:{
					   printf("请进行更改#");
					   int new_age = 0;
					   scanf("%d", &new_age);
					   sp->age = new_age;
			}
				break;
			case 4:{
					   printf("请进行更改#");
					   char new_phone[PHONE_SIZE];
					   scanf("%s", new_phone);
					   memcpy(&sp->phone, new_phone, PHONE_SIZE);
			}
				break;
			case 5:{
					   printf("请进行更改#");
					   char new_address[ADDRESS_SIZE];
					   scanf("%s", new_address);
					   memcpy(&sp->address, new_address, ADDRESS_SIZE);
			}
			}
			return;
		}
	}
	printf("查无此人!\n");

}


void SaveContact(book_p p)//保存通讯录
{
	FILE *fp = fopen(SAVE_FILE, "wb");
	if (fp == NULL)
	{
		printf("保存失败(打开文件失败)!\n");
		return;
	}

	fwrite(p, sizeof(book_t), 1, fp);
	fwrite(p->porsen, sizeof(person_t), p->size, fp);
	printf("文件保存成功!\n");
	fclose(fp);
}

https://github.com/Moon-Li/The-C-Programming-Language/tree/master/address_book

猜你喜欢

转载自blog.csdn.net/Mmonster23/article/details/104743361