动态空间通讯录——详细注释

效果展示

在这里插入图片描述
在这里插入图片描述
实现功能:
1.添加联系人信息
2.删除联系人信息
3.查找指定联系人信息
4.修改指定联系人信息
5.显示所有联系人信息
6.清空所有联系人信息
7.排序所有联系人
8.自动保存读取通讯录内容

设计思路:
动态思想:
1.储存类型:当然是结构体了;
2.动态存储:实现动态存储即需要用到空间的申请malloc和修改relloc(这两个函数前面博客有提到哦),这两个函数提供了增长的能力,那么怎么进行增长呢,这时候就需要两个结构体了。
一个用来囊括所需要的所有成员变量,另一个囊括用来指向第一个结构体的指针,当前成员个数的计数器,当前开辟多少空间的计数器;
通过两个计数器的比较就知道是否需要开辟空间了;
功能实现
首先得先写一个空间开辟函数,即给定义的结构体变量先开辟一块内存空间;
1.添加联系人信息:
这里得先写一个空间判断函数,判断当前开辟的空间容量是否足够,不够就再开辟2个联系人空间,再进行数据输入,每输入一个人的信息,计数器加1;
2.删除联系人信息:
删除之前写一个通过名字查询联系人的函数,通过返回值判断是否找到,找到了再执行删除,这里删除的方式是进行覆盖,即将后面空间的内容覆盖掉前面的内容,同时当前成员计数器的数值减1
3.查找指定联系人信息:
通过输入名字,利用strcmp函数进行比较,找到了就返回下标进行打印出来
4.修改联系人信息:
利用查找联系人函数来返回找到的下标,再利用switch进行循环选择修改的信息
5.显示所有成员信息:
通过当前的成员计数器,利用for函数将全部成员信息进行输出(指针+数字的方式访问元素);
6.清空所有联系人:
将申请的动态空间利用free函数释放掉,再将两个计数器重置;
7.排序所有联系人:
利用qsort函数进行排序操作
8.内容储存
创建一个记事本,在程序退出之前写入记事本之内,程序读取开辟空间的时候将数据读取出来;

#ifndef _TEST_H_
#define _TEST_H_

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


#define TWO 2
#define NUM 20
typedef struct LIST //可以储存的成员信息列表
{
	char name[20];
	char sex[20];
	int age;
	char tel[20];
	char address[50];
}list;

typedef struct ADDRESS_BOOK
{
	list *call;//调用信息表
	int count;//表明存储个数
	int  capacity;//当前通讯录容量
}address;

void Menu();//菜单
void Add();//添加联系人信息
void Delect();//删除联系人信息
int Found();//找到并打印联系人信息
void Alter();//修改联系人信息
void Show();//显示所有联系人
void Empty();//清空所有联系人
void Rank();//以姓氏排序
void Open();//开辟空间函数
void Save_book();//将数据保存到磁盘之中

#endif
#include "test.h"

int main()
{
	address book;//创建通讯录book
	Open(&book);//给通讯录开辟空间

	int select = 0;
	while (!select)
	{
		Menu();
		printf("请输入你的选择\n");
		scanf("%d", &select);
		getchar();
		switch (select)
		{
		case 1:
			system("cls");
			Add(&book);//添加联系人,传址
			select = 0;
			break;
		case 2:
			system("cls");
			Delect(&book);//删除联系人
			select = 0;
			break;
		case 3:
			system("cls");
			Found(&book);//查找
			select = 0;
			break;
		case 4:
			system("cls");
			Alter(&book);//修改
			select = 0;
			break;
		case 5:
			system("cls");
			Show(&book);//显示
			select = 0;
			break;
		case 6:
			system("cls");
			Empty(&book);//清空
			select = 0;
			break;
		case 7:
			system("cls");
			Rank(&book);//以姓氏排序
			select = 0;
			break;
		case 8:
			select = 1;
			Save_book(&book);
			break;//退出
		default:
			printf("输入有误\n");
			select = 0;
		}
	}
	system("pause");
	return 0;
}
#include "test.h"
void Menu()
{
	printf("###1.添加联系人信息############2.删除指定联系人信息####################\n");
	printf("###3.查找指定联系人信息#########4.修改指定人信息#######################\n");
	printf("###5.显示所有联系人信息#########6.清空所有联系人#######################\n");
	printf("###7.以名字排序所有联系人#######8.退出#################################\n");

}
int Comp(char name[],address *sp)//寻找对应的名字;
{
	int i = 0;
	for (i = 0; i < sp->count; i++)
	{
		if ((strcmp(sp->call[i].name, name)) == 0)
			return i;//返回找到的下标;
	}
	return -1;//找不到返回-1
}
void Save_book(address *sp)//存储信息函数
{
	FILE *fp = fopen("book.log", "wb");//打开文件
	if (fp == NULL)
	{
		return ;
	}
	fwrite(sp, sizeof(address), 1, fp);//保存通讯录
	fwrite(sp->call, sizeof(list), sp->capacity, fp);//保存开辟出来的空间之中的内容	
	fclose(fp);
}

 void Open(address *p)//开辟空间函数
{
	FILE *fp = fopen("book.log", "rb");//打开文件
	if (fp == NULL)//没有文件则开辟空间
	{
		p->call = (list *)malloc(TWO*sizeof(list));//宏TWO=2,给调用信息表的指针分配内存
		if (p->call != NULL)
		{
			p->count = 0;//记录存储个数的计数器count
			p->capacity = 2;//开辟空间容量计数器,每次开辟空间提供2次存储机会;
		}
	}
	else//有文件则读取数据
	{
		printf("读取数据中\n");
		address temp;
		fread(&temp, sizeof(address), 1, fp);//读取通讯录address
		int size = sizeof(list)*temp.capacity;//读取出来的空间大小
		p->capacity = temp.capacity;
		p->count = temp.count;	
		p->call= (list *)malloc(size);//开辟空间
		if (p->call == NULL)
		{
			exit(1);
		}
		fread(p->call, sizeof(list), p->capacity, fp);
		fclose(fp);
		printf("读取成功\n");
	}
}
static void Judge(address *sp)//进行空间容量判断
{
	if (sp->capacity == 0)//清空了通讯录重新开辟空间;
	{
		sp->call = (list *)malloc(TWO*sizeof(list));//宏TWO=2,给调用信息表的指针分配内存
		if (sp->call != NULL)
		{
			sp->count = 0;//记录存储个数的计数器count
			sp->capacity = 2;//开辟空间容量计数器,每次开辟空间提供2次存储机会;
		}
	}
	else if (sp->count == sp->capacity)//上次开辟的内存满了
	{
		list *dst = (list *)realloc(sp->call,(sp->capacity+TWO)*sizeof(list));//增加两个空间;
		if (dst != NULL)
		{
			sp->call = dst;//将开辟成功的地址返回给原指针
			sp->capacity += 2;//空间容量计数器+2;
		}
	}
}
void Add(address *p)//增加函数
{
	Judge(p);//进行空间判断是否足够;
	printf("请输入联系人姓名\n");
	scanf("%s", p->call[p->count].name);
	printf("请输入联系人性别\n");
	scanf("%s", p->call[p->count].sex);
	printf("请输入联系人年龄\n");
	scanf("%d", &(p->call[p->count].age));
	printf("请输入联系人电话\n");
	scanf("%s", p->call[p->count].tel);
	printf("请输入联系人住址\n");
	scanf("%s", p->call[p->count].address);
	p->count++;//计数器+1;
}

