數據結構項目實戰——通訊錄

c語言通訊錄

  • 前言
  • 一、基于動態順序表實現通訊錄
    • 1 功能要求
    • 2 代碼實現
  • 二、具體代碼實現
    • 需要使用的頭文件及宏定義
    • 通訊錄所需要的結構體
    • 通訊錄的初始化函數
    • 通訊錄的添加函數
    • 通訊錄的刪除函數
      • 比較函數
      • 主要函數
    • 通訊錄的查找函數
    • 通訊錄的修改函數
    • 通訊錄的排序函數
    • 通訊錄的打印函數
    • 內存返回函數
    • 數據保存函數
    • 枚舉函數
    • 菜單函數
  • 三、通訊錄完整代碼實現
    • contact.h
    • contact.c
    • test.c


前言

C語言通訊錄是一個使用C語言編寫的簡單程序,用于存儲和管理聯系人信息。該程序允許用戶添加、刪除、查找和顯示通訊錄中的聯系人。每個聯系人通常包括姓名、電話號碼和電子郵件地址等基本信息。程序使用結構體來存儲聯系人信息,并使用數組或鏈表等數據結構來組織和管理通訊錄。通過命令行界面與用戶進行交互,用戶可以通過輸入命令來執行相應的操作。C語言通訊錄程序可以用于個人或小型組織的信息管理,提高聯系人信息的管理效率。


一、基于動態順序表實現通訊錄

C語言基礎要求:結構體、動態內存管理、順序表、文件操作

1 功能要求

  1. 至少能夠存儲100個人的通訊信息
  2. 能夠保存用戶信息:名字、性別、年齡、電話、地址等
  3. 增加聯系人信息
  4. 刪除指定聯系人
  5. 查找制定聯系人
  6. 修改指定聯系人
  7. 顯示聯系人信息

2 代碼實現

【思考1】?靜態順序表和動態順序表分別如何實現
【思考2】如何保證程序結束后,歷史通訊錄信息不會丟失

二、具體代碼實現

需要使用的頭文件及宏定義

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>//使用斷言所需的頭文件
#define _CRT_SECURE_NO_WARNINGS 1 //VS所需要使用的,關于代碼安全性的問題
#define Name_max 20 // 姓名 年齡 性別 電話 地址
#define Sex_max 20
#define Tele_max 20
#define Addr_max 20
#define People_max 100
#define Move_people 3

通訊錄所需要的結構體

typedef struct contact
{char name[Name_max];char sex[Sex_max];char addr[Addr_max];int tele[Tele_max];int age;
}contact;
//靜態
/*typedef struct people
{contact data[People_max];int count;
}people;*/
typedef struct people//動態
{contact* data;int count;int capity;
}people;

通訊錄的初始化函數

//void Initcontact(people* pc);//初始化函數
int Initcontact(people* pc);//動態初始化函數
/*void Initcontact(people* pc)靜態
{pc->count = 0;memset(pc->data, 0, People_max);//
}*/
//動態
int Initcontact(people* pc)//#define Name_max 20 // 姓名 年齡 性別 電話 地址
//#define Sex_max 20
//#define Tele_max 20
//#define Addr_max 20
//#define People_max 100
//#define Move_people 3
{pc->capity = Move_people;//將通訊錄的容量設置成第一次的最大容量pc->count = 0;//通訊錄里的人是0人pc->data = calloc(pc->capity, sizeof(contact));//開辟空間并將數據初始化為0if (pc->data == NULL)//開辟空間失敗會報錯{printf("%s", strerror(errno));//或者使用perror("pc->data");return 1;}//讀取函數FILE* pt = fopen("test.txt", "rb");//以二進制可讀打開文件if (pt == NULL)//沒有文件會報錯{perror("FileRead: ");}contact tep = { 0 };//結構體tepwhile (fread(&tep, sizeof(contact), 1, pt))//從文件中讀取二進制結構體數據存放到tep中{if (pc->count == pc->capity)//讀取數據超過容量,擴容{contact* ptr = (contact*)realloc(pc->data, (pc->capity + 2) * sizeof(contact));if (ptr == NULL){printf("Addcontact: %s\n", strerror(errno));printf("增容失敗");}else{printf("增容成功");pc->capity += 2;pc->data = ptr;}}pc->data[pc->count] = tep;pc->count++;}fclose(pt);//關閉文件pt = NULL;return 0;
}

通訊錄的初始化函數是構建整個通訊錄系統的基石,它負責在程序啟動時創建和配置通訊錄的基本結構和功能。這個函數的任務繁重且關鍵,因為它不僅要確保通訊錄能夠正常運作,還要為后續的數據添加、修改、刪除等操作提供堅實的基礎。

初始化函數首先會創建一個空的通訊錄數據結構,這個結構通常是一個列表、數組或更復雜的數據結構,用于存儲聯系人信息。每個聯系人信息可能包括姓名、電話號碼、電子郵件地址等字段。接下來,函數會設置一些基本的參數,比如通訊錄的最大容量、默認的排序方式等。

在創建了基本的數據結構之后,初始化函數還會進行一些必要的配置工作。例如,它可能會加載一些預設的聯系人信息,或者從外部文件、數據庫中導入已有的數據。這些配置操作確保了通訊錄在啟動時就包含了必要的信息,用戶無需手動添加。

