怎样“动”起来?
之前写过一个静态版的通讯录,现在把它修改成为动态版的。
首先要做出的调整是:
通讯录类型
相比于静态内存的版本,动态内存的通讯录类型应该要维护3个变量。分别为:记录动态开辟内存的指针、当前通讯录录入了多少个人、当前通讯录的容量是多少。
我们假定现在通讯录初始可以存储3个人的信息,当存满了之后一次扩容2个空间。
所以通讯录的类型定义应该调整为:
接下来就要进行初步的动态开辟:
初始化函数
给data在堆区上申请一块连续的空间,将capacity初始化为当前的最大容量。
(对比静态版)
在后续的各项操作中,“添加联系人”涉及到动态内存的扩容,“退出通讯录”涉及到动态内存的释放,所以是需要进行修改的。
添加联系人函数
(对比静态版)
退出通讯录这一项需要多一项销毁通讯录的操作,销毁在堆区上的内存。
销毁通讯录
注:使用动态内存函数记得引用头文件stdlib.h
试运行
代码
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" void menu() { printf(" \n"); printf(" 1.add 2.del \n"); printf(" 3.search 4.modify \n"); printf(" 5.sort 6.print \n"); printf(" 0.exit \n"); printf(" \n"); } enum Option //定义枚举变量 { EXIT, ADD, DEL, SEARCH, MODIFY, SORT, PRINT }; int main() { int input = 0; Contact con; //创建一个通讯录变量 //初始化通讯录 InitContact(&con); do { menu(); printf("请选择:"); scanf("%d", &input); system("cls"); switch (input) { case ADD: //增 //添加联系人的信息 AddContact(&con); break; case DEL: //删 //删除联系人的信息 DelContact(&con); break; case SEARCH: //查 //查找指定联系人 SearchContact(&con); break; case MODIFY: //改 //修改指定联系人 ModifyContact(&con); break; case SORT: //排序 break; case PRINT: //打印出联系人的信息 PrintContact(&con); break; case EXIT: printf("退出通讯录\n"); //销毁通讯录 DestoryContact(&con); return; break; default: printf("输入错误,请重新输入\n"); break; } system("cls"); } while (input); return 0; }
const.h
#include <string.h> #include <windows.h> #include <stdlib.h> #include <stdio.h> #define MAX_NAME 20 //设置名字字符串的最大长度 #define MAX_SEX 10 //设置性别字符串的最大长度 #define MAX_TELE 12 //设置电话字符串的最大长度 #define MAX_ADDR 30 //设置地址字符串的最大长度 #define DEFAULT_SZ 3 //初始动态内存能存储的人数 #define INC_SZ 2 //动态内存一次要扩容的人数 //定义通讯录中每一个人的信息的类型 typedef struct PeoInfo { char name[MAX_NAME]; char sex[MAX_SEX]; int age; char tele[MAX_TELE]; char addr[MAX_ADDR]; }PeoInfo; //静态 //typedef struct Contact //{ // PeoInfo data[MAX];//存放了添加进来的人的信息 // int sz;//记录了当前通讯录中有效信息的个数 //}Contact; //动态 typedef struct Contact { PeoInfo* data;//记录堆区中开辟的空间的起始地址 int sz;//记录了当前通讯录中有效信息的个数 int capacity;//记录当前通讯录的最大容量 }Contact; //初始化通讯录 void InitContact(Contact* pc); //增加联系人 void AddContact(Contact* pc); //打印出联系人的信息 void PrintContact(const Contact* pc); //删除联系人的信息 void DelContact(Contact *pc); //查找指定联系人 void SearchContact(const Contact *pc); //修改指定联系人 void ModifyContact(Contact* pc); //销毁通讯录 void DestoryContact(Contact* pc);
const.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" //初始化通讯录(静态) //void InitContact(Contact* pc) //{ // pc->sz = 0; // memset(pc->data, 0, sizeof(pc->data));//memset内存设置 //} //初始化通讯录(动态) void InitContact(Contact* pc) { pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo)); //申请3个联系人的大小 if (pc->data == NULL) { perror("InitContact"); //如果开辟失败则报错 return; } pc->sz = 0; pc->capacity = DEFAULT_SZ; } void DestoryContact(Contact* pc) { free(pc->data); pc->data = NULL; pc->sz = 0; pc->capacity = 0; printf("销毁成功\n"); } //增加联系人 //void AddContact(Contact* pc) //{ // if (pc->sz == MAX) // { // printf("通讯录已满,无法添加"); // return; // } // //添加一个人的信息(静态) // int input = 0; // do // { // printf("请输入名字:"); // scanf("%s", pc->data[pc->sz].name); // // printf("请输入年龄:"); // scanf("%d", &(pc->data[pc->sz].age)); // // printf("请输入性别:"); // scanf("%s", pc->data[pc->sz].sex); // // printf("请输入电话:"); // scanf("%s", pc->data[pc->sz].tele); // // printf("请输入地址:"); // scanf("%s", pc->data[pc->sz].addr); // // printf("确认添加输入0,否则输入1重新开始添加\n"); // scanf("%d", &input); // } while (input); // // // pc->sz++; // printf("添加成功\n"); // Sleep(700); //} //增加联系人(动态) void AddContact(Contact* pc) { //考虑扩容 if (pc->sz == pc->capacity) { PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->sz + INC_SZ) * sizeof(PeoInfo));//3+2 if (ptr != NULL) { pc->data = ptr; pc->capacity += INC_SZ; printf("扩容成功\n"); } else { perror("AddContact"); printf("添加失败\n"); return; } } //添加一个人的信息 int input = 0; do { printf("请输入名字:"); scanf("%s", pc->data[pc->sz].name); printf("请输入年龄:"); scanf("%d", &(pc->data[pc->sz].age)); printf("请输入性别:"); scanf("%s", pc->data[pc->sz].sex); printf("请输入电话:"); scanf("%s", pc->data[pc->sz].tele); printf("请输入地址:"); scanf("%s", pc->data[pc->sz].addr); printf("确认添加输入0,否则输入1重新开始添加\n"); scanf("%d", &input); } while (input); pc->sz++; printf("添加成功\n"); Sleep(700); } //打印出联系人的信息 void PrintContact(const Contact* pc) { //打印标题 printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); //打印数据 int i = 0; for (i = 0; i < pc->sz; i++) { printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } int input = 0; printf("输入0返回主界面\n"); do { scanf("%d", &input); if(input != 0) printf("输入错误,请重新输入\n"); } while (input); system("cls"); } //通过名字查找,判断通讯录中其是否存在 //我们只需要它在当前源文件中产生作用,所以加上static static int FindByName(Contact* pc, char name[]) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) return i; } return -1;//找不到 } //删除联系人的信息 void DelContact(Contact* pc) { if (pc->sz == 0) { printf("通讯录为空,无需删除\n"); return; } char name[MAX_NAME] = { 0 }; //1.查找要删除的人,判断其是否存在 //存在or不存在 printf("请输入要删除的人的姓名:"); scanf("%s", name); int pos = FindByName(pc, name); if (pos == -1) { printf("要删除的人不存在\n"); return 0; } //2.删除 int i = 0; //这里删除的逻辑是将后面的元素往前覆盖一位,从而达到被覆盖的这一位被删除的目的 for (i = pos; i < pc->sz - 1; i++) //sz-1的原因是data[i]遍历到数组的最后一位时,其下一位是空白的,不需要将其往前覆盖 { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("删除成功\n"); Sleep(700); } //查找指定联系人 void SearchContact(const Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要查找的人的名字:"); scanf("%s", name); int pos = FindByName(pc, name); if (pos == -1) { printf("要查找的人不存在\n"); return; } else { printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "姓名", "年龄", "性别", "电话", "地址"); printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } int input = 0; printf("输入0返回主界面\n"); do { scanf("%d", &input); if (input != 0) printf("输入错误,请重新输入\n"); } while (input); system("cls"); } //修改指定联系人 void ModifyContact(Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要修改的人的名字:"); scanf("%s", name); int pos = FindByName(pc, name); if (pos == -1) { printf("要修改的人不存在\n"); return; } else { int input = 0; do { printf("请输入名字:"); scanf("%s", pc->data[pos].name); printf("请输入年龄:"); scanf("%d", &(pc->data[pos].age)); printf("请输入性别:"); scanf("%s", pc->data[pos].sex); printf("请输入电话:"); scanf("%s", pc->data[pos].tele); printf("请输入地址:"); scanf("%s", pc->data[pos].addr); printf("确认添加输入0,否则输入1重新开始添加\n"); scanf("%d", &input); } while (input); } }