【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.pswp.cn/news/41718.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41718.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41718.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機器學習基礎(三)

邏輯回歸 場景 垃圾郵件分類 預測腫瘤是良性還是惡性 預測某人的信用是否良好 正確率與召回率 正確率與召回率(Precision & Recall)是廣泛應用于信息檢索和統計學分類領域的兩個度量值,用來評價結果的質量。 一般來說,正確率就是檢索出來的條目有多少是正確的,召回率就…

salesforce創建定時任務時明明implements the Schedulable interface卻提示不是的解決方法

Apex類&#xff1a; global class TimesheetWeeklyJob implements Schedulable{global void execute( SchedulableContext SC ) {WeeklyTimesheetProcess.markSubmitted();WeeklyTimesheetProcess.createNewSheets();} }卻提示&#xff1a; Error: You must select an Apex cl…

數據結構:二叉樹的遞歸實現(C實現)

個人主頁 &#xff1a; 個人主頁 個人專欄 &#xff1a; 《數據結構》 《C語言》 文章目錄 前言一、樹的概念二、二叉樹二叉樹的概念二叉樹的性質 三、二叉樹鏈式結構實現二叉樹節點定義創建二叉樹節點遍歷二叉樹先序遍歷二叉樹(BinaryTreePrevOrder)中序遍歷二叉樹(BinaryTree…

Air780EG —— 合宙4G定位解決方案

定位模式&#xff1a; 外部單片機控制模式(常見于AT固件客戶)&#xff1a; 開機 -> 搜星 -> 定位成功 -> 上報 -> 關機 780E自行控制模式(常見于二次開發客戶&#xff0c;AT用戶也可以使用): 開機 -> 搜星 -> 定位成功 -> 模塊休眠&#xff0c;關閉GP…

億發創新中醫藥信息化解決方案,自動化煎煮+調劑,打造智能中藥房

傳統中醫藥行業逐步復興&#xff0c;同時互聯網科技和人工智能等信息科技助力中醫藥行業逐步實現數字化轉型。利用互聯網、物聯網、大數據等科技&#xff0c;實現現代科學與傳統中醫藥的結合&#xff0c;提供智能配方顆粒調配系統、中藥自動化調劑系統、中藥煎配智能管理系統、…

【從零學習python 】40.python魔法方法(一)

文章目錄 魔法方法1. __init__ 方法2. __del__ 方法3. __str__ 方法4. __repr__ 方法5. __call__ 方法進階案例 魔法方法 Python 里有一種方法&#xff0c;叫做魔法方法。Python 的類里提供的&#xff0c;兩個下劃線開始&#xff0c;兩個下劃線結束的方法&#xff0c;就是魔法…

如何切換goland之中的版本號(升級go 到1.20)

go 安裝/版本切換_go 切換版本_云滿筆記的博客-CSDN博客 用brew就行&#xff1a; echo export PATH"/opt/homebrew/opt/go1.20/bin:$PATH" >> ~/.zshrc

[國產MCU]-BL602開發實例-OLED-SSD1306驅動與U8g2移植

OLED-SSD1306驅動與U8g2移植 文章目錄 OLED-SSD1306驅動與U8g2移植1、OLED介紹2、SSD1306介紹2、U8g2介紹3、U8g2移植3.1 定義U8g2圖形庫的移植函數3.2 移植函數實現3.3 移植函數調用4、驅動測試本文將詳細介紹如何在BL602中移植U8g2圖形庫,并通過U8g2庫驅動OLED SSD1306顯示屏…

Linux6.40 Kubernetes 配置資源管理

文章目錄 計算機系統5G云計算第三章 LINUX Kubernetes 配置資源管理一、Secret1.Secret 四種類型1&#xff09;kubernetes.io/service-account-token2&#xff09;Opaque3&#xff09;kubernetes.io/dockerconfigjson4&#xff09;kubernetes.io/tls 2.Pod 需要先引用才能使用某…

React入門 jsx學習筆記

一、JSX介紹 概念&#xff1a;JSX是 JavaScript XML&#xff08;HTML&#xff09;的縮寫&#xff0c;表示在 JS 代碼中書寫 HTML 結構 作用&#xff1a;在React中創建HTML結構&#xff08;頁面UI結構&#xff09; 優勢&#xff1a; 采用類似于HTML的語法&#xff0c;降低學…

