开饭了,之前写的通讯录,是否会有人觉得申请1000人的空间是不是有点用不上呀,怎么才能做到要多少申请多少个呢??我们学完动态内存管理,和文件的相关操作,终于可以继续完善我们的通讯录了
船新版本:
为了适应各个用户的体验,8.18日,系统升级,请各位用户查看最新的安装包,做出以下修改
1.为了不占用更多的空间,通讯录容量满时,进行扩容操作。
2.通讯录初始化,会加载文件中的通讯录成员信息,防止出现程序结束后,通讯录销毁问题。
3.增加背景音乐功能,用户在使用该通讯录时,有更好的用户体验,别人有的 咱们必须有
4.增加销毁通讯录功能。
5.增加将通讯录保存到文件功能。
👍 静态版链接
通讯录(静态版)
👍 通讯录结构体的修改
typedef struct pp {struct peoinfo *arr;int sz;int size;}pp;
size:通讯录容量大小,区别于sz(当前存了多少个人)
将struct peoinfo arr[1000]修改为struct peoinfo *arr
对arr指针指向的地方进行动态内存分配,将分配好的地址放到arr中去
👍 扩容函数
void Addbig(pp* p)
{if (p->sz == p->size){peoinfo* tmp = (peoinfo*)realloc(p->arr, (p->size + 2) * sizeof(peoinfo));if (tmp != NULL){p->arr = tmp;}p->size+= 2;printf("增容 + 2\n");}
}
当通讯录实际容纳的用户大小通讯录的当前容量时,开始扩容,使用realloc函数,参数1(要扩容空间的起始地址)参数2(扩容后总空间字节大小),将开辟的空间首地址放到tmp指针变量中去,如果扩容成功,将扩容好的首地址放到p->arr指针里面去,p->size+= 2,每次增加两个容量大小
👍 文件加载到通讯录函数
void Loadcontact(pp* p)
{FILE* fp=fopen("contact.txt", "rb");if (fp == NULL){perror("Loadcontact:");return;}peoinfo tmp = { 0 };while (fread(&tmp,sizeof(peoinfo),1,fp)){Addbig(p);p->arr[p->sz] = tmp;p->sz++;}fclose(fp);fp = NULL;
}
用二进制读的方式打开文件,如果未打开,返回空指针给fp,然后打印出错误,定义一个人信息的结构体变量,使用fread函数参数1(目标地址),参数2(一次读多少个字节,这里读一个人信息结构体的字节),参数3(每次读几个这样结构体),参数4(从那里读,文件指针),返回值是每次读多少个人信息结构体,如果小于参数3(0).则读完了,读不到一个完整人的结构体.每次从文件中读取数据,调用扩容函数,防止读取数据大于总容量,扩容函数会增加总容量大小,每次将一个人的信息读到结构体tmp中,将tmp里面的一个人信息赋值给p->arr[p->sz];然后当前存储的数目sz++;
然后关闭文件,将文件指针置空
👍 初始化通讯录函数
void Initcontanct(pp* p)
{/*p->sz = 0;memset(p->arr, 0, sizeof(p->arr));*/p->sz = 0;p->size = SIZE;p->arr = (peoinfo*)malloc(p->size * sizeof(peoinfo));if (p->arr == NULL){perror(" Initcontanct:malloc");return;}memset(p->arr, 0, p->size * sizeof(peoinfo));Loadcontact(p);}
初始化通讯录没有存入信息,p->sz=0;开始通讯录的容量可以存三个人,p->size = SIZE;前面定义 SIZE 为3,动态开辟三个人信息结构体大小的空间,将开辟空间的首地址传给指针变量p->arr;如果传的为空指针,则打印错误,memset,内存操作函数将创建三个容量大小的数据置为0,调用Loadcontact§;加载文件中的数据
👍 保存进文件函数
void Savecontact(pp* p)
{FILE* fp = fopen("contact.txt", "wb");if (fp == NULL){perror("Savecontact:");return;}int i = 0;for (i = 0; i < p->sz; i++){fwrite(p->arr+i, sizeof(peoinfo), 1, fp);}fclose(fp);fp = NULL;printf("保存成功\n");
}
以二进制写的方式打开文件,打开失败返回空指针,打印错误,使用fwrite函数参数(要写入文件的数据起始地址),参数2(每次写入的字节大小,)参数3(每次写1个人信息结构体大小),参数3(写入文件的地址,文件指针)循环向文件中写入通讯录每个用户信息,循环次数为p->sz,当前通讯录用户人数
👍 通讯录销毁函数
void DestroyContanct(pp* p)
{free(p->arr);p->arr = NULL;p->size = 0;p->sz = 0;printf("销毁成功\n");
}
free释放动态申请的内存,参数(动态申请空间的地址),指针置空,
容量清0,当前用户人数清0
👍背景音乐函数
头文件
#include<windows.h>
#include<mmsystem.h>//包含多媒体设备接口头文件
#pragma comment(lib,"winmm.lib")//加载静态库
函数实现
void bgm()
{ //打开音乐mciSendString("open ./music.MP3", 0, 0, 0);//后面参数不用管,写0即可//播放音乐mciSendString("play ./music.MP3", 0, 0, 0);//后面参数不用管
}
注意:上面路径是相对./文件名.文件类型,./是在当前目录下,也可以使用绝对路径,不能出现空格,文件类型最好用大写,使用qq音乐下载好音乐,点击主菜单,音频转码转成MP3格式
使用其他的音乐软件播放不出来(qq音乐打钱)
将音频文件放到当前目录下,在vs中找到解决方案,右击鼠标,找到在文件资源管理器中打开文件夹,放到图示位置即可
使用绝对路径复制上面的复制路径"D:\C-code\1\elementary-stage-of-c-language\通讯录(动态加文件)\通讯录(动态加文件)\music.mp3",将反斜杠改成双反‘'或者/也行。
如果出现以下错误
调试找到调试属性
高级-字符集
使用多字节字符集就ok了
#源码展示
contanct.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<windows.h>#include<mmsystem.h>//包含多媒体设备接口头文件
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#pragma comment(lib,"winmm.lib")//加载静态库
#define MAX_NAME 20
#define MAX_SEX 6
#define MAX_TEL 12
#define MAX_ADDR 20
#define SIZE 3
enum opion
{EXIT,ADD,DEL,SEARCH,MODIFY,SORT,PRINT,SAVE,MUSIC,DESTROY
};
typedef struct peoinfo {char name[MAX_NAME];char sex[MAX_SEX];int age;char tel[MAX_TEL];char addr[MAX_ADDR];}peoinfo;typedef struct pp {struct peoinfo *arr;int sz;int size;}pp;
void Initcontanct(pp* p);
void Addcontanct(pp* p);
void Printcontanct(pp* p);
void Delcontanct(pp* p);
void findcontanct(pp* p);
void modifycontanct(pp* p);
void Sortcontanct(pp* p);
void Addbig(pp* p);
void Loadcontact(pp* p);
void Savecontact(pp* p);
void bgm();
void DestroyContanct(pp* p);
contanct.c
#include"contanct.h"
//#include<windows.h>
#include<graphics.h>//包含图形库头文件
//#include<mmsystem.h>//包含多媒体设备接口头文件
//#pragma comment(lib,"winmm.lib")//加载静态库
void DestroyContanct(pp* p)
{free(p->arr);p->arr = NULL;p->size = 0;p->sz = 0;printf("销毁成功\n");
}
void Addbig(pp* p)
{if (p->sz == p->size){peoinfo* tmp = (peoinfo*)realloc(p->arr, (p->size + 2) * sizeof(peoinfo));if (tmp != NULL){p->arr = tmp;}p->size+= 2;printf("增容 + 2\n");}
}
void Loadcontact(pp* p)
{FILE* fp=fopen("contact.txt", "r");if (fp == NULL){perror("Loadcontact:");return;}peoinfo tmp = { 0 };while (fread(&tmp,sizeof(peoinfo),1,fp)){Addbig(p);p->arr[p->sz] = tmp;p->sz++;}fclose(fp);fp = NULL;
}
void Savecontact(pp* p)
{FILE* fp = fopen("contact.txt", "wb");if (fp == NULL){perror("Savecontact:");return;}int i = 0;for (i = 0; i < p->sz; i++){fwrite(p->arr+i, sizeof(peoinfo), 1, fp);}fclose(fp);fp = NULL;printf("保存成功\n");
}
void Initcontanct(pp* p)
{/*p->sz = 0;memset(p->arr, 0, sizeof(p->arr));*/p->sz = 0;p->size = SIZE;p->arr = (peoinfo*)malloc(p->size * sizeof(peoinfo));if (p->arr == NULL){perror(" Initcontanct:malloc");return;}memset(p->arr, 0, p->size * sizeof(peoinfo));Loadcontact(p);}void Addcontanct(pp* p)
{Addbig(p);printf("请输入姓名\n");scanf("%s", p->arr[p->sz].name);printf("请输入性别\n");scanf("%s", p->arr[p->sz].sex);printf("请输入年龄\n");scanf("%d", &(p->arr[p->sz].age));printf("请输入电话\n");scanf("%s", p->arr[p->sz].tel);printf("请输入地址\n");scanf("%s", p->arr[p->sz].addr);p->sz++;printf("录入成功\n");}
void Printcontanct(pp* p)
{int i = 0;printf("******************************************************\n");printf("%-10s %-5s %-5s %-12s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("******************************************************\n");for (i = 0; i < p->sz; i++){printf("%-10s %-5s %-5d %-12s %-20s\n", p->arr[i].name, p->arr[i].sex, p->arr[i].age, p->arr[i].tel, p->arr[i].addr);printf("******************************************************\n");}
}
int find(pp* p, char name[])
{int i = 0;for (int i = 0; i < p->sz; i++){if (!strcmp(p->arr[i].name, name))return i;}return -1;
}
void Delcontanct(pp* p)
{char name[MAX_NAME];printf("请输入要删除朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);for (int j = k; j < p->sz - 1; j++){p->arr[j] = p->arr[j + 1];}p->sz--;printf("删除成功\n");}
}
void findcontanct(pp* p)
{char name[MAX_NAME];if (p->sz == 0){printf("通讯录为空\n");return;}printf("请输入要查找朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);printf("******************************************************\n");printf("%-10s %-5s %-5s %-12s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-5s %-5d %-12s %-20s\n", p->arr[k].name, p->arr[k].sex, p->arr[k].age, p->arr[k].tel, p->arr[k].addr);printf("******************************************************\n");}
}
void modifycontanct(pp* p)
{char name[MAX_NAME];printf("请输入修改朋友的名字\n");scanf("%s", name);if (find(p, name) == -1){printf("查无此人\n");}else{int k = find(p, name);printf("请输入要修改朋友的信息\n");printf("修改性别->");scanf("%s", p->arr[k].sex);printf("修改年龄->");scanf("%d", &(p->arr[k].age));printf("修改电话->");scanf("%s", p->arr[k].tel);printf("修改地址->");scanf("%s", p->arr[k].addr);printf("修改成功\n");}
}
int int_cmp_age(const void* p1, const void* p2)//按年龄比较
{return ((struct peoinfo*)p1)->age - ((struct peoinfo*)p2)->age;
}
void Sortcontanct(pp* p)
{qsort(p->arr, p->sz, sizeof(peoinfo), int_cmp_age);printf("按年龄排序成功,快去打印吧\n");
}
void bgm()
{ //打开音乐mciSendString("open ./music.MP3", 0, 0, 0);//后面参数不用管//播放音乐mciSendString("play ./music.MP3", 0, 0, 0);//后面参数不用管
}
test.c
#include"contanct.h"
void menu()
{printf("#######################################\n");printf("#********* 1.add ***************#\n");printf("#********* 2.del ***************#\n");printf("#********* 3.search ***************#\n");printf("#********* 4.modify ***************#\n");printf("#********* 5.sort ***************#\n");printf("#********* 6.print ***************#\n");printf("#********* 7.save ***************#\n");printf("#********* 8.music ***************#\n");printf("#********* 9.Destroy***************#\n");printf("########## 0.exit ################\n");}
void test()
{pp pro;Initcontanct(&pro);int input;do {menu();scanf_s("%d", &input);switch (input){case ADD:Addcontanct(&pro);break;case DEL:Delcontanct(&pro);break;case SEARCH:findcontanct(&pro);break;case MODIFY:modifycontanct(&pro);break;case SORT:Sortcontanct(&pro);break;case PRINT:Printcontanct(&pro);break;case SAVE:Savecontact(&pro);break;case MUSIC:bgm();break;case DESTROY:DestroyContanct(&pro);break;case EXIT:printf("退出通讯录\n");break;default:printf("输入错误,请重新输入\n");break;}} while (input);
}void main()
{test();}
👍 总结
使用动态内存管理,以及文件操作优化了静态通讯录不足,加上了背景音乐,如果对你有帮助的话,请一键三连,谢谢大家了