使用动态内存分配的通讯录实现


实现一个通讯录;
通讯录可以用来存储1000个人的信息,每个人的信息包括:
姓名、性别、年龄、电话、住址


提供方法:
1. 添加联系人信息
2. 删除指定联系人信息
3. 查找指定联系人信息
4. 修改指定联系人信息
5. 显示所有联系人信息
6. 清空所有联系人

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


静态内存开辟点击打开链接

上一篇博客写出了先给结构体开辟一块大小固定的空间,然后往里面存放数据,但是这种方法会造成很大的内存浪费,如果存两个数据那么就有998块内存浪费,还是很吃内存的,所以用动态内存开辟的方法可以很好的解决这个问题,不够了再给你加,管饱!


下面是代码实现:

Contact.h

#ifndef __CONTACT_H__
#define __CONTACT_H__

#define _CRT_SECURE_NO_WARNINGS 1
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

#define NAME_MAX 20
#define SEX_MAX 4
#define TEL_MAX 12
#define ADDR_MAX 30
#define MAX 1000
#define M 2
#define N 5
typedef struct PeoInfo	//定义一个存一个数据的结构体
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct Contact	//定义一个能存放1000个类型为PeoInfo类型的结构体
{
	PeoInfo *data;
	int sz;		//已用空间
	int count;	//总用空间
};

typedef struct Contact *Contact;	//将结构体重命名为一个结构体指针,用来直接指向结构体内容
void InitContact(Contact pcon);
int add_con(Contact pcon);
int del_con(Contact pcon);
int find_con(Contact pcon);
int modifty_con(Contact pcon);
int show_con(Contact pcon);
int empty_con(Contact pcon);
int sort_con(Contact pcon);
void send_out(Contact pcon);


#endif //__CONTACT_H__

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"

void InitContact(Contact pcon)	//静态初始化
{
	pcon->data = (PeoInfo *)malloc(M*sizeof(PeoInfo));	//先给PeoInfo结构分配M大小的内存
	if(pcon->data == NULL)	//如果存放数据的空间不够了,则输出没空间了
	{
		printf("out of memory\n");
		exit(1);
	}
	else
	{
		memset(pcon->data,0,M*sizeof(PeoInfo));
		pcon->sz = 0;	//已存数据为0
		pcon->count = M;	//将通讯录总数据初始化为M
	}
}

void check_memory(Contact pcon)	//检查内存是否够用
{
	if(pcon->sz == pcon->count) //如果已用内存和总内存相同,则内存不够用了
	{
		PeoInfo *str = (PeoInfo *)realloc(pcon->data,(pcon->count+N)*sizeof(PeoInfo));	//将data的内存增加N个
		if(str == NULL)
		{
			printf("out of memory\n");
			exit(1);
		}
		else
		{
			pcon->data = str;	//将新分配到的内存给data,同时data的内容也拷贝过来
			pcon->count += N;	//将总大小每次增加N个,不够再分,能节省内存
		}
	}
}

int add_con(Contact pcon)	//添加数据
{
	check_memory(pcon);
	printf("请输入姓名:>");
	scanf("%s",pcon->data[pcon->sz].name);
	printf("请输入性别:>");
	scanf("%s",pcon->data[pcon->sz].sex);
	printf("请输入年龄:>");
	scanf("%d",&pcon->data[pcon->sz].age);
	printf("请输入电话号码:>");
	scanf("%s",pcon->data[pcon->sz].tel);
	printf("请输入地址:>");
	scanf("%s",pcon->data[pcon->sz].addr);
	printf("添加成功\n");
	pcon->sz++;		//存一个计数器加1
	return 0;
}

int del_con(Contact pcon)	//要删除的数据
{
	int i = 0;
	int ret = 0;
	int tmp = 0;
	if(pcon->sz == 0)	//如果没有数据则返回-1
	{
		printf("通讯录里没有信息\n");
		return 0;
	}
	ret = find_con(pcon);	//先遍历一遍
	printf("确定删除吗? 1、确定  0、取消\n");
	scanf("%d",&tmp);
	if(tmp == 0)
		return 0;
	if(ret != -1)
	{
		for(i=ret; i<(pcon->sz)-1; i++);
		{
			pcon->data[ret] = pcon->data[ret+i];	//删除相当于把后面的数据依次向前覆盖前面的数据
		}
		pcon->sz--;		//删除之后计数器减1
		return 1;
	}
	else 
	{
		printf("没有要删除的人\n");
		return -1;
	}
}