因果推斷(四)斷點回歸(RD)

因果推斷&#xff08;四&#xff09;斷點回歸&#xff08;RD&#xff09; 在傳統的因果推斷方法中&#xff0c;有一種方法可以控制觀察到的混雜因素和未觀察到的混雜因素&#xff0c;這就是斷點回歸&#xff0c;因為它只需要觀察干預兩側的數據&#xff0c;是否存在明顯的斷點…

【C++入門到精通】C++入門 —— list (STL)

閱讀導航 前言一、list簡介1.概念2.特點 二、list的使用1.list的構造2.常見的操作?std::list類型的增、刪、查、改 三、list與vector的對比溫馨提示 前言 文章綁定了VS平臺下std::list的源碼&#xff0c;大家可以下載了解一下&#x1f60d; 前面我們講了C語言的基礎知識&…

C語言實例_獲取文件MD5值

一、MD5介紹 MD5&#xff08;Message Digest Algorithm 5&#xff09;是一種常用的哈希函數算法。將任意長度的數據作為輸入&#xff0c;并生成一個唯一的、固定長度&#xff08;通常是128位&#xff09;的哈希值&#xff0c;稱為MD5值。MD5算法以其高度可靠性和廣泛應用而聞名…

全球磁強計市場價值約為16.2億美元,預測期內將以超過5.21%的增長率增長

磁強計是一種用于測量磁場強度和方向的儀器。它可以檢測和測量地球磁場、物體的磁性、地下礦藏、磁性材料等。磁強計在地球科學、物理學、地質學、勘探、礦業等領域具有廣泛的應用。 根據阿譜爾&#xff08;APO&#xff09;的統計及預測&#xff0c;2022年全球磁強計市場價值約…

跳跳!(c++題解)

題目描述 你是一只小跳蛙&#xff0c;你特別擅長在各種地方跳來跳去。 這一天&#xff0c;你和朋友小 F 一起出去玩耍的時候&#xff0c;遇到了一堆高矮不同的石頭&#xff0c;其中第 ii 塊的石頭高度為 hi?&#xff0c;地面的高度是 h0?0。你估計著&#xff0c;從第 ii 塊…

ts與vue

ts與Vue 如果你已經學習了typeScript,但不知道如何在vue項目中使用&#xff0c;那么這篇文章將會很適合你。參考千峰教育 kerwin視頻 1.會自動推導&#xff0c;隱士推導。提示 類型系統。 獨立模塊。 isolatedModules選項&#xff1a;是否配置為獨立的模塊。 減少報錯 let …

dispatcherServlet在tomcat啟動時如何被加載(1)

目錄 在springboot工程中, 如何添加一個servlet呢? 方法1 : 使用WebServlet注解 方法2 : 使用ServletRegistrationBean進行注冊 springmvc 采用的就是方式2和springboot集成的, 看一下源碼 springboot 字段裝配里面有這個類, 看一下源碼 90行, 創建了一個DispatcherServlet對象…

深入探究Socks5代理與IP代理在網絡安全與爬蟲中的應用

1. Socks5代理&#xff1a;打開網絡隧道的多功能工具 Socks5代理是一種流行的代理協議&#xff0c;它在傳輸層為數據包提供了隧道。相較于之前的版本&#xff0c;Socks5不僅支持TCP連接&#xff0c;還可以處理UDP流量&#xff0c;使其在需要實時數據傳輸的應用中表現出色。在網…

Zabbix配置通用的TCP/IP:port監控項

我們經常的用接口&#xff0c;比如說FTP、HTTP、DNS、數據庫接口&#xff0c;都可以用IP:PORT方式探測其是否存活&#xff0c;那么我們去繁就簡&#xff0c;就簡單監控一下IP&#xff1a;PORT吧&#xff01; 1、新建主機&#xff1a; 填入主機名稱、群組、Agent就是127.0.0.1…

解決Adobe Flash Player已被屏蔽

問題&#xff1a;該插件不支持 原因&#xff1a;現在瀏覽器默認禁用flash 博主當前使用的是谷歌瀏覽器Chrome 2個主要方法都已經失效 搜索一圈后&#xff0c;之前博客給出的2個主要方法都已經失效。 1、flash.cn 下載本地播放器 2、在chrome中打開flash的禁用開關 2023年解…