一、内存管理
C语言动态内存内存是非常重要的一部分,首先c的内存存储方式如下图:
其中,栈的空间是我们经常使用的,但是通常栈的大小只占内存的1%,因此,当我们使用较大的数据量时,栈就不够用了,而堆的空间几乎占据了整个内存,但是使用时需要程序员自己进行手动申请和释放。还有在设置变量时,类如通讯类存储联系人的数量,如果设置成固定长的数组,在联系人存满时就会出现问题,这时如果可以在程序运行过程中进行扩容就大大增加了程序的实用性。因此,c语言的动态内存管理就显得非常的重要。
二、申请内存方法
1.malloc
该函数向内存申请一块连续可用的空间,并返回指向这片空间的指针。
(1)如果开辟成功,则返回一个指向开辟好空间的指针。
(2)如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
(3)返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
(4)如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
void* malloc (size_t size)
2.calloc
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
void* calloc (size_t num, size_t size);
3. realloc
realloc函数的出现让动态内存管理更加灵活。 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存, 我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。 函数原型 如下:
void* realloc (void* ptr, size_t size);
4.free
free函数用来释放动态开辟的内存。
(1) 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
(2) 如果参数 ptr 是NULL指针,则函数什么事都不做。
void free(void* ptr);
三、动态内存版本通讯录
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef void(*Func)();
typedef struct PersonInfo
{
char name[1024];
char sex[1024];
char age[1024];
char phone[1024];
char adress[1024];
} PersonInfo;
typedef struct AdressBook
{
PersonInfo *persons;
int capacity;
int size;
} AdressBook;
AdressBook g_address_book;
void Init()
{
g_address_book.size = 0;
g_address_book.capacity = 100;
g_address_book.persons = (PersonInfo *)malloc(g_address_book.capacity * sizeof(PersonInfo));
for (int i = 0; i < g_address_book.capacity; i++)
{
g_address_book.persons[i].name[0] = '\0';
g_address_book.persons[i].phone[0] = '\0';
g_address_book.persons[i].adress[0] = '\0';
g_address_book.persons[i].sex[0] = '\0';
g_address_book.persons[i].age[0] = '\0';
}
}
int Menu()
{
int i = -1;
printf("========================\n");
printf(" 1. 添加联系人信息\n");
printf(" 2. 删除指定联系人信息\n");
printf(" 3. 查找指定联系人信息\n");
printf(" 4. 修改指定联系人信息\n");
printf(" 5. 显示所有联系人信息\n");
printf(" 6. 清空所有联系人\n");
printf(" 7. 排序(以名字排序)\n");
printf(" 8 .保存联系人到文件\n");
printf(" 9. 加载联系人\n");
printf(" 0. 退出\n");
printf("========================\n");
printf("请输入要选择操作的序号:");
fflush(stdin);
scanf("%d", &i);
return i;
}
int Judge_Input_Legal(int choice)
{
if (choice < 0 || choice > 9)
{
printf("输入有误请重新输入!\n");
return -1;
}
if (choice == 0)
{
printf("Goodbye\n");
return 0;
}
return choice;
}
void Empty()
{
//TMOD
}
void Add_Contact()
{
PersonInfo *person_info = &g_address_book.persons[g_address_book.size];
if (g_address_book.size >= g_address_book.capacity)
{
printf("内存已满进行扩容");
g_address_book.capacity = 2 * g_address_book.capacity;
//g_address_book.persons = (PersonInfo *)realloc(g_address_book.persons, g_address_book.capacity * sizeof(PersonInfo));
PersonInfo *p = (PersonInfo *)malloc(g_address_book.capacity * sizeof(PersonInfo));
for (int i = 0; i < g_address_book.size; i++)
{
p[i] = person_info[i];
}
free(g_address_book.persons);
g_address_book.persons = p;
}
printf("请输入要添加联系人的信息:\n");
printf("输入姓名:");
scanf("%s", person_info->name);
printf("输入性别:");
scanf("%s", person_info->sex);
printf("输入年龄:");
scanf("%s", person_info->age);
printf("输入电话:");
scanf("%s", person_info->phone);
printf("输入地址:");
scanf("%s", person_info->adress);
g_address_book.size++;
printf("添加联系人成功\n");
}
void Delet_Contact()
{
PersonInfo *person_info = &g_address_book.persons;
int num = 0;
printf("请输入要删除联系人的序号:");
scanf("%d", &num);
if (num < 0 || num >=g_address_book.size)
{
printf("输入有误");
return;
}
*(person_info + num) = *(person_info + g_address_book.size - 1);
g_address_book.size--;
printf("删除联系人成功\n");
}
void Search_Contact()
{
char search_name[1024] = " ";
PersonInfo *person_info = &g_address_book.persons;
printf("请输入要查找的姓名:");
scanf("%s", search_name);
for (int i = 0; i < g_address_book.size; i++)
{
if (0 == strcmp((g_address_book.persons + i)->name, search_name))
{
printf("[%d]\t%s\t%s\t%s\t%s\t%s\n",
i,
(person_info + i)->name,
(person_info + i)->sex,
(person_info + i)->age,
(person_info + i)->phone,
(person_info + i)->adress
);
}
}
}
void Update_Contact()
{
int num = 0;
PersonInfo *person_info = &g_address_book.persons;
printf("请输入要修改的序号:");
scanf("%d", &num);
printf("请输入新的姓名:");
scanf("%s", (person_info + num)->name);
printf("请输入新的性别:");
scanf("%s", (person_info + num)->sex);
printf("请输入新的年龄:");
scanf("%s", (person_info + num)->age);
printf("请输入新的电话:");
scanf("%s", (person_info + num)->phone);
printf("请输入新的住址:");
scanf("%s", (person_info + num)->adress);
printf("联系人信息修改成功\n");
}
void Print_Contact()
{
PersonInfo *person_info = &g_address_book.persons;
printf("打印共%d条联系人信息如下:\n", g_address_book.size);
printf("序号\t姓名\t性别\t年龄\t电话\t住址\n");
for (int i = 0; i < g_address_book.size; i++)
{
printf("[%d]\t%s\t%s\t%s\t%s\t%s\n",
i,
(g_address_book.persons + i)->name,
(g_address_book.persons+ i)->sex,
(g_address_book.persons+ i)->age,
(g_address_book.persons+ i)->phone,
(g_address_book.persons+ i)->adress
);
}
printf("打印全部信息成功\n");
}
void Clear_Contact()
{
g_address_book.size = 0;
printf("全部清空成功");
}
void Sort_Contact()
{
PersonInfo *person_info = &g_address_book.persons;
//PersonInfo *PersonInfo_tmp = &g_address_book.persons[g_address_book.size+1];
char PersonInfo_tmp[1024] = " ";
for (int i = 0; i < g_address_book.size; i++)
{
for (int j = 0; j < g_address_book.size - i-1; j++)
{
if (strcmp((person_info + j)->name, (person_info + j + 1)->name) > 0)
{
//*PersonInfo_tmp = *(person_info + j);
//*(person_info + j) = *(person_info + j + 1);
//*(person_info + j + 1) = *PersonInfo_tmp;
strcpy(PersonInfo_tmp, person_info + j);
strcpy(person_info + j, person_info + j + 1);
strcpy(person_info + j + 1, PersonInfo_tmp);
}
}
}
printf("排序成功\n");
}
{
Func arr[] =
{
Empty,//无作用,只为把数组0号元素占用,使序号与数组下标对应
Add_Contact,
Delet_Contact,
Search_Contact,
Update_Contact,
Print_Contact,
Clear_Contact,
Sort_Contact,
Save_Contact_file,
Load_Contact
};
Init();
while (1)
{
int choice = Menu(); //打印菜单并读取用户输入
choice = Judge_Input_Legal(choice);
if(choice == 0) break; //判断用户输入是否合法
if(choice < 0) continue;
arr[choice]();//转移表调用函数
}
return 0;
}