当前位置: 首页 > news >正文

【c语言】通讯录(动态版+文件+背景音乐)含源码

开饭了,之前写的通讯录,是否会有人觉得申请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();}

👍 总结

使用动态内存管理,以及文件操作优化了静态通讯录不足,加上了背景音乐,如果对你有帮助的话,请一键三连,谢谢大家了

http://www.lryc.cn/news/128632.html

相关文章:

  • c#后端获实体类多列最大值
  • 腾讯云国际轻量应用服务器使用流程是什么呢?
  • CentOS 8 非编译方式 yum 安装 FFmpeg
  • 【Linux命令详解 | ssh命令】 ssh命令用于远程登录到其他计算机,实现安全的远程管理
  • IP 地址监控工具
  • 基于OpenCV的人脸识别和模型训练系统(万字详解)
  • Docker容器与虚拟化技术:Docker镜像创建、Dockerfile实例
  • 每天一道leetcode:646. 最长数对链(动态规划中等)
  • 651页23万字智慧教育大数据信息化顶层设计及建设方案WORD
  • Vue3 使用json编辑器
  • centos7 docker离线安装教程
  • 解决爬虫上下行传输效率问题的实用指南
  • Vue2入门学习汇总
  • 收支明细高效管理,轻松查看和统计时间段内的开销收支明细!
  • c++ 成绩统计
  • PostgreSQL-UDF用户自定义函数-扩展插件
  • 接口测试及接口抓包常用测试工具和方法?
  • C语言入门_Day 6布尔数与比较运算
  • Java中的JDBC
  • Vue 安装开发者工具
  • oracle修改临时表出现已使用的事务正在处理临时表问题
  • RestTemplate
  • rabbitMQ服务自动停止(已解决
  • Qt平滑弹出页面
  • 第07天 Static关键字作用及用法
  • Redis扩容与一致性Hash算法解析
  • 【第七讲---视觉里程计1】
  • Linux: sched: might_sleep; 一个调试函数,演变为真实的睡眠函数,实至名归
  • (三) 搞定SOME/IP通信之CommonAPI库
  • windows bat脚本,使用命令行增加/删除防火墙:入站-出站,规则