目录
前言
之前写了通信录的静态版本,但是如果联系人个数多余100就不能存入,这次通过动态内存写通讯录就解决了这个问题。
1.改进办法
1.1申请动态内存
通过malloc函数申请动态内存
void* malloc (size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
- 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己
来决定。
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
1.2添加内存
通过realloc函数增加内存
void* realloc (void* ptr, size_t size);
- ptr 是要调整的内存地址
- size 调整之后新大小
- 返回值为调整之后的内存起始位置。
- 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新 的空间。
1.3销毁动态内存
通过free释放内存
void free (void* ptr);
free函数用来释放动态开辟的内存。
- 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
2.添加代码
2.1改变结构体定义
2.1.1分析
struct PeoInfo *data;//指向存放数据的空间 从结构体数组变成指针
int sz;//已经放进去的信息 从个数变成已有信息的个数
int capacity;//容量
2.1.2代码
//通讯录
struct contact
{
struct PeoInfo *data;
int sz;
int capacity;
};
2.2初始化通讯录
2.2.1分析
1>用assert函数断言pc
2>用malloc函数开辟内存空间
3>若开辟内存失败,用perror提示,若成功,则继续
4>设置已放入信息个数为0和初识容量
2.2.2代码
//初始化通讯录
void Initcontact(struct contact* pc)
{
assert(pc);
pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
if (pc->data == NULL)
{
perror("Initcontact()");
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
2.3销毁通讯录
2.3.1分析
用动态内容开辟空间,用完结束后一定要释放内存,否则就会内存泄漏
1>用free函数释放内存,把指针置空,防止产生野指针
2>容量和已存入信息赋0
2.3.2代码
//销毁通讯录
void Destroycontact(struct contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
2.4添加信息
2.4.1分析
在添加联系人信息时,如果空间不够,则进入check_capacity函数进行增容
1>判断空间是否已满,若满了进入if语句进行增容,若没有返回1
2>用realloc函数增加空间
3>若增加空间成功,每次增加INC_SZ个空间
2.4.2代码
//增加信息
static int check_capacity(struct contact*pc)
{
//空间已满
if (pc->sz == pc->capacity)
{
//增容
struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity+INC_SZ )* sizeof(struct PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
return 1;
}
else
{
perror("Addcontact()");
return 0;
}
}
else
return 1;
}
3.代码
3.1test.c
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
void meun()
{
printf("********************************\n");
printf("****1.add 2.del ***\n");
printf("****3.search 4.modify ***\n");
printf("****5.show 6.sort ***\n");
printf("****0.exit ****************\n");
printf("********************************\n");
}
int main()
{
int input = 0;
struct contact con;
//初识化通讯录
Initcontact(&con);
do {
meun();
printf("请选择>\n");
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:
Sortcontact(&con);
break;
case 0:
Destroycontact(&con);
printf("退出通讯录\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
3.2contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
//初始化通讯录
void Initcontact(struct contact* pc)
{
assert(pc);
pc->data = (struct PeoInfo*)malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
if (pc->data == NULL)
{
perror("Initcontact()");
return;
}
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
}
//销毁通讯录
void Destroycontact(struct contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
//增加信息
static int check_capacity(struct contact*pc)
{
//空间已满
if (pc->sz == pc->capacity)
{
//增容
struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity+INC_SZ )* sizeof(struct PeoInfo));
if (ptr != NULL)
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功\n");
return 1;
}
else
{
perror("Addcontact()");
return 0;
}
}
else
return 1;
}
void Addcontact(struct contact* pc)
{
assert(pc);
if (0 == check_capacity(pc))
{
return;
}
//增加信息
printf("请输入名字>\n");
scanf("%s", pc->data[pc->sz].name);//字符串的名字是首地址
printf("请输入性别>\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄>\n");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话>\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址>\n");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
//显示信息
void Showcontact(const struct contact* pc)
{
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-30s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
int Find(const struct contact* pc, char name[])
{
for (int i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name));
return i;
}
return -1;
}
//删除联系人
void Delcontact(struct contact* pc)
{
char name[MAX_name];
printf("请输入要删除的联系人的名字\n");
scanf("%s", name);
int ret=Find(pc, name);
//查找指定人是否存在
if (ret == -1)
{
printf("联系人不存在\n");
return;
}
for (int j = 0; j < pc->sz-1; j++)
{
pc->data[j] = pc->data[j+1];
}
pc->sz--;
printf("删除成功\n");
}
//查找指定联系人的信息
void Searchcontact(const struct contact* pc)
{
char name[MAX_name];
printf("请输入要查找的人的名字:>");
scanf("%s", name);
//查找一下指定的人是否存在
int ret = Find(pc, name);
if (ret == -1)
printf("要查找的人不存在\n");
else
{
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-20s\t%-5s\t%-5d\t%-12s\t%-30s\n", pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].age,
pc->data[ret].tele,
pc->data[ret].addr);
}
}
//修改
void Modifycontact(struct contact* pc)
{
char name[MAX_name];
printf("请输入要查找人的名字\n");
scanf("%s", name);
//查找指定人是否存在
int ret = Find(pc, name);
if (ret == -1)
{
printf("要修改的人不存在\n");
return;
}
//修改信息
printf("请输入名字>\n");
scanf("%s", pc->data[pc->sz].name);//字符串的名字是首地址
printf("请输入性别>\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄>\n");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话>\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址>\n");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
//排序
void CmpByName(const void* e1,const void* e2)
{
return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
void CmpByAge(const void* e1, const void* e2)
{
return ((struct PeoInfo*)e1)->age-((struct PeoInfo*)e2)->age;
}
void Sortcontact(struct contact* pc)
{
按名字排
//qsort(pc->data, pc->sz, sizeof(struct PeoInfo), CmpByName);
//按年龄排
qsort(pc->data, pc->sz, sizeof(struct PeoInfo), CmpByAge);
}
3.3contact.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 12
#define MAX_addr 30
#define DEFAULT_SZ 2
#define INC_SZ 2
//表示一个人的信息
struct PeoInfo
{
char name[MAX_name];
char sex[MAX_sex];
int age;
char tele[MAX_tele];
char addr[MAX_addr];
};
//通讯录
struct contact
{
struct PeoInfo *data;//指向存放数据的空间
int sz;//已经放进去的信息
int capacity;//容量
};
//初始化通讯录
void Initcontact(struct contact* pc);
//增加信息
void Addcontact(struct contact* pc);
//显示联系人
void Showcontact(const struct contact* pc);
//删除联系人
void Delcontact(struct contact* pc);
//查找联系人
void Searchcontact(const struct contact* pc);
//修改
void Modifycontact(struct contact* pc);
//排序
void Sortcontact(struct contact* pc);
//销毁通讯录
void Destroycontact(struct contact* pc);