日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

完美C语言通讯录(含代码)

發布時間:2023/12/31 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 完美C语言通讯录(含代码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C語言通訊錄大作業,支持永久數據儲存,無內存浪費。

相關部分介紹

本工程用到庫文件stdio.h 、stdlib.h 、string.h 、error.h
對于內存的管理使用了動態內存分配,每存入一個人的信息,就分配相應大小的空間。
相對于其他工程關閉程序后就會丟失信息,本工程支持文件操作,關閉系統時會將錄入的信息寫入一個contact.txt文件中,下次打開系統時又會錄入信息。

代碼詳解

contact.h

項目頭文件,聲明了兩個結構體

struct contact {char name[8]; //姓名char sex[8]; //性別int age; //年齡char ID[12]; //電話 };struct NumofCon {int Num; //作用是表示現在有幾個人的信息被存到通訊錄中,方便開辟內存struct contact p[];//柔性數組,可以使用動態內存開辟空間 };

contact.c

這個源文件是代碼的主要部分,相關功能的函數全都存儲在這里

第一個函數:通訊錄初始化函數

struct NumofCon* Contact_Init(void) {struct NumofCon* ps = (struct NumofCon*) malloc(4+32*1);if(ps == NULL){printf("%s\n",strerror(errno));}ps->Num = 0;return ps; }

該函數返回一個struct NumofCon型的指針,對應第二個聲明的結構體第一行就是這個代碼最重要的一部分,開辟一個4+321字節大小的內存,并把他的指針傳給ps,如果開辟失敗就返回空指針,printf就會打印失敗原因。注意,strerror(errno);函數使用需要應用errno.h頭文件。
開辟字節的大小要取決于struct NumofCon結構體的大小。
將ps指向的結構體里的Num成員賦值成0,因為還沒有信息被儲存。

第二個函數:向通訊錄中增加信息

struct NumofCon* contact_add(struct NumofCon* ps) {ps->Num++;struct NumofCon* ps2 = (struct NumofCon*) realloc(ps,4+32*(ps->Num));if(ps2 == NULL){printf("%s\n",strerror(errno));}int i = ps2->Num-1;printf("請輸入姓名:");scanf("%s",ps2->p[i].name);printf("請輸入姓別:");scanf("%s",ps2->p[i].sex);printf("請輸入年齡:");scanf("%d",&(ps2->p[i].age));printf("請輸入電話:");scanf("%s",ps2->p[i].ID);ps = ps2;ps2 = NULL;return ps; }

Num加一,告訴系統有新人要存入。Num的值取決于通訊錄內有多少人。
使用realloc函數調整開辟內存的大小,并把新的地址傳給ps2,用if語句判斷是否開辟成功。
定義i作為柔性數組的下標,下標的值為Num-1。
接下來就是信息錄入過程,使用了結構體嵌套調用,沒有什么可講的。
我重點要說一下最后幾行,為什么要多定義一個ps2來儲存地址呢?這和realloc函數的特性有關。realloc函數是調整動態內存空間大小的函數,他的參數有兩個,一個是你要修改的地址,二是要修改的大小。假如要增加十個字節,如果ps指向的空間后面有足夠大小的空間,那新修改的地址就不會改變,但是如果后面空間不夠增加10個字節,系統就會在其他位置另起爐灶,并把原先的內容拷貝到新的地址里,并且釋放原來的空間。當內存調整失敗,返回空指針,直接用ps接受,那我們就沒法找回原先空間的地址,程序崩潰。所以ps2是一個保險選項,防止由于內存開辟失敗導致原有空間位置丟失。當函數執行到最后,ps2的使命結束,在置為空指針,防止越界訪問。

第三個函數,查詢,第四個函數,打印所有成員

void contact_find(struct NumofCon* ps) {int i=0;char name[8];printf("請輸入要尋找的人物姓名:");scanf("%s",name);while(strcmp(name,ps->p[i].name)){i++;}printf("姓名:%s\n",ps->p[i].name);printf("姓別:%s\n",ps->p[i].sex);printf("年齡:%d\n",ps->p[i].age);printf("電話:%s\n",ps->p[i].ID); }void contact_Printall(struct NumofCon* ps) {for(int i = 0;i<ps->Num; i++){printf("Num:%d\n",i+1);printf("姓名:%s\n",ps->p[i].name);printf("姓別:%s\n",ps->p[i].sex);printf("年齡:%d\n",ps->p[i].age);printf("電話:%s\n",ps->p[i].ID);} }

沒有什么好說的,只有查詢函數用了一個庫函數strcmp,聲明在string.h中

第五個函數,刪除

struct NumofCon* contact_delete(struct NumofCon* ps) {int i=0;char name[8];printf("請輸入要刪除的人物姓名:");scanf("%s",name);while(strcmp(name,ps->p[i].name)){i++;if(i>ps->Num-1){printf("沒有此人信息\n");return ps;}}for(;i < ps->Num; i++){strcpy(ps->p[i].name, ps->p[i+1].name);strcpy(ps->p[i].sex, ps->p[i+1].sex);ps->p[i].age = ps->p[i+1].age;strcpy(ps->p[i].ID, ps->p[i+1].ID);}ps->Num = ps->Num - 1;struct NumofCon* ps2 = (struct NumofCon*) realloc(ps,4+32*(ps->Num));if(ps2 == NULL){printf("%s\n",strerror(errno));}ps = ps2;ps2 = NULL;printf("%s的信息已經移除\n",name);return ps; }

這個函數的重點是刪除一個人后要把ps->Num的值減一,并且調整內存大小,后面成員的位置依次向前36個字節

到這里通訊錄的主要功能已經完成,現在要做數據的永久儲存,也就是把信息導入文件中,防止關閉程序后信息丟失。

保存數據到contact.txt文件中

void contact_serve(struct NumofCon* ps) {FILE* pf = fopen( "contact.txt", "w");int i = 0;if(pf == NULL){printf("%s\n",strerror(errno));}while(i < ps->Num){fprintf(pf, "%d ",i+1);fprintf(pf, "%s ",ps->p[i].name);fprintf(pf, "%s ",ps->p[i].sex);fprintf(pf, "%d ",ps->p[i].age);fprintf(pf, "%s\n",ps->p[i].ID);i++;}fclose(pf); }

注意,要在代碼當前路徑建立一個文件contact.txt,否則程序報錯。

讀取文件信息

struct NumofCon* Contact_read(struct NumofCon* ps) {struct contact file;int Num = 1;int check = Num-1;FILE* pf = fopen("contact.txt", "r");if(pf == NULL){printf("%s\n",strerror(errno));}char ch = fgetc(pf);if(ch == EOF)Num = 0;rewind(pf);while(Num){fscanf(pf, "%d", &Num);if(check == Num)break;check = Num;fscanf(pf, "%s", file.name);fscanf(pf, "%s", file.sex);fscanf(pf, "%d", &(file.age));fscanf(pf, "%s", file.ID);ps = (struct NumofCon*) realloc(ps,4+32*Num);ps->Num = Num;strcpy(ps->p[Num-1].name, file.name);strcpy(ps->p[Num-1].sex, file.sex);ps->p[Num-1].age = file.age;strcpy(ps->p[Num-1].ID, file.ID);}fclose(pf);return ps; }

上面兩個代碼涉及到文件操作系統,較為復雜,篇幅原因,我會新寫一篇文章來介紹。

main.c

將上面代碼都放在頭文件聲明后就可以寫主函數了,該系統為模塊化,主函數相對簡單

#include <stdio.h> #include "contact.h"int main() {int i;struct NumofCon* Con = Contact_Init();Con = Contact_read(Con);do{system("pause");system("cls");printf("------------CONTACT-------------\n");printf("-----1.添加---------2.查詢------\n");printf("-----3.顯示---------4.刪除------\n");printf("------------0.退出--------------\n");printf("--------------------------------\n");printf("輸入指令");scanf("%d",&i);if(i == 1)Con = contact_add(Con);if(i == 2)contact_find(Con);if(i == 3)contact_Printall(Con);if(i == 4)Con = contact_delete(Con);}while(i);contact_serve(Con);return 0; }

功能演示




一定要通過指令0退出,不然無法保存信息
現在我們打開文件看看


再次打開程序,直接使用3命令打印

我們沒有錄入信息,可是系統直接讀取了信息,是因為系統將文件里的信息讀取了。
也可以直接在contact文件中添加人物,但要遵守格式。

這就是相關代碼的講解,我會把工程上傳,需要自取。
https://download.csdn.net/download/Mr_Hanc_Tiskor/15533285

有關文件的那兩個函數和柔性數組我也會在下一篇文章講解。
如果本文對你有幫助,別忘了點贊哦。歡迎大家留言討論與大佬們的建議。

總結

以上是生活随笔為你收集整理的完美C语言通讯录(含代码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。