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

简介: 【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();
}

👍 总结

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

目录
相关文章
|
17天前
|
Linux C语言
C语言获取文件长度
C语言获取文件长度
|
1月前
|
安全 算法 程序员
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
34 0
|
1月前
|
C语言
用c语言实现一个通讯录
用c语言实现一个通讯录
10 0
|
1月前
|
存储 C语言
C语言详解【通讯录的实现】
C语言详解【通讯录的实现】
|
1月前
|
C语言
C语言对文件的输入输出
C语言对文件的输入输出
17 0
C4.
|
1月前
|
存储 程序员 数据库
C语言顺序读写数据文件
C语言顺序读写数据文件
C4.
15 0
|
1月前
|
存储 C语言
C语言-打开与关闭文件
C语言-打开与关闭文件
21 1
|
3月前
|
存储 XML JSON
【C语言-通讯录的分析与实现】
我们以手机里面的通讯录为例,说明通讯录主要有以下什么功能,我们先用一张简单的图来说明一下
22 0
|
3月前
|
C语言
【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化
动态内存管理的函数有:malloc,calloc,ralloc,free,本文讲解动态内存函数和使用,如何进行动态内存管理,实现通讯录联系人容量的动态化,对常见动态内存错误进行总结。
35 0
|
2天前
|
存储 算法 C语言
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)