void Delect(address *p)//删指定人函数
{
	int i = 0;//接收查找的人
	char name[20];
	printf("请输入要删除的指定人的名字\n");
	scanf("%s", name);
	i = Comp(name,p);
	if (i == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		Judge(p);//进行空间判定,避免越界;
		for (i; i < p->count; i++)//覆盖,利用后面的数据将前面的数据全部覆盖;
		{
			p->call[i] = p->call[i + 1];
		}
		p->count--;//成员减1,计数器减1
		printf("删减成功\n");
	}
	
}

int Found(address *p)//查找成员
{
	char name[NUM];
	printf("请输入你要查找的名字\n");
	scanf("%s", name);
	int j = Comp(name,p);//接收返回值,找到返回值为对应的成员下标
	if (j == -1)
	{
		printf("查无此人\n");
	}
	else
		printf("姓名:%s 性别:%s 年龄:%d 电话:%s 住址:%s\n", p->call[j].name,
		p->call[j].sex,p->call[j].age,p->call[j].tel,p->call[j].address);

	return j;//方便Alter函数调用
}

void Alter(address *p)//修改指定人信息
{
	int select = 0;
	char newname[NUM];//需要修改的名字
	char newsex[NUM];//需要修改的性别
	int  neweag;//需要修改的年龄
	char newtel[NUM];//需要修改的电话
	char newaddress[NUM];//需要修改的地址;
	int j=Found(p);//先找到这个人
	if (j !=-1)
	{
		while (!select)
		{
			printf("请选择需要修改的信息\n");
			printf("********************************\n");
			printf("**1.姓名**********2.性别*********\n");
			printf("**3.年龄**********4.电话*********\n");
			printf("**5.住址**********6.退出*********\n");
			printf("********************************\n");
			scanf("%d", &select);
			switch (select)
			{
			case 1:
				printf("请输入新的姓名\n");
				scanf("%s", newname);
				strcpy(p->call[j].name, newname);
				select = 0;
				break;
			case 2:
				printf("请输入新的性别\n");
				scanf("%s", newsex);
				strcpy(p->call[j].sex, newsex);
				select = 0;
				break;
			case 3:
				printf("请输入新的年龄\n");
				scanf("%d", &neweag);
				p->call[j].age = neweag;
				select = 0;
				break;
			case 4:
				printf("请输入新的电话\n");
				scanf("%s", newtel);
				strcpy(p->call[j].tel, newtel);
				select = 0;
				break;
			case 5:
				printf("请输入新的住址\n");
				scanf("%s", newaddress);
				strcpy(p->call[j].address, newaddress);
				select = 0;
				break;
			case 6:
				select = 1;
				break;
			default:
				printf("输入有误,从新输入\n");
				select = 0;
				break;
			}
		}
	}

}

void Show(address *p)//显示所有人信息
{
	if (p->count == 0)
		printf("联系人列表为空\n");
	for (int j = 0; j < p->count; j++)//将第一个到最后一个有信息的名单打印出来
	{
		printf("姓名:%s 性别:%s 年龄:%d 电话:%s 住址:%s\n", p->call[j].name,
			p->call[j].sex, p->call[j].age, p->call[j].tel, p->call[j].address);
	}
}

void Empty(address *p)//清空通讯录
{
	free(p->call);//释放掉申请的内存
	p->count = 0;//计数器归零
	p->capacity;//容量计数器归零
}

static int Compar(const list *x, const list *y)//排序回调函数
{
	return strcmp(x->name, y->name);
}
void Rank(address *p)
{
		if (p->count==0)
		{
			printf("联系人列表为空\n");
		}

	else
		qsort(p->call->name, p->count, sizeof(list), Compar);//利用qsort进行排序;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值