漫长的通讯录制作( Ĭ ^ Ĭ )

前言:因为太久没有做这种大型代码导致自己犯了不少低级错误以至于众多前辈也难以解决,最后不得已重做n次的代码(*^▽^*);

首先通讯录需要有几个必须有的功能:

1、添加联系人。

2、删除联系人。

3、寻找联系人。

4、修改联系人。

5、展示通讯录所有联系人。

6、清空所有联系人。

7、将联系人排序。

一、首先联系人肯定不能只有名字不然就是一个char[]就完事的东西,需要在里面有许多信息如姓名、地址、电话、性别等。所以这里选择构建一个结构体

#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 30
#define TELE_MAX 12
#define INIT_CAPA 3
#define INC_CAPA 2
typedef struct Peoinfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char addr[ADDR_MAX];
	char tele[TELE_MAX];
}Peoinfo;

同样的这个通讯录大小也需要记录控制

typedef struct Contact
{
	Peoinfo *data;
	int sz;
	int capacity;
}Contact;

二、主要的功能及其实现

老规矩do while进入菜单

然后用Switch语句来展开

void menu()
{
	printf("************************************\n");
	printf("******  1. add    2. del      ******\n");
	printf("******  3. search 4. modify   ******\n");
	printf("******  5. show   6. empty    ******\n");
	printf("******  7.sort    0. exit     ******\n");
	printf("************************************\n");
	
}
int main() {
	int input=0;
	Contact con;
	Initcontact(&con);
	char sort[5] = "name";
	do {
		menu();
		printf("请输入:");
		scanf("%d", &input);
		switch (input)
		{case 1:
			Addcontact(&con);
			break;
		case 2:
			 Delcontact(&con);
			break;
		case 3:
			Searchcontact(&con);
			break;
		case 4:
            Modifycontact(&con);
			break; 
		case 5:
			Showcontact(&con);
            break; 
		case 6:
			Emptycontact(&con);
			
			break;
		case 7:
			Sortcontact(&con);
			break;
		case 0:
			Savecontact(&con);
			DestroyContact(&con);
			printf("通讯录已退出\n");
				break;
		default:
			printf("选择错误\n");
			break;

			}
	} while (input);
	
	return 0;
}

入口设置好就可以开展功能块了

(1)首先需要初始化通讯录Initcontact

void Initcontact(Contact* pc)
{
	assert(pc!=NULL);
	pc->sz = 0;
	pc->capacity = INIT_CAPA;
	Peoinfo* ptr = (Peoinfo*)calloc(INIT_CAPA,sizeof(Peoinfo));
	if (ptr == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->data = ptr;
	Getcontact(pc);
}

(2)其中 Getcontact是将通讯录从文件中打开,

void Getcontact(Contact* pc)
{
	assert(pc);
	FILE* pf = fopen("Contact.txt", "rb");\
		if (pf == NULL) {
			perror("Getcontact::fopen");

		}
		else {
			Peoinfo ptr = {0};
			int i = 0;
			while (fread(&ptr, sizeof(Peoinfo), 1, pf))
			{
				check_capacity(pc);
				pc->data[i] = ptr;
				i++;
				pc->sz++;
			}
			fclose(pf);
			pf = NULL;
		}
}

(3)添加联系人

void Addcontact(Contact* pc)
{
	assert(pc);
	
	printf("请输入名字:");
	scanf("%s",pc->data[pc->sz].name);
	printf("请输入年龄:");
	scanf("%d",&(pc->data[pc->sz].age));
	printf("请输入性别:");
	scanf("%s",pc->data[pc->sz].sex);
	printf("请输入地址:");
	scanf("%s",pc->data[pc->sz].addr);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].tele);
	pc->sz++;
}

(5)Find

删除联系人,查找联系人,以及修改联系人,

这三个功能都需要另一个功能查找来实现

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

(6)Delcontact

删除联系人

void Delcontact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = {0};
	if (pc->sz==0)
	{
		printf("无法删除\n");
		return ;
	}
	printf("请输入需要删除的人的姓名");
	int ret = Find(pc,name);
	if (-1 == ret)
	{
		printf("要删除的人不存在");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}pc->sz--;
	printf("删除成功\n");
}

