用C语言实现通讯录(二、动态版+文件保存信息)

  之前写的静态版的通讯录,只能存储固定数目大小的联系人信息,现在要升级为动态版的,这样只要容量不够的话只需自动扩容就可以啦!而且之前版本的信息每次退出程序后不会保存,每次需要重新录入,加入文件操作后可以将录入的信息保存到文件中,然后再从文件中读取就可以了。现在就让我们来完成一下之前程序的升级版。

实现一个简单的通讯录

要求: 
通讯录可以用来存储1000个人的信息,每个人的信息包括: 
姓名、性别、年龄、电话、住址 
该通讯录所具备的基本功能: 

1. 添加联系人信息 

2. 删除指定联系人信息 

3. 查找指定联系人信息 

4. 修改指定联系人信息 

5. 显示所有联系人信息 

6. 清空所有联系人 

7. 以名字排序所有联系人

8.可以将信息保存到文件中,每次从文件中读取信息 

9.可以实现扩容,实现动态存储

#ifndef _CONTACT_H__
#define _CONTACT_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TEL 11
#define MAX 10
#define ADD_CAPACITY 10
#define MAX_ADDR 100
#define FILE_NAME "contact.txt"
enum OPERATIONS//通讯录的所有功能选项
{
	EXIT,
	ADD,
	DEL,
	MODIFY,
	SORT,
	SEARCH,
	SHOW,
	CLEAR
};
enum MODIFYINFORMATION//修改联系人信息的选项
{
	EXITMODIFY,
	NAME,
	AGE,
	TEL,
	SEX,
	ADDR
};
typedef struct Person_Information
{
	char name[MAX_NAME];
	int age;
	int tel[MAX_TEL];
	char sex[MAX_SEX];
	char addr[MAX_ADDR];
	int flag;

}PerInfor;//存放联系人信息的一个结构体类型
typedef struct Contact
{
	PerInfor* data;
	int count;
	int capacity;
}Contact, *pContact;//count表示联系人的个数,data是一个PerInfor类型的数组用来存放联系人信息

void InitContact(pContact p);//对count和data[]进行初始化

int findperson(pContact p);//查找指定的联系人,并返回下标

void ADDContact(pContact p);//	添加联系人信息 

void DELContact(pContact p);//删除指定联系人信息 

void MODIFYMenu();//修改联系人信息的选择菜单

void MODIFYContact(pContact p);//修改指定联系人信息

void SORTContact(pContact p);//根据名字将联系人排序;

void SEARCHContact(pContact p);//查找指定联系人信息 

void ShowContact(pContact p);//	显示所有联系人信息 

void CLEARContact(pContact p);//清空所有联系人

void DestoryContact(pContact p);//销毁动态开辟的空间

void SaveContact(pContact p);//保存内存信息到文件

void LoadContact(pContact p);//从文件中加载信息到内存
#endif //_CONTACT_H__

