開飯了,之前寫的通訊錄,是否會有人覺得申請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();}
👍 總結
使用動態內存管理,以及文件操作優化了靜態通訊錄不足,加上了背景音樂,如果對你有幫助的話,請一鍵三連,謝謝大家了