(7)Searchcontact

查找联系人

void Searchcontact(const Contact * pc){
	assert(pc);
	char name[NAME_MAX] = {0};
	printf("请输入要查找人的名字");
	scanf("%s",name);
	int p = Find(pc,name);
	if (p == -1)
	{
		printf("要查找的人不存在");
		return;
	}
	printf("姓名\n", "年龄\n", "性别\n", "地址\n", "电话\n");
		printf("%-10s\t%-4d\t%-5s\t%-20s\t%-12s\n",
			pc->data[p].name,
			pc->data[p].age,
			pc->data[p].sex,
			pc->data[p].addr,
			pc->data[p].tele);
}

(8)Modifycontact

修改联系人

void Modifycontact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };//初始化name数组(字符串)
	printf("请输入要修改人的名字:>");
	scanf("%s",name);
	int pos = Find(pc, name);//函数复用
	if (-1 == pos)
	{
		printf("要修改的人不存在\n");
		return;
	}

	//重新录入
	printf("请输入修改后的名字:>");
	scanf("%s",pc->data[pos].name);

	printf("请输入修改后的年龄:>");
	scanf("%d", &(pc->data[pos].age));//age不是数组,需要取地址

	printf("请输入修改后的性别:>");
	scanf("%s", pc->data[pos].sex);

	printf("请输入修改后的地址:>");
	scanf("%s", pc->data[pos].addr);

	printf("请输入修改后的电话:>");
	scanf("%s", pc->data[pos].tele);

	printf("修改完成\n");

}

(9) Showcontact

展示通讯录

展示就很简单了只需要依次展现出来就好

void Showcontact(const Contact* pc)
{
	assert(pc != NULL);
	printf("%-20s\t%-4s\t%-4s\t%-12s\t%-30s\n", "姓名", "年龄", "性别", "电话号码", "地址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-4s\t%-12s\t%-30s\n",
			pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);


	}
}

(10) Sortcontact

排序通讯录还好,在确定通讯录不空的前提下直接排就好

int CmpcontactByAge(const void* e1, const void* e2)
{
	//这个排出来的是升序,如果想排降序,只需将e1和e2的位置调换即可
	return ((Contact*)e1)->data->age - ((Contact*)e2)->data->age;
}
//整理通讯录
void Sortcontact(Contact* pc)
{
	assert(pc);
	int sz = pc->sz;
	if (pc->sz == 0) {
		printf("未录入联系人,无法排序\n");
		return;
	}
	Peoinfo temp;
	for (int i = 0; i < pc->sz - 1; i++)
	{
		for (int j = 0; j < pc->sz - 1 - i; j++)
		{
			if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0) {
				temp = pc->data[j]=pc->data[j+1];
			}
		}
	}
	通过qsort函数辅助排序
	//qsort(pc->data, sz, sizeof(pc->data[0]), CmpcontactByAge);
	printf("排序成功\n");
}

(11)Emptycontact

清空通讯录

void Emptycontact(Contact* p)
{
	assert(p);
	memset(p->data, 0, p->sz * sizeof(struct Peoinfo));
	p->sz = 0;
	//释放内存,指针置为NULL
	free(p->data);
	p->data = NULL;
	printf("已清空通讯录\n");

}

(12)扩容通讯录

void check_capacity(Contact* pc)
{
	assert(pc);
	if (pc->capacity == pc->sz)
	{
		Peoinfo* ptr = (Peoinfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(Peoinfo));
			if (ptr == NULL) {
				perror("check_capacity");
				return;
			}
			pc->data = ptr;
			pc->capacity += INC_CAPA;
			printf("扩容成功\n");
	}
}

(13)销毁通讯录

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

(14)保存通讯录

void Savecontact(Contact* pc) {
	assert(pc);
	FILE* pf = fopen("Contact.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");

	}
	else {
		for (int i = 0; i < pc->sz; i++)
		{
			fwrite(pc->data + i, sizeof(Peoinfo), 1, pf);
		}
		fclose(pf);
		pf = NULL;
		printf("保存成功\n");
	}

}

总结:很辛苦但是按部就班最好

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值