通讯录进阶——动态内存和文件存取

前言

  • 在简易通讯录版本为基础,修改为可动态增长的通讯录内存大小,以及将录入的通讯录内容保存在本地文件中,并在下一次录入前导入到本地内存

动态控制通讯录大小

  • 修改通讯录的结构体

sz 记录通讯录中信息个数,初始为0
capacity 记录通讯录内存大小,初始为0

typedef struct Contact{
    PeoInfo* data;
    int sz;
    int capacity;
}Contact;
  • 新增检查通讯内存函数

在每次导入或者新增信息前,检查通讯里剩余内存,内存不足则动态增长

void Check_Capacity(Contact* pc){
    assert(pc);
    if(pc->sz == pc->capacity){
        PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity+3) * sizeof(PeoInfo));
        if(tmp != NULL){
            pc->data = tmp;
            pc->capacity += 3;
            printf("增容成功\n");
        }
        else{
            perror("Check_Capacity::realloc");
            return;
        }
    }
}
  • 新增销毁通讯录函数
void DestoryContact(Contact* pc) {
    free(pc->data);
    pc->sz = 0;
    pc->capacity = 0;
    pc->data = NULL;
    printf("销毁成功\n");
}

在文件中储存和导入通讯录信息

  • 新增储存函数

将通讯录数据以二进制形式储存到文件 Contact.dat

void SaveContact(const Contact* pc){
    FILE* pf = fopen("Contact.dat","wb");
    if (NULL == pf) {
        perror("SaveContact::fopen");
        return;
    }
    for (int i = 0; i < pc->sz; i++) {
        fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
    }
    printf("保存通讯录成功\n");
    fclose(pf);
    pf = NULL;
}
  • 新增导入函数

从文件 Contact.dat 以二进制形式导入通讯录信息到内存中

void LoadContact(Contact* pc) {
    // 打开文件
    FILE* pf = fopen("contact.dat","rb");
    if(NULL == pf){
        perror("LoadContact::fopen");
        return;
    }
    else{
        // 暂存读取的数据
        PeoInfo tmp = { 0 };
        // 读文件
        while(fread(&tmp, sizeof(PeoInfo), 1, pf)){
            // 导入前也得检查内存大小
            Check_Capacity(pc);
            pc->data[pc->size++] = tmp;
        }
        printf("通讯录导入成功\n");
    }
    PrintContact(pc);
    // 关闭文件
    fclose(pf);
    pf = NULL;
}
  • 修改初始化函数
void InitContact(Contact* pc){ 
    assert(pc);
    pc->sz = 0;
    pc->capacity = 3;
    pc->data = (PeoInfo*)malloc(sizeof(PeoInfo) * pc->capacity);
    if (NULL == pc->data) {
		perror("InitContact::malloc");
		return;
	}
	//初始化通讯录
    memset(pc->data, 0, pc->capacity * sizeof(pc->data));
    // 导入已有通讯录
    LoadContact(pc);
}

运行截图

  • 首次运行

通讯录进阶——动态内存和文件存取_第1张图片
通讯录进阶——动态内存和文件存取_第2张图片

  • 第二次运行

通讯录进阶——动态内存和文件存取_第3张图片

你可能感兴趣的:(C语言,c语言)