<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
大家好~今天要實現一個非常有意思的東西–通訊錄。
為了實現通訊錄管理系統,為此,要保證實現以下的功能:
能夠存放1000個聯絡人的資訊、每個人的資訊包含:名字、年齡、性別、電話、地址、除此之外,還是實現:增加人的資訊、刪除人的資訊、修改指定人的資訊、查詢指定人的資訊、清空聯絡人的資訊、顯示聯絡人的資訊、排序通訊錄的資訊.
1.增加聯絡人資訊
2.刪除聯絡人資訊
3.查詢聯絡人資訊
4.修改聯絡人資訊
5.顯示聯絡人資訊
6.排序聯絡人資訊
7.清空聯絡人資訊
靜態版本的通訊錄首先宣告一個結構體型別(struct PeoInfo)用來描述一個人的聯絡人的各種資訊;
然後再宣告一個結構體型別(struct Contact)用來描述通訊錄,成員使用陣列開闢1000個聯絡人的記憶體空間實現通訊錄,陣列的型別為struct PeoInfo
最後就是對存放聯絡人資訊陣列的一系列存取操作,封裝各個函數實現各部分功能!
#define _CRT_SECURE_NO_WARNINGS 1 #include"contact.h" void menu() { printf("*******************************n"); printf("***** 1.add 2.del *****n"); printf("***** 3.search 4.modify *****n"); printf("***** 5.sort 6.print *****n"); printf("***** 7.clear 0.exit *****n"); printf("*******************************n"); } enum Option { EXIT, ADD, DEL, SEARCH, MODIFY, SORT, PRINT, CLEAR }; int main() { int input = 0; //建立通訊錄,結構體型別在標頭檔案中定義的,所以要引標頭檔案,MAX的定義在標頭檔案或者該原始檔內定義都是可以的,因為包含了標頭檔案 //但是如果把陣列和陣列元素個數sz定義成一個結構體,就要去標頭檔案中定義,那邊就需要MAX,如果MAX在test.c中定義的話,contact.h中就會報錯 //既然這樣,就直接把MAX定義在contact.h中去,即可。 //PeoInfo data[MAX] = { 0 };//不完全初始化 //通訊錄中當前有幾個元素: //int sz = 0; //建立通訊錄 Contact con; //con就是通訊錄,也可以直接進行初始化,但是為了更好的體現模組化,就對初始化通訊錄封裝一個函數。 //如果想把其中的一部分初始化為0,就必須使用函數來做了。 //初始化通訊錄 InitContact(&con); //初始化通訊錄的時候要對通訊錄中的內容進行修改,如果傳值呼叫的話,不會修改實參中的內容,而且效率低,所以要傳址呼叫。 do { menu(); printf("請選擇:>"); scanf("%d", &input); switch (input) { case ADD: //增加聯絡人資訊 AddContact(&con); //要把陣列和陣列元素個數都進行傳參,會比較麻煩,把兩者定義成一個新的結構體 break; case DEL: //刪除聯絡人資訊 DelContact(&con); break; case SEARCH: //查詢聯絡人資訊 SearchContact(&con); break; case MODIFY: //修改聯絡人資訊 ModifyContact(&con); break; case SORT: //排序聯絡人資訊 SortContact(&con); break; case PRINT: //雖然只是列印資訊,不會改變實參的資訊,但是考慮的效率的話,還是使用傳址呼叫比較好,結構體傳參最好傳地址。 PrintContact(&con); break; case CLEAR: //清空所有聯絡人資訊 ClearContact(&con); break; case EXIT: printf("退出通訊錄n"); break; default: printf("選擇錯誤,請重新選擇:>"); break; } } while (input); //如果有同名的,一律操作第一個出現該名字的那個成員,因為遍歷是從前往後遍歷的,在這裡不考慮同名的情況。 return 0; }
#define _CRT_SECURE_NO_WARNINGS 1 #include"contact.h" //初始化通訊錄 void InitContact(Contact* pc) { assert(pc); //記憶體設定函數 — memset() - 記憶體設定 (pc->sz) = 0; memset(pc->data, 0, sizeof(pc->data)); //pc->data 就相當於找到了整個陣列,而整個陣列可以使用陣列名來表示,所以可以使用data來表示整個陣列 //即:pc->data === data ,,,陣列名在第一個引數中沒有&和sizeof,代表的是陣列首元素的地址,第二個引數是把 //每一個位元組都設定成0,十進位制的0,轉為十六進位製表示形式就是0x 00,,pc->data === data,陣列名單獨放在 //sizeof中,代表的是整個陣列,計算的是整個陣列的大小,單位是位元組也可以寫成:MAX * sizeof(Contact) } //增加聯絡人 void AddContact(Contact* pc) { assert(pc); if (pc->sz == MAX) { printf("通訊錄已滿、無法新增新的聯絡人n"); return; //返回型別是void,也可以寫return,但是不能帶出去返回值。 } //通訊錄未滿,可以新增新成員,增加一個人的資訊 printf("請輸入名字:>"); scanf("%s", pc->data[pc->sz].name); printf("請輸入年齡:>"); scanf("%d", &(pc->data[pc->sz].age)); printf("請輸入性別:>"); scanf("%s", pc->data[pc->sz].sex); printf("請輸入電話:>"); scanf("%s", pc->data[pc->sz].tele); printf("請輸入地址:>"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("增加聯絡人成功n"); //在這裡,[ ]的優先順序等於->,,但是,data和[ ]是不可以先進行結合的,因為,這是在一個呼叫函數中,形參那部分接受到的只有指標變數pc //也就是說,如果後兩者進行結合的話,系統根本就不知道data是什麼東西,所以它結合出來是錯誤的,即,即使[ ]的優先順序等於->,但是後兩者不能 //進行結合會出錯,又因結合性從左到右所以,還是先讓data和->進行結合,即先進行pc->data的操作,所以在結構體成員變數中找到了整個陣列data //而整個陣列可以使用陣列名進行表示,知道了陣列名就可以再通過下標對陣列元素進行存取了。 } //顯示聯絡人資訊 void PrintContact(const Contact* pc) { assert(pc); //列印出所有人的資訊,即sz個人的資訊。 int i = 0; //列印標題 printf("%-10st%-5st%-5st%-12st%-50sn", "名字", "年齡", "性別", "電話", "地址");// t === tab //列印資料 for (i = 0; i < (pc->sz); i++) { printf("%-10st%-5dt%-5st%-12st%-50sn", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } //通過pc->data[i]找到陣列data中下標為i的元素,即找到了一個變數,再通過點來存取該人的姓名等,,由於姓名是一個陣列,找到的就是整個陣列,整個 //陣列又可以使用陣列名來表示,即:pc->data[i].name === name ,沒有sizeof和&,代表陣列首元素的地址,再通過%s進行列印字串,除了年齡是一個變數,其他的都是陣列,和name同理。 } //因為該函數只是為了滿足刪除,查詢,修改功能的需要,而這三個功能對應的函數的實現都會在該 .c 檔案內進行實現,所以,對於這個函數 //只需要在該 .c 檔案內執行即可,不許要暴露給別人,,所以,在前面加上static,就固定了該函數只在目前所在的 .c 檔案內進行工作即可。 //static 修飾函數,本質上是改變了函數的連結屬性。 static int Find_By_Name(const Contact* pc, char name[])//陣列形式接收,陣列形式接受的話就不考慮const的使用了。 { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0)//相等 //第一個引數先找到整個陣列,可以使用陣列名來表示,不是特例,即代表陣列首元素的地址,第二個引數也不是特例,也是陣列首元素的地址。 { return i; } } return -1; } //刪除聯絡人資訊 void DelContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; if (pc->sz == 0) { printf("通訊錄為空、不可以再進行刪除操作n"); return; } //刪除某個人的資訊 printf("請輸入要刪除人員的姓名:>"); scanf("%s", name); //1、查詢要刪除的人 //不管是刪除還是查詢還是修改,都需要使用到查詢這個功能,所以就單獨把該功能拿出來封裝一個函數; int pos = Find_By_Name(pc, name);//一級指標傳參和陣列名傳參 //不存在該人 if (pos == -1) { printf("要刪除的人員不存在n"); return; } //2、存在該人員,要進行刪除,把陣列該位置上的人員刪除之後,陣列後面的人員依次往前移動一個位置。 int i = 0; for (i = pos; i < (pc->sz - 1); i++) { pc->data[i] = pc->data[i + 1]; } //pc->sz -= 1; pc->sz--; //如果想刪除最後一個,是刪除不掉的,因為,如果10個元素,最後一個下標為9,判斷條件是<9,,所以不進入迴圈,但是 //迴圈後面還有pc->sz--,,成員個數少了1,再顯示人員資訊的時候,存取不到最後一個人員了,,即使沒刪掉,也存取不掉, //最後的結果和刪掉最後一個人員的效果是一樣的。 //假設MAX=3,把最後一個元素刪除,本質上並沒有從陣列中刪除掉,而是因為sz減1,列印的時候不存取最後一個元素,看起來和刪除的效果是一樣的,現在由於 //看起來刪了,本質上沒刪去,如果再新增新元素會怎麼樣呢? //因為刪除完之後,元素個數就會減去1,由原來的3變成了2,,再新增新元素的時候,就會直接把新元素的內容放在下標為2的位置上,這樣的話,即使之前的最後一個元素 //沒刪去,也會被新的元素覆蓋掉,新增完之後元素個數加1,再列印出來就是新增成員後的資訊,是對的。 printf("刪除聯絡人員成功n"); } //查詢聯絡人資訊 void SearchContact(const Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; //查詢某個人的資訊 printf("請輸入要查詢人員的姓名:>"); scanf("%s", name); int pos = Find_By_Name(pc, name); //要查詢的人員不存在 if (pos == -1) { printf("要查詢的人員不存在n"); return; } //2、存在該人員,找出之後並列印出該成員的資訊 //列印標題 printf("%-10st%-5st%-5st%-12st%-50sn", "名字", "年齡", "性別", "電話", "地址");// t === tab //列印資料 printf("%-10st%-5dt%-5st%-12st%-50sn", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } //修改指定聯絡人的資訊 void ModifyContact(Contact* pc) { assert(pc); char name[MAX_NAME] = { 0 }; //修改某個人的資訊 printf("請輸入要修改人員的姓名:>"); scanf("%s", name); int pos = Find_By_Name(pc, name); //要修改的人員不存在 if (pos == -1) { printf("要修改的人員不存在n"); return; } else { printf("請輸入修改後人員的名字:>"); scanf("%s", pc->data[pos].name); printf("請輸入修改後人員的年齡:>"); scanf("%d", &(pc->data[pos].age)); printf("請輸入修改後人員的性別:>"); scanf("%s", pc->data[pos].sex); printf("請輸入修改後人員的地址:>"); scanf("%s", pc->data[pos].addr); printf("請輸入修改後人員的電話:>"); scanf("%s", pc->data[pos].tele); printf("修改聯絡人員資訊成功n"); } } int cmp_Per_by_name(const void* e1, const void* e2) { return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name); } void SortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_Per_by_name); PrintContact(pc); } void ClearContact(Contact* pc) { assert(pc); InitContact(pc); printf("清空成功n"); }
#pragma once //型別的定義、通訊錄中要放1000個人的資訊, //每個人的資訊要包括名字、年齡、性別、電話、地址等, //所以要定義成一個結構體,而該結構體要在兩個原始檔中使用, //所以最好定義在標頭檔案中,這樣只需要包含一下標頭檔案就可以頻繁的使用了 //標頭檔案的包含 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<assert.h> //定義結構體型別 #define MAX_NAME 20 #define MAX_SEX 10 #define MAX_TELE 12 #define MAX_ADDR 30 #define MAX 1000 typedef struct PeoInfo { //char name[20]; //直接寫成固定值就寫死了,不方便後期的修改, //所以使用#define 來定義一個常數,後期直接改變#define中的內容即可。 char name[MAX_NAME]; char sex[MAX_SEX]; int age; char tele[MAX_TELE]; char addr[MAX_ADDR]; }PeoInfo;//使用typedef對結構體型別重新命名為:PeoInfo //結構體巢狀 //通訊錄 typedef struct Contact//重新命名 { PeoInfo data[MAX];//存放新增進去的聯絡人的資訊 int sz;//記錄當前通訊錄中有效資訊的個數 }Contact; //初始化通訊錄 void InitContact(Contact* pc); //增加聯絡人 void AddContact(Contact* pc); //列印資訊 void PrintContact(const Contact* pc); //刪除聯絡人資訊 void DelContact(Contact* pc); //查詢聯絡人資訊 void SearchContact(const Contact* pc); //修改指定聯絡人的資訊 void ModifyContact(Contact* pc); //排序聯絡人的資訊 void SortContact(Contact* pc); //清空所有聯絡人的資訊 void ClearContact(Contact* pc);
以上就是C語言實現靜態版通訊錄的範例程式碼的詳細內容,更多關於C語言靜態通訊錄的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45