除了創建和配置數據結構,初始化函數還會初始化一些與用戶界面相關的元素。例如,它可能會設置通訊錄界面的布局、樣式和交互邏輯,確保用戶能夠方便地查看和編輯聯系人信息。

最后,初始化函數會進行一些錯誤處理和優化工作。它會檢查數據結構的完整性和一致性,確保沒有錯誤或不一致的數據存在。同時,它還會進行一些性能優化,比如對數據結構進行預分配、使用緩存等,以提高通訊錄的響應速度和穩定性。

總的來說,通訊錄的初始化函數是一個綜合性的函數,它負責創建和配置通訊錄的基本結構和功能,為后續的操作提供堅實的基礎。通過精心設計和實現初始化函數,可以確保通訊錄系統的穩定性和可靠性,為用戶提供良好的使用體驗。

通訊錄的添加函數

void Addcontact(people* pc);//添加函數
void Addcontact(people* pc)
{/*if (pc->count == People_max)靜態{printf("數據已滿");return;}*/if (pc->count == pc->capity)//增容{contact* ptr = (contact*)realloc(pc->data, (pc->capity + 2) * sizeof(contact));if (ptr == NULL){printf("Addcontact: %s\n", strerror(errno));printf("增容失敗");}else{printf("增容成功");pc->capity += 2;pc->data = ptr;}}else{printf("請輸入名字:>");scanf("%s", pc->data[pc->count].name);printf("請輸入年齡:>");scanf("%d", &pc->data[pc->count].age);//注意:年齡和其他的不一樣,要有取地址符,因為其他的是數組,數組的名字代表首元素的地址,可以不需要取地址符,而年齡不行printf("請輸入性別:>");scanf("%s", pc->data[pc->count].sex);printf("請輸入電話:>");scanf("%s", pc->data[pc->count].tele);printf("請輸入地址:>");scanf("%s", pc->data[pc->count].addr);pc->count++;printf("添加成功\n");}
}

通訊錄添加函數是手機應用中不可或缺的一部分,它為用戶提供了便捷的聯系人管理方式。當用戶想要添加新的聯系人時,這個功能就發揮了它的作用。

一個好的添加函數應該簡單、直觀,讓用戶能夠輕松完成操作。除了基本的聯系人信息外,通訊錄添加函數還可以提供一些高級功能。這些功能可以進一步提升用戶的體驗,讓他們能夠更個性化地管理自己的通訊錄。同時,這些功能也應該易于使用,不會給用戶帶來額外的負擔。

在實現通訊錄添加函數時,我們還需要考慮到數據的安全性和完整性。用戶的通訊錄信息是非常敏感的,因此在添加新聯系人時,我們需要確保這些信息能夠安全地存儲和傳輸。此外,我們還需要對數據進行驗證,確保添加的聯系人信息是準確和完整的。

在實際應用中,通訊錄添加函數通常會與其他功能相結合,如搜索功能、聯系人詳情頁面等。這些功能可以為用戶提供更全面的通訊錄管理體驗,讓他們能夠更方便地查找、編輯和刪除聯系人。

通訊錄的刪除函數

void Delectcontact(people* pc);//刪除函數

比較函數