#include "Contact.h"

 void check_capacity(pContact p)//增容
{
	if (p->count == p->capacity)
	{
		PerInfor* pc = (PerInfor*)realloc(p->data, (p->capacity + ADD_CAPACITY)*sizeof(PerInfor));
		if (pc == NULL)
		{
			printf("增容失败\n");
		}
		else
		{
			p->data = pc;
			pc = NULL;
		}
		p->capacity += ADD_CAPACITY;
		printf("增容成功\n");
	}
}
void LoadContact(pContact p)//从文件中读取信息
{
	PerInfor tmp = { 0 };
	FILE *pf = fopen(FILE_NAME, "r");
	if (pf == NULL)
	{
		perror("open file for read");
		exit(EXIT_FAILURE);
	}
	while (fread(&tmp, sizeof(PerInfor), 1, pf))
	{
		//扩容
		check_capacity(p);
		p->data[p->count] = tmp;
		p->count++;	
	}
	fclose(pf);
	pf = NULL;
}
void InitContact(pContact p)
{
	p->count = 0;
	p->capacity = MAX;
	p->data = (PerInfor*)calloc(sizeof(PerInfor),p->capacity);
	p->data->flag = 1;
	LoadContact(p);//加载文件的信息到内存中
}
int findperson(pContact p)
{
	int i = 0;
	char personname[MAX_NAME];
	printf("请输入要查找的联系人的姓名\n");
	scanf("%s", personname);
	for (i = 0; i < p->count; i++)
	{
		if (strcmp(personname, p->data[i].name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void ADDContact(pContact p)
{
	    check_capacity(p);
		printf("请输入姓名\n");
		scanf("%s", p->data[p->count].name);
		printf("请输入年龄\n");
		scanf("%d", &(p->data[p->count].age));
		printf("请输入联系方式\n");
		scanf("%s", p->data[p->count].tel);
		printf("请输入性别\n");
		scanf("%s", p->data[p->count].sex);
		printf("请输入家庭住址\n");
		scanf("%s", p->data[p->count].addr);
	    p->count++;
	    printf("添加联系人成功\n");
		
}
void DELContact(pContact p)
{

	int i = 0;
	if (p->count == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	else
	{
		int ret = findperson(p);
		if (ret == -1)
		{
			printf("无该联系人\n");
			return;
		}
		else
		{
			p->data->flag = 0;
			p->count--;
		}
		printf("删除联系人成功\n");
	}
}
void MODIFYMenu()
{
	printf("*******************************\n");
	printf("********1.name****2.age********\n");
	printf("********3.tel ****4.sex********\n");
	printf("*************5.addr************\n");
	printf("**********0.exitmodify*********\n");
	printf("*******************************\n");
}
void MODIFYContact(pContact p)
{
	int ret = findperson(p);
	if (ret == -1)
	{
		printf("无该联系人,请检查输入信息\n");
		return;
	}
	else
	{
		int input = 0;
		MODIFYMenu();
		printf("请选择要修改的信息\n");
		scanf("%d", &input);
		switch (input)
		{
		case NAME:
			printf("请输入修改后的名字\n");
			scanf("%s", p->data[ret].name);
			break;
		case AGE:
			printf("请输入修改后的年龄\n");
			scanf("%d", &(p->data[ret].age));
			break;
		case TEL:
			printf("请输入修改后的联系方式\n");
			scanf("%S", p->data[ret].tel);
			break;
		case SEX:
			printf("请输入修改后的性别\n");
			scanf("%s", p->data[ret].sex);
			break;
		case ADDR:
			printf("请输入修改后的住址\n");
			scanf("%s", p->data[ret].addr);
			break;
		case EXITMODIFY:
			break;
		default:
			printf("无该选项,请重新选择\n");
			break;
		}
	}
	printf("修改联系人信息成功\n");
}

int DATA_name_cmp(const void* e1, const void* e2)
{
	assert(e1&&e2);
	return (strcmp(((PerInfor*)e1)->name, ((PerInfor*)e2)->name));
}
void SWAP(char *e1, char *e2, int width)
{
	assert(e1&&e2);
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *((char*)e1 + i);
		*((char*)e1 + i) = *((char*)e2 + i);
		*((char*)e2 + i) = tmp;
	}
}
void BUBBLE_sort(void *base, int count, int width, int(*cmp)(const void *e1, const void *e2))
{
	assert(base&&cmp);
	int i = 0;
	int j = 0;
	for (i = 0; i < count - 1; i++)
	{
		for (j = 0; j < count - i - 1; j++)
		{
			if (cmp((char *)base + j*width, (char *)base + (j + 1)*width)>0)
			{
				SWAP((char *)base + j*width, (char *)base + (j + 1)*width, width);
			}
		}
	}
}
void SORTContact(pContact p)
{
	int i = 0;
	if (p->count == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	else
	{
		BUBBLE_sort(p->data, p->count, sizeof(PerInfor), DATA_name_cmp);
	}
	ShowContact(p);
	printf("联系人列表排序成功\n");
}
void SEARCHContact(pContact p)
{
	int ret = findperson(p);
	printf("%10s %10s %10s %10s %10s\n", "姓名", "年龄", "联系方式", "性别", "住址");
	printf("%10s ", p->data[ret].name);
	printf("%9d ", p->data[ret].age);
	printf(" %10s ", p->data[ret].tel);
	printf("%9s ", p->data[ret].sex);
	printf(" %10s ", p->data[ret].addr);
	printf("\n");
}
void CLEARContact(pContact p)
{
	p->count = 0;
	printf("通讯录清空成功\n");
}
void ShowContact(pContact p)
{
	int i = 0;
	int j = 0;
	if (p->count == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	else 
	{
		if (p->data->flag == 1)
		{
			printf("%10s %10s %10s %10s %10s\n", "姓名", "年龄", "联系方式", "性别", "住址");
			for (i = 0; i < p->count; i++)
			{
				printf("%10s ", p->data[i].name);
				printf("%9d ", p->data[i].age);
				printf(" %10s ", p->data[i].tel);
				printf("%9s ", p->data[i].sex);
				printf(" %10s ", p->data[i].addr);
				printf("\n");
			}
		}
	}
}
void SaveContact(pContact p)//退出程序时,将所录入的信息保存到文件中
{
	FILE*pf = fopen(FILE_NAME, "w");
	if (pf == NULL)
	{
		perror("open file for write");
		exit(EXIT_FAILURE);
	}
	//保存信息
	int i = 0;
	for (i = 0; i < p->count; i++)
	{
		fwrite(p->data+i,sizeof(PerInfor),1,pf );
		fflush(pf);
	}
	fclose(pf); 
	pf = NULL;
}
void DestoryContact(pContact p)
{
	//保存内存信息到文件
	SaveContact(p);
	printf("信息已成功保存\n");
	free(p->data);
	p->data = NULL;
	p->count = 0;
	p->capacity = 0;
}

#include "Contact.h"
void menu()
{
	printf("********************************\n");
	printf("*******1.add********2.del*******\n");
	printf("*******3.modify****4.sort*******\n");
	printf("*******5.search*****6.show******\n");
	printf("*******7.clear******0.exit******\n");
	printf("********************************\n");


}
int main()
{
	int input = 0;
	Contact my_con;
	InitContact(&my_con);
	do
	{
		menu();
		printf("请选择操作功能>:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			ADDContact(&my_con);
			break;
		case DEL:
			DELContact(&my_con);
			break;
		case MODIFY:
			MODIFYContact(&my_con);
			break;
		case SORT:
			SORTContact(&my_con);
			break;
		case SEARCH:
			SEARCHContact(&my_con);
			break;
		case SHOW:
			ShowContact(&my_con);
			break;
		case CLEAR:
			CLEARContact(&my_con);
			break;
		case EXIT:
			DestoryContact(&my_con);
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值