int find_con(Contact pcon)	//查找,为后面的其他选项提供遍历
{
	int i = 0;
	char name[NAME_MAX];
	printf("请输入名字:>");
	scanf("%s",name);
	printf("%10s%6s%6s%14s%20s\n","姓名","性别","年龄","电话","地址");
	for(i=0; i<pcon->sz; i++)
	{
		if(strcmp(pcon->data[i].name,name)==0)
		{
			printf("%10s",pcon->data[i].name);
			printf("%6s",pcon->data[i].sex);
			printf("%6d",pcon->data[i].age);
			printf("%14s",pcon->data[i].tel);
			printf("%20s",pcon->data[i].addr);
			printf("\n");
			return i;
		}
	}
	return -1;
}

int modifty_con(Contact pcon)	//要修改的内容
{
	int i = 0;
	int ret = 0;
	if(pcon->sz == 0)	//如果没数据则返回
	{
		printf("没有可修改的数据\n");
		return 0;
	}
	ret = find_con(pcon);	//先在遍历一遍,看有没有要修改的数据
	if(ret != -1)
	{
		printf("请重新输入要改的数据\n");
		printf("请输入姓名:>");
		scanf("%s",pcon->data[ret].name);
		printf("请输入性别:>");
		scanf("%s",pcon->data[ret].sex);
		printf("请输入年龄:>");
		scanf("%d",&pcon->data[ret].age);
		printf("请输入电话:>");
		scanf("%s",pcon->data[ret].tel);
		printf("请输入地址:>");
		scanf("%s",pcon->data[ret].addr);
		printf("修改成功\n");
		return 1;
	}
	else
	{
		printf("没找到要修改的名字\n");
		return -1;
	}
}

int show_con(Contact pcon)	//将所有信息按存入时间来显示出来
{
	int i = 0;
	printf("%10s%6s%6s%14s%20s\n","姓名","性别","年龄","电话","地址");
	for(i=0; i<pcon->sz; i++)	//时间顺序
	{
		printf("%10s",pcon->data[i].name);
		printf("%6s",pcon->data[i].sex);
		printf("%6d",pcon->data[i].age);
		printf("%14s",pcon->data[i].tel);
		printf("%20s",pcon->data[i].addr);
		printf("\n");
	}
	printf("\n");
	return 0;
}

int empty_con(Contact pcon)	//清空数据
{
	pcon->sz = 0;	//只是将要计数器清零,实际数据还在(相当于地址变为起始地址指针)
	return 0;
}

int sort_con(Contact pcon)	//按姓名字母大小排序显示
{
	int tmp = 0;
	int ret = 0;
	int i = 0;
	int j = 0;
	PeoInfo swp ;	//定义另一个PeoInfo的对象
	if(pcon->sz == 0)	//如果列表为空,则返回
	{
		printf("没有可靠的数据\n");
		return 0;
	}
	for(i=0; i<pcon->sz-1; i++)
	{
		for(j=0; j<pcon->sz-i-1; j++)
		{
			if(strcmp(pcon->data[j].name,pcon->data[j+1].name)>0)	//按照名字的大小,按照从小到大冒泡排序
			{
				swp = pcon->data[j];
				pcon->data[j] = pcon->data[j+1];
				pcon->data[j+1] = swp;
			}
		}
	}
	tmp = show_con(pcon);	//将排序后的打印出来
	return 0;
}

void send_out(Contact pcon)
{
	if(pcon->data != NULL)
		free(pcon->data);
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"

void menu()
{
	printf("***************************************************\n");
	printf("***1、添加联系人信息       2、删除指定联系人信息***\n");
	printf("***3、查找指定联系人信息   4、修改指定联系人信息***\n");
	printf("***5、显示所有联系人信息   6、清空所有联系人    ***\n");
	printf("***7、以名字排序所有联系人 0、exit              ***\n");
	printf("***************************************************\n");
}

enum OP	//用枚举法列出选项,直观
{
	EXIT,
	ADD,
	DEL,
	FIND,
	MOD,
	SHOW,
	EMPTY,
	SORT
};

void test()
{
	int input = 0;
	struct Contact my_con;	//创建一个struct Contact类型的对象
	my_con.sz = 0;	//将计数器清零
	InitContact(&my_con);	//初始化对象
	do
	{
		menu();
		printf("请输入你的选择:>");
		scanf("%d",&input);
		switch (input)
		{
		case ADD:
			add_con(&my_con);
			break;
		case DEL:
			del_con(&my_con);
			break;
		case FIND:
			find_con(&my_con);
			break;
		case MOD:
			modifty_con(&my_con);
			break;
		case SHOW:
			show_con(&my_con);
			break;
		case EMPTY:
			empty_con(&my_con);
			break;
		case SORT:
			sort_con(&my_con);
			break;
		case EXIT:
			printf("退出\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	}while(input);

}

int main()
{
	test();
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值