通讯录+动态管理内存

目录

  1. 静态通讯录
  2. 动态管理内存
  3. 动态通讯录

静态通讯录

功能:
1.添加
2.删除
3.查找
4.显示
5.排序
6.修改
7.退出

小编通过构建了一个结构体数组实现了通讯录,只不过该方式不能动态管理通讯录的大小。

1.func.h`

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 1000
#define name_max 10
#define phone_max 20
#define addr_max 10
void Qsort(struct contact *s);
void Initial(struct contact *s);
void Del(struct contact *s);
int Add(struct contact *s);
void Show(struct contact *s);
void Seacher(struct contact *s);
void Modify(struct contact *s);
struct people
{
	char name[name_max];
	char phone[phone_max];
	char addr[addr_max];
};
struct contact
{
	struct people arr[MAX];
	int sz;
};

2.function.c

#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
int _compare(const void *elem1, const void *elem2)
{
	return strcmp(((struct people*)elem1)->name 
		,((struct people*)elem2)->name);
}
void Show(struct contact *s)
{
	if (s->sz!=0)
	{
		printf("%-15s\t%-15s\t%-15s\n", "名字", "电话", "地址");
		int n = s->sz;
		int i = 0;
		for (i = 0; i < n ; i++)
		{
			printf("%-15s\t", (s->arr[i].name));
			printf("%-15s\t", (s->arr[i].phone));
			printf("%-15s\t\n", (s->arr[i].addr));
		}
	}
	return;
}
int Find(char*a,struct contact *s)
{
	int i = 0;
	int n = s->sz;
	for (i = 0; i < n; i++)
	{
		if (strcmp(a, s->arr[i].name) == 0)
			return i;
	}
	return -1;
}
void Initial(struct contact *s)
{
	s->sz = 0;
	memset(s->arr, 0, sizeof(s->arr));
}
int Add(struct contact *s)
{
	if (MAX == s->sz)
	{
		printf("通讯录已满。\n");
		return 0;
	}
	int n = s->sz;
	printf("请输入:\n");
	printf("请输入名字。\n");
	scanf("%s", &(s->arr[n].name));
	printf("请输入电话。\n");
	scanf("%s", &(s->arr[n].phone));
	printf("请输入住址。\n");
	scanf("%s", &(s->arr[n].addr));
	s->sz++;
	return 0;
}


void Modify(struct contact *s)
{
	printf("请输入要修改的名字->\n");
	char a[name_max] = {0};
	scanf("%s", &a);
	int pos = Find(a,s);
	if (pos >= 0)
	{
		printf("请输入:\n");
		printf("请输入名字。\n");
		scanf("%s", &(s->arr[pos].name));
		printf("请输入电话。\n");
		scanf("%s", &(s->arr[pos].phone));
		printf("请输入住址。\n");
		scanf("%s", &(s->arr[pos].addr));
	}
	else
		printf("此用户不存在\n");
	return;
}

void Del(struct contact *s)
{
	int n = 0;
	if (0 == s->sz)
	{
		printf("通讯录没人。\n");
		return;
	}
	else
	{
		printf("请输入要删除的名字\n");
		char sname[10];
		scanf("%s", sname);
		n = Find(sname, s);
		if (n < 0)
		{
			printf("不存在此人。\n");
			return;
		}
		else
		{
			for (; n < s->sz - 1; n++)
			{
				s->arr[n] = s->arr[n + 1];
			}
			s->sz--;
		}
	}
	return;
}
void Seacher(struct contact *s)
{
	if (s->sz == 0)
	{
		printf("先加加人吧。\n");
		return ;
	}
	printf("请输入人名\n");
	char sname[10];
	scanf("%s", sname);
	int n = Find(sname, s);
	if (n >= 0)
	{
		printf("%-15s\t%-15s\t%s-15\n", "名字", "电话", "地址");
		printf("%-15s\t", (s->arr[n].name));
		printf("%-15s\t", (s->arr[n].phone));
		printf("%-15s\t\n", (s->arr[n].addr));
		return;
	}
	printf("查无此人\n");
	return;
}
void Qsort(struct contact *s)
{
	qsort(s->arr, s->sz, sizeof(s->arr[0]), _compare);
}

3.test.c

#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
void menu()
{
	printf("******************\n");
	printf("*1.add****2.del***\n");
	printf("*3.seacher*4.show*\n");
	printf("*5.qsort**6.modify*\n");
	printf("*0.exit***********\n");
	printf("******************\n");
}
int main()
{
	int input = 0;
	struct contact s;
	Initial(&s);
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 0: 
			break;
		case 1:
			Add(&s);
			break;
		case 2:
			Del(&s);
			break;
		case 3:
			Seacher(&s);
			break;
		case 4:
			Show(&s);
			break;
		case 5:
			Qsort(&s);
			break;
		case 6:
			Modify(&s);
			break;
		default:
			printf("请重试\n");
			break;
		}
	} while (input);
	return 0;
}

动态内存管理

首先我们来想一想为什么存在动态内存管理呢?目前我们开辟空间的方式主要有创建一个变量或数组,但是这种方式开辟的空间是一定的,一旦我们只有在使用时,才能确定所需要的空间大小,这种方式就满足不了了。那动态内存管理时如何实现的呢?接下来,我们来了解一下几个函数。

动态内存管理函数

1.malloc
在这里插入图片描述
函数参数
1.开辟所需的内存大小

Return Value

malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available.

返回值有两种情况
1.一个类型为 void*的指针,并指向向内存申请的连续空间。
2.NULL空指针,当开辟失败时。

当使用malloc函数时,需搭配free函数使用,不然会造成内存泄漏。

2.free(销毁动态开辟的空间)
在这里插入图片描述
函数参数

1.指向销毁空间的指针

返回值为void

举个栗子

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
	char *p1 = (char*)malloc(20);
	if (p1 != NULL) //判断是否开辟成功
	{
		strcpy(p1, "hello world");
		printf("%s\n", p1);
	}
	free(p1);
	p1 = NULL;  //该操作是非常有必要的,因为free过后,p1所指的空间归还,不能被使用
	            //该操作可避免非法访问内存
	return 0;
}

3.calloc
在这里插入图片描述
函数功能:开辟一块空间,该空间有num个size字节的元素,并且会将所有字节初始化为0。

函数参数
1.元素个数
2.元素的字节大小

int main()
{
	int *arr = (int*)calloc(10, sizeof(int));
	if (arr != NULL)
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			printf("%d ", arr[i]);
		}
	}
	free(arr);
	arr = NULL;
	return 0;
}

在这里插入图片描述
4.realloc
该函数可以灵活的调整内存的大小
在这里插入图片描述
函数参数
1.指向要调整空间的指针
2.调整后的大小

返回值
调整后的内存的起始地址

该函数实际运行时会有两种结果:
1.当需调整的内存之后的空间足够时,直接在后面追加
2.当需调整的内存之后的空间不够时,重新开辟一块空间并将原空间的内容拷贝过来,返回新空间的起始地址。

实例:

int main()
{
	int i = 0;
	int *ps = (int *)calloc(10, sizeof(int)); //此时开辟了40个字节的空间
	if (ps != NULL)
	{
		int* tmp = realloc(ps, 80);//扩充到80字节
		if (tmp != NULL)
		{
			ps = tmp;
		}
	}
	for (i = 0; i < (80) / sizeof(int); i++)
	{
		ps[i] = i;
	}
	for (i = 0; i < (80) / sizeof(int); i++)
	{
		printf("%d ", ps[i]);
	}
	return 0;
}

在这里插入图片描述

常见的动态内存管理错误

1.对NULL指针解引用

int main()
{
	int * ps = (int*)malloc(INT_MAX / 4);
	*ps = 20;//当ps为NULL会发生什么?
	printf("%d\n", ps);
	free(ps);
	ps = NULL;
	return 0;
}

在这里插入图片描述
2.对动态内存的越界访问

int main()
{
	int *ps = (int *)malloc(10 * sizeof(int));
	int i = 0;
	if (ps != NULL)
	{
		for (i = 0; i < 12; i++)
		{
			ps[i] = i;   //当i>=10时,就会发生越界。
		}
	}
	free(ps);
	ps = NULL;
	return 0;
}

当i>=10时,就会发生越界。

3.对非动态开辟的内存进行free

int main()
{
	int i = 0;
	int *p = &i;
	free(p);
	return 0;
}

在这里插入图片描述
4.用free释放内存的一部分

int main()
{
	int i = 0;
	int *ps = (int *)malloc(40);
	if (ps != NULL)
	{
		for (i = 0; i < 5; i++)
		{
			*ps = i;
			ps++;
		}
	}
	free(ps);
	ps = NULL;
	return 0;
}

在这里插入图片描述
free需接收动态开辟的内存的起始地址。

5.对同一内存多次free

int main()
{
	int *ps = (int*)malloc(40);
	if (ps != NULL)
	{
		free(ps);
	}
	free(ps);
	return 0;
}

在这里插入图片描述
6.动态开辟的内存未释放(内存泄漏)

void test()
{
	int *ps = (int*)malloc(40);
	if (ps != NULL)
	{
		*ps = 20;
	}
}
int main()
{
	test();
	while (1);
	return 0;
}

ps:内存泄漏会导致内存利用率下降,当动态开辟的内存不用时需及时并正确的释放。

动态通讯录

1.test.c

#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
void menu()
{
	printf("******************\n");
	printf("*1.add****2.del***\n");
	printf("*3.seacher*4.show*\n");
	printf("*5.qsort**6.modify*\n");
	printf("*0.exit***********\n");
	printf("******************\n");
}
int main()
{
	int input = 0;
	struct contact s;
	Initial(&s);
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 0: 
			Destroy(&s);
			break;
		case 1:
			Add(&s);
			break;
		case 2:
			Del(&s);
			break;
		case 3:
			Seacher(&s);
			break;
		case 4:
			Show(&s);
			break;
		case 5:
			Qsort(&s);
			break;
		case 6:
			Modify(&s);
			break;
		default:
			printf("请重试\n");
			break;
		}
	} while (input);
	return 0;
}

2.function.c

#include"func.h"
int _compare(const void *elem1, const void *elem2)
{
	return strcmp(((struct people*)elem1)->name 
		,((struct people*)elem2)->name);
}
void Destroy(struct contact *s)
{
	free(s->arr);
	s->arr = NULL;
	s->max = 0;
	s->sz = 0;
}
void Show(struct contact *s)
{
	if (s->sz!=0)
	{
		printf("%-15s\t%-15s\t%-15s\n", "名字", "电话", "地址");
		int n = s->sz;
		int i = 0;
		for (i = 0; i < n ; i++)
		{
			printf("%-15s\t", (s->arr[i].name));
			printf("%-15s\t", (s->arr[i].phone));
			printf("%-15s\t\n", (s->arr[i].addr));
		}
	}
	return;
}
int Find(char*a,struct contact *s)
{
	int i = 0;
	int n = s->sz;
	for (i = 0; i < n; i++)
	{
		if (strcmp(a, s->arr[i].name) == 0)
			return i;
	}
	return -1;
}
void Initial(struct contact *s)
{
	s->sz = 0;
	struct people * tmp = (struct people *)malloc(default_num*sizeof(s->arr[0]));
	if (tmp != NULL)
	{
		s->arr = tmp;
		s->max = default_num;
	}
	else
		printf("开辟失败\n");
}
int Add(struct contact *s)
{
	if (s->max == s->sz)
	{
		struct people * tmp = (struct people *)realloc
			(s->arr, (s->max + 2)*sizeof(s->arr[0]));
		if (tmp != NULL)
		{
			s->arr = tmp;
			int n = s->sz;
			printf("请输入:\n");
			printf("请输入名字。\n");
			scanf("%s", &(s->arr[n].name));
			printf("请输入电话。\n");
			scanf("%s", &(s->arr[n].phone));
			printf("请输入住址。\n");
			scanf("%s", &(s->arr[n].addr));
			s->sz++;
			s->max += 2;
		}
	}
	else
	{
		int n = s->sz;
		printf("请输入:\n");
		printf("请输入名字。\n");
		scanf("%s", &(s->arr[n].name));
		printf("请输入电话。\n");
		scanf("%s", &(s->arr[n].phone));
		printf("请输入住址。\n");
		scanf("%s", &(s->arr[n].addr));
		s->sz++;
	}
	return 0;
}


void Modify(struct contact *s)
{
	printf("请输入要修改的名字->\n");
	char a[name_max] = {0};
	scanf("%s", &a);
	int pos = Find(a,s);
	if (pos >= 0)
	{
		printf("请输入:\n");
		printf("请输入名字。\n");
		scanf("%s", &(s->arr[pos].name));
		printf("请输入电话。\n");
		scanf("%s", &(s->arr[pos].phone));
		printf("请输入住址。\n");
		scanf("%s", &(s->arr[pos].addr));
	}
	else
		printf("此用户不存在\n");
	return;
}

void Del(struct contact *s)
{
	int n = 0;
	if (0 == s->sz)
	{
		printf("通讯录没人。\n");
		return;
	}
	else
	{
		printf("请输入要删除的名字\n");
		char sname[10];
		scanf("%s", sname);
		n = Find(sname, s);
		if (n < 0)
		{
			printf("不存在此人。\n");
			return;
		}
		else
		{
			for (; n < s->sz - 1; n++)
			{
				s->arr[n] = s->arr[n + 1];
			}
			s->sz--;
		}
	}
	return;
}
void Seacher(struct contact *s)
{
	if (s->sz == 0)
	{
		printf("先加加人吧。\n");
		return ;
	}
	printf("请输入人名\n");
	char sname[10];
	scanf("%s", sname);
	int n = Find(sname, s);
	if (n >= 0)
	{
		printf("%-15s\t%-15s\t%s-15\n", "名字", "电话", "地址");
		printf("%-15s\t", (s->arr[n].name));
		printf("%-15s\t", (s->arr[n].phone));
		printf("%-15s\t\n", (s->arr[n].addr));
		return;
	}
	printf("查无此人\n");
	return;
}
void Qsort(struct contact *s)
{
	qsort(s->arr, s->sz, sizeof(s->arr[0]), _compare);
}

3.func.h

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 1000
#define name_max 10
#define phone_max 20
#define addr_max 10
#define default_num 3
void Destroy(struct contact *s);
void Qsort(struct contact *s);
void Initial(struct contact *s);
void Del(struct contact *s);
int Add(struct contact *s);
void Show(struct contact *s);
void Seacher(struct contact *s);
void Modify(struct contact *s);
struct people
{
	char name[name_max];
	char phone[phone_max];
	char addr[addr_max];
};
struct contact
{
	struct people* arr;
	int sz;
	int max;
};

ps:只需在静态的基础上修改一下初始化函数和Add函数和结构体contact即可,最后需释放动态内存。

如有错误,还望见谅。

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值