static int Findnum(people* pc, char name[])//static 放在函數前面表示只在這個文件下使用的函數,別的文件使用不了,具體的可以看下面,因為這個函數我是放在contact.c中使用的,可以結合下面具體的代碼來看
{int i = 0;for (i = 0; i < pc->count; i++){if (strcmp(pc->data[i].name, name) == 0)//字符串比較函數,主要是用來判斷兩個函數是否相等{return i;}}return -1;
}

主要函數

void Delectcontact(people* pc)
{char name[Name_max] = { 0 };if (pc->count == 0){printf("無需刪除");return;}printf("輸入要刪除的姓名");scanf("%s", name);int pos = Findnum(pc, name);//見上面比較函數if (pos == -1){printf("無刪除數據");return;}int i = 0;for (i = pos; i < pc->count - 1; i++){pc->data[i] = pc->data[i + 1];}pc->count--;printf("刪除成功");
}

C語言通訊錄的刪除函數通常涉及以下步驟:

  1. 接收輸入:首先,用戶需要輸入要刪除的聯系人的信息,如姓名或ID。
  2. 遍歷通訊錄:然后,程序會遍歷通訊錄中的每個聯系人,查找與輸入信息匹配的聯系人。
  3. 刪除聯系人:一旦找到匹配的聯系人,程序會從通訊錄中刪除該聯系人。這通常是通過移動其他聯系人來填補刪除的聯系人的位置,或者通過減小通訊錄的大小來實現。
  4. 更新通訊錄:刪除操作完成后,程序需要更新通訊錄,以確保數據的準確性。
  5. 返回結果:最后,程序會返回一個消息,告知用戶刪除操作是否成功。

總的來說,C語言通訊錄的刪除函數通過接收用戶輸入,遍歷通訊錄,刪除匹配的聯系人,更新通訊錄,并返回結果,實現了對通訊錄中聯系人的刪除操作。

通訊錄的查找函數

void Searchcontact(people* pc);//查找函數
void Searchcontact(people* pc)
{char name[Name_max] = { 0 };if (pc->count == 0){printf("沒有數據");return;}printf("輸入要查找的姓名");scanf("%s", name);int pos = Findnum(pc, name);if (pos == -1){printf("無查找的人");return;}else{printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "姓名", "年齡", "性別", "電話", "地址");//打印數據printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}
}

通訊錄的查找函數是手機或電腦等通訊設備中不可或缺的一部分。它的主要作用是根據用戶提供的關鍵詞或條件,快速定位到通訊錄中的特定聯系人。在這個信息時代,人們的社交圈不斷擴大,通訊錄中的聯系人數量也隨之增長,因此,一個高效、準確的查找函數顯得尤為重要。

在設計通訊錄查找函數時,需要考慮到多種因素。首先是查找速度。當用戶輸入關鍵詞時,函數應該能夠迅速篩選出符合條件的聯系人,避免用戶長時間等待。其次是查找準確性。函數需要確保篩選出的聯系人確實符合用戶輸入的關鍵詞或條件,避免出現誤判或遺漏。

為了實現這些目標,開發者通常會采用一些先進的技術手段。例如,利用數據庫索引技術,將通訊錄中的聯系人信息按照一定的規則進行分類和排序,從而提高查找速度。同時,還會采用智能匹配算法,對用戶輸入的關鍵詞進行語義分析和處理,以提高查找準確性。

除了技術手段外,通訊錄查找函數的設計還需要考慮到用戶體驗。例如,函數應該提供多種查找方式,如按姓名、按電話號碼、按郵箱等,以滿足用戶的不同需求。同時,還應該提供模糊查找功能,允許用戶輸入不完整的關鍵詞或拼音等,以提高查找的靈活性。

綜上所述,查找函數很重要,本文將以關鍵詞為基礎,展現一下簡單的查找函數應該怎么來寫

通訊錄的修改函數

void Modifycontact(people* pc);//修改函數
void Modifycontact(people* pc)
{char name[Name_max] = { 0 };if (pc->count == 0){printf("無需修改");return;}printf("輸入要修改的姓名");scanf("%s", name);int pos = Findnum(pc, name);if (pos == -1){printf("無修改數據");return;}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].tele);printf("請輸入地址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}

通訊錄的修改函數是通訊錄管理系統中的一個核心功能,它允許用戶根據需要對已存儲的聯系人信息進行更新和修正。在實際應用中,這個函數通常需要處理各種可能的異常情況,比如聯系人信息不存在、輸入數據格式錯誤等。

一個典型的修改函數實現可能包括以下幾個步驟:

首先,函數會接收用戶輸入的新聯系人信息,這通常包括姓名、電話號碼、電子郵件地址等字段。然后,函數會檢查輸入的數據是否滿足格式要求,比如電話號碼是否符合常見的格式,電子郵件地址是否有效等。如果輸入數據不符合要求,函數會返回錯誤信息,提示用戶重新輸入。

接下來,函數會根據用戶提供的唯一標識符(如聯系人ID或姓名)在通訊錄數據庫中查找對應的聯系人記錄。如果找不到匹配的記錄,函數會返回錯誤信息,告知用戶聯系人不存在。

如果找到了匹配的記錄,函數會進一步比較新舊信息,確定哪些字段發生了變化。然后,它會更新數據庫中的聯系人記錄,將舊的信息替換為新的信息。在這個過程中,函數還會檢查是否有必要的數據丟失或更改,如果有,它也會進行相應的處理。

最后,函數會返回一個確認信息,告知用戶聯系人信息已成功更新。同時,它還會提醒用戶,如果需要進一步的操作或有其他問題,可以通過相應的接口或聯系方式與系統管理員聯系。

本文將以c語言學習階段常用的形式來展示

通訊錄的排序函數

void Qsortcontact(people* pc);//排序函數
int cmp_by_name(const void* e1, const void* e2)//按姓名來排
{return strcmp(((contact*)e1)->name, ((contact*)e2)->name);
}
int cmp_by_sex(const void* e1, const void* e2)//按性別來排
{return strcmp(((contact*)e1)->sex, ((contact*)e2)->sex);
}
int cmp_by_tele(const void* e1, const void* e2)//按電話來排
{return strcmp(((contact*)e1)->tele, ((contact*)e2)->tele);
}
int cmp_by_addr(const void* e1, const void* e2)//按地址來排
{return strcmp(((contact*)e1)->addr, ((contact*)e2)->addr);
}
int cmp_by_age(const void* e1, const void* e2)//按年齡來排
{return _stricmp(((contact*)e1)->age, ((contact*)e2)->age);
}
void Qsortcontact(people* pc)//排序函數
{char name[Name_max] = { 0 };printf("按照什么排序> \n");scanf("%s", name);if (strcmp(name, "姓名") == 0)//本文使用qsort函數來進行排序,qsort函數排序的本質是快速排序,想要了解qsort函數可以去看我之前的文章{qsort(pc->data, pc->count, sizeof(contact),cmp_by_name);}if (strcmp(name, "年齡") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_age);}if (strcmp(name, "性別") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_sex);}if (strcmp(name, "電話") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_tele);}if (strcmp(name, "地址") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_addr);}printf("排序完成");
}

c語言從入門到實戰——回調函數與qsort的講解和模擬實現
這篇文章寫了我對qsort函數的講解

通訊錄的排序函數是手機或電腦中常用的一個功能,它根據特定的規則將聯系人列表進行排序,使用戶能夠快速找到并聯系到需要的人。然而,這個看似簡單的功能背后,卻蘊含了多種排序算法和邏輯思考。

首先,通訊錄的排序可以根據不同的標準進行,比如姓名、電話號碼、最后聯系時間等。這就涉及到了選擇排序算法的問題。對于姓名排序,我們通常會采用字典序,也就是按照字母表順序進行排序。而對于電話號碼排序,則需要考慮到數字的特殊性,可能采用數值排序算法更為合適。最后聯系時間排序則需要一個時間戳來記錄每次聯系的時間,然后按照時間先后進行排序。

其次,通訊錄的排序還需要考慮到用戶的個性化需求。有些用戶可能更習慣于按照姓名的拼音首字母進行排序,而有些用戶則可能更喜歡按照電話號碼的區號進行排序。因此,通訊錄的排序函數需要支持用戶自定義排序規則,以滿足不同用戶的需求。

此外,通訊錄的排序還需要考慮到性能問題。當聯系人數量龐大時,如果采用簡單的冒泡排序等低效算法,可能會導致排序時間過長,影響用戶體驗。因此,通訊錄的排序函數需要采用高效的排序算法,如快速排序、歸并排序等,以提高排序速度。

最后,通訊錄的排序函數還需要考慮到穩定性和易用性。穩定性是指排序過程中不會改變原有數據的順序,這對于保持通訊錄的原始結構非常重要。易用性則是指排序函數需要簡單易懂,方便用戶操作。

綜上所述,通訊錄的排序函數不僅僅是一個簡單的功能,它涉及到了多種排序算法、用戶個性化需求、性能優化以及穩定性和易用性等方面的考慮。只有在這些方面都做得足夠好,才能為用戶提供一個高效、方便、穩定的通訊錄排序體驗。

通訊錄的打印函數

void Printcontact(people* pc);//打印函數
void Printcontact(people* pc)
{int i = 0;//打印標題printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "姓名", "年齡", "性別", "電話", "地址");//打印數據for (i = 0; i < pc->count; i++){printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}

通訊錄的打印函數是許多應用程序中不可或缺的一部分,它負責將存儲在數據庫或內存中的聯系人信息以人類可讀的形式展示出來。這個函數的設計和實現,不僅關系到用戶界面的友好程度,還直接影響到程序的性能和效率。

在實現通訊錄的打印函數時,首先要考慮的是數據的來源和格式。通訊錄中的數據通常以結構化的方式存儲,比如每個聯系人可能包含姓名、電話號碼、電子郵件地址等字段。這些數據可以存儲在文件、數據庫或內存中,而打印函數則需要從這些源中讀取數據,并將其轉換為適合展示的格式。

其次,打印函數還需要考慮如何呈現聯系人信息。最簡單的方式是將所有聯系人的信息按照一定格式連續打印出來,例如按姓名排序或按添加時間排序。然而,在實際應用中,用戶可能希望根據不同的條件篩選聯系人,或者對聯系人信息進行分組和排序。這就需要打印函數支持靈活的查詢和排序功能。

此外,為了提高用戶體驗,打印函數還可以加入一些額外的功能。比如,可以為每個聯系人信息添加高亮或顏色編碼,以便用戶更容易地識別重要信息或區分不同類型的聯系人。還可以添加搜索功能,允許用戶快速找到特定的聯系人。

在實現這些功能時,需要注意程序的性能和效率。如果通訊錄中包含大量的聯系人信息,打印函數可能會消耗大量的計算資源和時間。因此,需要采用一些優化措施,比如使用高效的數據結構和算法,或者將部分計算任務異步處理,以避免阻塞用戶界面。

內存返回函數

void Quitcoontact(people* pc);//內存返回函數
void Quitcoontact(people* pc)
{free(pc->data);pc->data = NULL;
}

內存返回函數是編程中常用的一個概念,它指的是一個函數在執行完畢后,將其所使用的內存空間返還給操作系統或其他需要使用的程序。在多數編程語言中,內存管理是一個重要且復雜的任務,因為它直接關系到程序的性能和穩定性。

當我們創建一個變量或對象時,系統會在內存中為其分配空間。隨著程序的執行,這些內存塊可能會被頻繁地創建和銷毀。如果沒有有效的內存管理機制,這些不再使用的內存塊會占用系統資源,導致內存泄漏和程序崩潰。

內存返回函數就是在這樣的背景下誕生的。它的作用是在函數執行完畢后,自動釋放函數內部創建的所有局部變量和動態分配的內存空間。這樣,操作系統或其他程序就可以重新利用這些內存空間,提高了內存的使用效率。

在C語言中,內存返回通常是通過手動調用free()函數來實現的。而在一些高級語言如Python和Java中,內存管理則是自動進行的,程序員無需手動調用內存返回函數。

然而,即使在這些高級語言中,內存管理仍然是一個需要注意的問題。因為雖然語言本身提供了自動內存管理功能,但如果程序員不正確地使用數據結構和算法,仍然可能導致內存泄漏或其他問題。

因此,無論在哪種編程語言中,程序員都應該對內存管理有一個清晰的認識,并時刻關注程序的內存使用情況。只有這樣,才能編寫出高效、穩定、可靠的程序。

總之,內存返回函數是編程中不可或缺的一部分。它幫助程序員有效地管理內存資源,防止內存泄漏和程序崩潰。同時,程序員也應該在編程過程中時刻關注內存管理問題,確保程序的性能和穩定性。

數據保存函數

void Filewrite(people* pc);//數據保存函數
void Filewrite(people* pc)
{FILE* pf = fopen("test.txt", "wb");if (pf == NULL){perror("Filewrite: ");return;}int i = 0; /*for (i = 0; i < pc->count; i++){fwrite(pc->data + i, sizeof(contact), 1, pf);}*/fwrite(pc->data, sizeof(contact), pc->count, pf);fclose(pf);pf = NULL;
}

數據保存函數是信息系統中至關重要的組成部分,它負責將處理后的數據以安全、有效的方式存儲在計算機系統的硬盤或其他持久化存儲介質中。在軟件開發過程中,數據保存函數的設計和實現直接關系到數據的安全性和完整性,因此,編寫一個穩健、高效的數據保存函數是每一個程序員都必須認真對待的任務。

編寫數據保存函數時,我們首先要考慮的是數據的格式。不同的數據格式有不同的存儲效率和讀取速度,同時還會影響到數據在不同系統之間的兼容性。例如,對于大量結構化數據,我們通常會選擇使用關系型數據庫來存儲,而對于非結構化數據或者需要高效讀寫的場景,可能會選擇NoSQL數據庫或者鍵值存儲等方案。

在確定了數據格式之后,我們還需要考慮數據的安全性問題。這包括數據的加密、備份和恢復等方面。為了防止數據被非法訪問或篡改,我們通常會對敏感數據進行加密處理,確保即使數據被竊取也無法被輕易解密。同時,為了防止數據丟失,我們還會定期備份數據,并測試備份數據的恢復能力,確保在數據出現問題時能夠迅速恢復。

除了安全性和完整性之外,數據保存函數還需要考慮性能問題。在大數據環境下,數據的寫入和讀取操作可能會變得非常頻繁,如果數據保存函數的設計不合理,可能會成為系統的瓶頸。因此,我們需要在設計數據保存函數時充分考慮其性能,可能需要采用異步處理、批量寫入等技術來提高性能。

最后,數據保存函數還需要考慮錯誤處理和日志記錄。在數據保存過程中,可能會出現各種錯誤,如磁盤空間不足、數據庫連接失敗等。我們需要為這些情況編寫相應的錯誤處理代碼,確保在出現錯誤時能夠及時處理并記錄日志,方便后續的故障排查和問題定位。

綜上所述,數據保存函數的設計和實現是一個復雜而重要的任務,需要綜合考慮數據格式、安全性、性能和錯誤處理等多個方面。只有在這些方面都做得足夠好,才能確保數據的安全性和完整性,為信息系統的穩定運行提供堅實的保障。

枚舉函數

enum num//通過使用枚舉函數來實現函數的控制
{go,add,delect,search,modify,sort,show
};

枚舉函數,作為一種編程中的重要工具,它的作用在于列出特定類型對象的所有可能值。在編程領域,枚舉函數不僅提高了代碼的可讀性和可維護性,還有助于減少錯誤和增強代碼的安全性。

在日常的軟件開發中,枚舉函數常常被用于處理那些具有固定、有限且明確值集合的數據類型。比如,一個表示星期幾的數據類型,其值集合就是“星期一”、“星期二”一直到“星期日”。通過使用枚舉函數,我們可以確保程序在處理這些數據時,不會出現意外的、不在預期范圍內的值。

此外,枚舉函數還能提高代碼的健壯性。在復雜的程序中,有時需要對某種類型的數據進行多種不同的處理。如果這些數據的值沒有明確的界限或定義,那么在處理過程中就很容易出現錯誤。通過使用枚舉函數,我們可以清楚地定義這些數據的取值范圍,并在代碼中對每一種取值進行相應的處理,從而有效地避免這類錯誤的發生。

當然,枚舉函數并不是萬能的。在某些情況下,使用枚舉函數可能會導致代碼變得過于復雜或難以理解。比如,當需要表示的數據類型具有大量的可能值時,如果全部使用枚舉函數進行定義,那么可能會導致代碼變得冗長且難以維護。在這種情況下,可能需要考慮使用其他的數據結構或方法來進行處理。

總的來說,枚舉函數是一種非常有用的編程工具,它可以幫助我們更好地處理和管理具有固定、有限且明確值集合的數據類型。但是,在使用枚舉函數時,我們也需要根據具體的情況進行考慮和選擇,以確保代碼的質量和效率。

菜單函數

void menu()
{printf("************************************\n");printf("*****1.增添         2.刪除**********\n");printf("************************************\n");printf("*****3.查找         4.修改**********\n");printf("************************************\n");printf("*****5.排序         6.顯示**********\n");printf("*************0.退出*****************\n");
}

三、通訊錄完整代碼實現

contact.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define _CRT_SECURE_NO_WARNINGS 1
#define Name_max 20 // 姓名 年齡 性別 電話 地址
#define Sex_max 20
#define Tele_max 20
#define Addr_max 20
#define People_max 100
#define Move_people 3
typedef struct contact
{char name[Name_max];char sex[Sex_max];char addr[Addr_max];int tele[Tele_max];int age;
}contact;
//靜態
/*typedef struct people
{contact data[People_max];int count;
}people;*/
typedef struct people
{contact* data;int count;int capity;
}people;
//void Initcontact(people* pc);//初始化函數
int Initcontact(people* pc);//動態初始化函數
void Addcontact(people* pc);//添加函數
void Delectcontact(people* pc);//刪除函數
void Searchcontact(people* pc);//查找函數
void Modifycontact(people* pc);//修改函數
void Qsortcontact(people* pc);//排序函數
void Printcontact(people* pc);//打印函數
void Quitcoontact(people* pc);//內存返回函數
void Filewrite(people* pc);//數據保存函數

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
/*void Initcontact(people* pc)靜態
{pc->count = 0;memset(pc->data, 0, People_max);
}*/
//動態
int Initcontact(people* pc)
{pc->capity = Move_people;pc->count = 0;pc->data = calloc(pc->capity, sizeof(contact));if (pc->data == NULL){printf("%s", strerror(errno));return 1;}//讀取函數FILE* pt = fopen("test.txt", "rb");if (pt == NULL){perror("FileRead: ");}contact tep = { 0 };while (fread(&tep, sizeof(contact), 1, pt)){if (pc->count == pc->capity){contact* ptr = (contact*)realloc(pc->data, (pc->capity + 2) * sizeof(contact));if (ptr == NULL){printf("Addcontact: %s\n", strerror(errno));printf("增容失敗");}else{printf("增容成功");pc->capity += 2;pc->data = ptr;}}pc->data[pc->count] = tep;pc->count++;}fclose(pt);pt = NULL;return 0;
}
void Addcontact(people* pc)
{/*if (pc->count == People_max)靜態{printf("數據已滿");return;}*/if (pc->count == pc->capity){contact* ptr = (contact*)realloc(pc->data, (pc->capity + 2) * sizeof(contact));if (ptr == NULL){printf("Addcontact: %s\n", strerror(errno));printf("增容失敗");}else{printf("增容成功");pc->capity += 2;pc->data = ptr;}}else{printf("請輸入名字:>");scanf("%s", pc->data[pc->count].name);printf("請輸入年齡:>");scanf("%d", &pc->data[pc->count].age);printf("請輸入性別:>");scanf("%s", pc->data[pc->count].sex);printf("請輸入電話:>");scanf("%s", pc->data[pc->count].tele);printf("請輸入地址:>");scanf("%s", pc->data[pc->count].addr);pc->count++;printf("添加成功\n");}
}
static int Findnum(people* pc, char name[])
{int i = 0;for (i = 0; i < pc->count; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}
void Delectcontact(people* pc)
{char name[Name_max] = { 0 };if (pc->count == 0){printf("無需刪除");return;}printf("輸入要刪除的姓名");scanf("%s", name);int pos = Findnum(pc, name);if (pos == -1){printf("無刪除數據");return;}int i = 0;for (i = pos; i < pc->count - 1; i++){pc->data[i] = pc->data[i + 1];}pc->count--;printf("刪除成功");
}
void Searchcontact(people* pc)
{char name[Name_max] = { 0 };if (pc->count == 0){printf("沒有數據");return;}printf("輸入要查找的姓名");scanf("%s", name);int pos = Findnum(pc, name);if (pos == -1){printf("無查找的人");return;}else{printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "姓名", "年齡", "性別", "電話", "地址");//打印數據printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}
}
void Modifycontact(people* pc)
{char name[Name_max] = { 0 };if (pc->count == 0){printf("無需修改");return;}printf("輸入要修改的姓名");scanf("%s", name);int pos = Findnum(pc, name);if (pos == -1){printf("無修改數據");return;}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].tele);printf("請輸入地址:>");scanf("%s", pc->data[pos].addr);printf("修改成功\n");
}
int cmp_by_name(const void* e1, const void* e2)
{return strcmp(((contact*)e1)->name, ((contact*)e2)->name);
}
int cmp_by_sex(const void* e1, const void* e2)
{return strcmp(((contact*)e1)->sex, ((contact*)e2)->sex);
}
int cmp_by_tele(const void* e1, const void* e2)
{return strcmp(((contact*)e1)->tele, ((contact*)e2)->tele);
}
int cmp_by_addr(const void* e1, const void* e2)
{return strcmp(((contact*)e1)->addr, ((contact*)e2)->addr);
}
int cmp_by_age(const void* e1, const void* e2)
{return _stricmp(((contact*)e1)->age, ((contact*)e2)->age);
}
void Qsortcontact(people* pc)
{char name[Name_max] = { 0 };printf("按照什么排序> \n");scanf("%s", name);if (strcmp(name, "姓名") == 0){qsort(pc->data, pc->count, sizeof(contact),cmp_by_name);}if (strcmp(name, "年齡") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_age);}if (strcmp(name, "性別") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_sex);}if (strcmp(name, "電話") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_tele);}if (strcmp(name, "地址") == 0){qsort(pc->data, pc->count, sizeof(contact), cmp_by_addr);}printf("排序完成");
}
void Printcontact(people* pc)
{int i = 0;//打印標題printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "姓名", "年齡", "性別", "電話", "地址");//打印數據for (i = 0; i < pc->count; i++){printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}
void Quitcoontact(people* pc)
{free(pc->data);pc->data = NULL;
}
void Filewrite(people* pc)
{FILE* pf = fopen("test.txt", "wb");if (pf == NULL){perror("Filewrite: ");return;}int i = 0; /*for (i = 0; i < pc->count; i++){fwrite(pc->data + i, sizeof(contact), 1, pf);}*/fwrite(pc->data, sizeof(contact), pc->count, pf);fclose(pf);pf = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
enum num
{go,add,delect,search,modify,sort,show
};
void menu()
{printf("************************************\n");printf("*****1.增添         2.刪除**********\n");printf("************************************\n");printf("*****3.查找         4.修改**********\n");printf("************************************\n");printf("*****5.排序         6.顯示**********\n");printf("*************0.退出*****************\n");
}
int main()
{int input = 0;people num;//定義結構體numInitcontact(&num);//結構體初始化do{menu();printf("請輸入>");scanf("%d", &input);switch (input){case add:Addcontact(&num); break;case delect:Delectcontact(&num); break;case search:Searchcontact(&num); break;case modify:Modifycontact(&num); break;case sort:Qsortcontact(&num); break;case show:Printcontact(&num); break;case go: Filewrite(&num); Quitcoontact(&num); break;default:printf("重新輸入"); break;}} while(input);return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714976.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714976.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714976.shtml

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

相關文章

項目組合研究的問題

接著上篇項目集&#xff0c;再查了查項目組合研究的問題&#xff0c;項目組合主要關注組織如何有效地管理多個項目以實現戰略目標&#xff0c;以及在資源有限的情況下最大化整體價值。以下是項目組合研究中常遇到的關鍵問題&#xff1a; 戰略一致性&#xff1a; 如何確保項目組…

Salesforce CPQ - 02 - Quote Price

最近又有客戶來咨詢學習Salesforce CPQ&#xff0c;所以本人總結了下近幾年CPQ培訓的一些實際案例拿出來分享給大家&#xff1b; 再次介紹下本人是一位Salesforce十多年的從業者。 先來介紹下Salesforce的價格體系&#xff0c;再介紹下各個Product Price是如何配置及使用的&a…

測試需求平臺8-Arco組件實現產品增改需求

?此系列為整理分享已完結入門搭建《TPM提測平臺》系列的迭代版&#xff0c;擁抱Vue3.0將前端框架替換成字節最新開源的arco.design&#xff0c;其中約60%重構和20%新增內容&#xff0c;定位為從 0-1手把手實現簡單的測試平臺開發教程&#xff0c;內容將囊括基礎、擴展和實戰&a…

在什么時候企業檔案才會發生調整

檔案在企業中通常會調整在以下幾個時刻&#xff1a; 1. 入職時&#xff1a;員工入職時&#xff0c;企業會要求員工提供個人檔案&#xff0c;包括身份證件、學歷證明、工作經歷等相關文件。 2. 離職時&#xff1a;員工離職時&#xff0c;企業會整理員工的離職檔案&#xff0c;包…

題目 1619: 藍橋杯算法訓練VIP-字串統計

題目描述: 給定一個長度為n的字符串S&#xff0c;還有一個數字L&#xff0c;統計長度大于等于L的出現次數最多的子串&#xff08;不同的出現可以相交&#xff09;&#xff0c;如果有多個&#xff0c;輸出最長的&#xff0c;如果仍然有多個&#xff0c;輸出第一次出現最早的。 …

JDBC

概念&#xff1a; JDBC 就是使用Java語言操作關系型數據庫的一套API 全稱&#xff1a;( Java DataBase Connectivity ) Java 數據庫連接。 JDBC的本質&#xff1a; 官方&#xff08;sun公司&#xff09;定義的一套操作所有關系型數據庫的規則&#xff0c;即 接口各個數據庫廠…

ChatGPT-4.0:學術研究論文檢索的新篇章

ChatGPT-4.0&#xff1a;學術研究論文檢索的新篇章 在當代學術研究的廣闊天地&#xff0c;知識的追求始終在不斷進化&#xff0c;緊密擁抱能夠加強研究者探索和吸收信息能力的創新技術。ChatGPT-4.0的出現代表了學術探索的一次質的飛躍&#xff0c;為研究人員查詢學術論文提供…

Filebeat將csv導入es嘗試

一、安裝 在docker中安裝部署ELKfilebeat 二、主要配置 - type: log # Change to true to enable this input configuration. enabled: true # Paths that should be crawled and fetched. Glob based paths. paths: - /home/centos/pip_v2.csv #源路徑 #…

Sqli-labs靶場第15關詳解[Sqli-labs-less-15]

Sqli-labs-Less-15 #自動化注入-SQLmap工具注入 SQLmap用戶手冊&#xff1a;文檔介紹 - sqlmap 用戶手冊 由于這題是post請求&#xff0c;所以先使用burp進行抓包&#xff0c;然后將數據包存入txt文件中打包 用-r 選擇目標txt文件 python sqlmap.py -r data.txt -current-db…

Visual Studio C++項目遠程斷點調試客戶現場程序方法

前言 程序開發一個很常見的場景&#xff0c;就是程序在自己本地部署調試明明一點問題都沒有&#xff0c;但是部署到客戶現場就問題百出&#xff0c;要調試起來還很困難&#xff0c;在自己本地也沒有條件復現&#xff0c;很多時候只能靠日志一點點排查和猜測&#xff0c;耗費大…

我在代碼隨想錄|寫代碼Day31 | 貪心算法總結篇 | 貪心終結一題

&#x1f525;博客介紹&#xff1a; 27dCnc &#x1f3a5;系列專欄&#xff1a; <<數據結構與算法>> << 算法入門>> << C項目>> &#x1f3a5; 當前專欄: << 算法入門>> 專題 : 數據結構幫助小白快速入門算法 &#x1f4…

window使用hyper安裝centos及docker、kubenet\k8s

window虛擬機安裝centos&#xff1a; windows系統下安裝linux&#xff08;centos7&#xff09;虛擬機詳細教程&#xff08;virtualbox環境&#xff09;_windows安裝linux虛擬機-CSDN博客 準備3臺機器&#xff1a; 172.29.34.250 172.29.37.174 172.29.39.106 安裝教程&…

關于定時器 setTimeout 可能會引發的內存泄露

前言 setTimeout 本身并不直接引發內存泄露&#xff0c;但如果使用不當&#xff0c;確實可以間接導致內存泄漏。以下是一些使用 setTimeout 可能導致內存泄漏的情況&#xff1a; 閉包引用&#xff1a; 在 setTimeout 的回調函數中&#xff0c;如果引用了外部變量&#xff08;形…

AJAX實例

AJAX - Asynchronous JavaScript and XML - 異步的JavaScript與XML&#xff0c;不是一門新技術&#xff0c;只是一個新的術語。&#xff08;老技術新玩法&#xff09; - 使用AJAX&#xff0c;網頁能夠將增量更新呈現在頁面上&#xff0c;而不需要刷新整個頁面。 - 雖然X代表…

力扣1892 頁面推薦Ⅱ

力扣1892&#xff0c;頁面推薦Ⅱ&#xff0c;為一個社交媒體網站實施一個頁面推薦系統。如果頁面被user_id的 至少一個朋友喜歡 &#xff0c;而 不被user_id喜歡 &#xff0c;你的系統將 推薦 一個頁面到user_id。 目錄 題目描述 解題思路 完整代碼 優化 題目描述 表&…

【C++】cout 的默認精度

cout 的默認精度為&#xff1a; 四舍五入保留六位有效數字輸出。例如 123.4567 應該輸出為 123.457&#xff0c;5432.10 應該輸出為 5432.1。 一、使用C語言輸出符合cout默認精度的數值 double weight; scanf("%lf",&weight);printf("%.6g",weight)…

FlinkSql hint之狀態生命周期 state_ttl

狀態生命周期hint FlinkSQL 的 state ttl&#xff08;Time-To-Live&#xff0c;生存時間&#xff09;是一個用于管理狀態數據生命周期的機制。在 Flink 流處理中&#xff0c;狀態是一個重要的概念&#xff0c;它允許跨時間窗口或事件時間處理的狀態化操作。然而&#xff0c;隨…

分治法(Divide and Conquer)

目錄 1.定義 2.例子 3.注意 1.定義 分治法&#xff08;Divide and Conquer&#xff09;是一種解決問題的算法設計策略&#xff0c;它將一個大問題分解成若干個規模較小且結構與原問題相似的子問題&#xff0c;然后遞歸地解決這些子問題&#xff0c;最后將子問題的解合并起來…

Dockerfile 語法教程

Dockerfile 語法教程 文章目錄 Dockerfile 語法教程Dockerfile 語法教程基礎概念Dockerfile 簡介鏡像、容器、倉庫的概念 Dockerfile 基本語法 Dockerfile 基本語法Dockerfile 的基本結構注釋的使用指令的格式指令的執行順序 Dockerfile 常用指令FROM 指令RUN 指令CMD 指令ENTR…

鴻蒙崗位需求突增!移動端、PC端、IoT到底該怎么選?

“2024年是原生鴻蒙的關鍵一年&#xff0c;我們要加快推進各類鴻蒙原生應用的開發&#xff0c;集中打贏技術底座和三方生態兩大最艱巨的戰斗。”這是余承東在新年信中表達的決心。 隨后在1月18日舉行的鴻蒙生態千帆啟航儀式上&#xff0c;華為宣布 HarmonyOS NEXT 鴻蒙星河版系…