无论是上面的静态版本的通讯录或者是动态版本的通讯录,在程序运行结束之后都会被销毁掉,就是保存的联系人的数据也会丢失,这显然不符合我们对通讯录的需求,我们正常需要的是能够在下一次打开通讯录的时候找到以前保存过的联系人的信息,这样才是有意义的通讯录,那我们可以把以上两个版本的通讯录进行改造,使它变成文件版本的通讯录,即把每次存进去的信息在程序关闭之前保存到文件当中,在下一次打开程序的时候自动加载到程序当中,这样才是符合我们需求的通讯录。
其实我们只需要增加两个函数即可,即退出程序前保存数据和运行程序时加载数据的函数:
//新增函数 //保存通讯录信息到文件中 void SaveContact(Contact* con) { assert(con); //以二进制写的形式打开文件“wb” FILE* pf = fopen("contact.txt", "wb"); if (pf == NULL) { perror("SaveContact"); return; } int i = 0; //遍历把数据逐一写到文件中 for (i = 0; i < con->sz; i++) { //参数意义:1.待写入数据的地址,2.结构体大小 //3.一次写入的数据的数量,逐一写入,4.存放数据的地址 fwrite(con->data + i, sizeof(peo_info), 1, pf); } fclose(pf);//关闭文件 pf = NULL; printf("保存成功!\n"); }
void check_capacity(Contact* con) { assert(con); if (con->capacity == con->sz) { peo_info* p = (peo_info*)realloc(con->data, sizeof(peo_info) * (con->capacity + 2)); if (p == NULL) { perror("realloc"); return; } else { con->data = p; con->capacity += 2; printf("增容成功!\n"); } } } //新增函数 void LoadContact(Contact* con) { assert(con); //由于保存数据时是用二进制的形式写进文件中 //所以需要用二进制读的形式打开文件 FILE* pf = fopen("contact.txt", "rb"); if (pf == NULL) { perror("LoadContact"); return; } //读数据,需要创建一个临时变量 peo_info tmp = { 0 }; int i = 0; //fread函数读到一个数据返回1,读不到数据返回返回0 //循环就停止 while (fread(&tmp, sizeof(peo_info), 1, pf)) { //读到一个数据需要先检查是否需要增容 check_capacity(con); con->data[i] = tmp;//对应位置进行结构体赋值即可 i++; con->sz++;//每加载一个数据数量sz+1 } printf("加载成功!\n"); fclose(pf);//关闭文件 pf = NULL; } void InitContact(Contact* con) { assert(con); peo_info* p = (peo_info*)calloc(2, sizeof(peo_info)); if (p == NULL) { perror("InitContact"); return; } con->data = p; con->sz = 0; con->capacity = 2; //新增函数,初始化完成后加载数据到程序中 //加载文件信息到通讯录 LoadContact(con); }
SaveContact函数保存数据在Destroy之前调用即可。
以上就是通讯录文件版本新增的两个函数,这个就是符合我们需求的通讯录的最终版本哦。你学会了吗?