C語言----實現動態通訊錄

2021-09-27 10:00:53


文章目錄

  • 前言
  • 一、建立檔案
  • 二、編寫函數
  • 三、偵錯執行
  • 四、成果展示
  • 五、程式碼彙總
  • 總結


前言

通訊錄是我們日常手機中常見的功能之一,綜合C語言中結構體,迴圈,條件語句,動態記憶體分配等等知識點,我們對手機通訊錄進行一個簡單的實現,下面我們開始講解!!!


準備工作:(利用C語言實現動態通訊錄)

所需知識:

①.函數呼叫,函數宏的定義及使用,庫函數對應的標頭檔案,函數宣告

②.迴圈語句,選擇語句( switch 和 if 語句 )的使用

③.指標,自定義型別的使用(結構體和列舉型別)

④.qsort函數的使用

⑤.動態記憶體分配函數(malloc函數和realloc函數)的使用

總結:該程式所需的知識比較全面,可以藉助本程式對所學C語言的知識進行一個較為全面的複習


在這裡我們採用的是多檔案的編寫方式,各個檔案分工明確,程式碼簡約可讀性高


一、建立檔案

1.建立一個標頭檔案用來編寫函數宣告,庫函數的標頭檔案,定義define宏,定義結構體的基本資訊,我們把這些程式碼都放在標頭檔案裡面方便我們另外兩個檔案呼叫,標頭檔案裡面的程式碼我們其他兩個 .c 檔案中都要用到,這樣的編寫方式使我們的程式碼更加簡約,增加可讀性。

2.在contact.c檔案中我們主要編寫的是通訊錄的功能函數

3.在test.c檔案中我們編寫的通訊錄的基本樣式,以及通過test.c這個檔案去串起來其他兩個檔案,實現通訊錄的功能



提示為了方便解析程式碼博主將程式碼進行了拆分,在文章的最後會給大家放上最終三個檔案的完整程式碼

二、需求分析+實際編寫

1.首先在我們的程式中先建立一個通訊錄,再利用它去實現功能

①.分析:我們知道通訊錄裡面會儲存一個人的多個資訊,比如:年齡,性別,電話等等,這些都是一個人的多個屬性,所以我們就可以把一個人的基本資訊封裝到一個結構體裡

具體程式碼如下:

struct PeoInfo//定義一個聯絡人基本資訊
{
	char name[namemax];
	int age;
	char sex[sexmax];
	char tel[telemax];
	char addr[addrmax];
};

我們看到在結構體裡面儲存一個人的五項基本資訊,由於兩個 .c 檔案都會用到此結構體的成員資訊,所以我們把這個結構體放在檔案中。我們注意到字串陣列括號裡面沒有寫具體的數位,而是用宏進行了代替,這樣的目的是方便以後對資料的修改,僅僅對宏修改即可,省去對程式的每一個涉及到該字串的資料進行修改。

該程式碼塊涉及到的宏:

#define namemax 20
#define sexmax 5
#define telemax 12
#define addrmax 30

我們看到如果需要修改字串陣列的容量,僅需要對宏後面的資料進行修改即可。

②.分析:我們已經定義了一個基本聯絡人的資訊,我們想一下,一個通訊錄是由多個聯絡人的基本資訊組成的,所以我們又可以把多個聯絡人的資訊(即結構體陣列),封裝到一個結構體中,此結構體代表的就是我們的所需要的通訊錄

具體程式碼如下:

struct contact
{
	struct PeoInfo* data;
	int sz ;//目前通訊錄有幾個
	int capacity;//通訊錄的總容量
};

我們在這裡定義了一個結構體用來存放多個聯絡人的資訊,在 contact 結構體裡我們存放了一個結構體指標運來存放 PeoInfo 結構體陣列的首地址,這裡結構體指標代表的就是多個通訊錄成員的資訊,sz變數用來記錄通訊錄的人數,capacity變數代表的是通訊錄的總容量。

2.通訊錄已經建立完成,接下來我們先編寫主函數,再對通訊錄進行初始化等一系列操作

我們先編寫一個選單函數,方便程式執行後根據選單選擇序號進行功能的實現

具體程式碼如下:

void menu()
{
	printf("**************************************\n");
	printf("*  1.新增聯絡人        2.刪除聯絡人    *\n");
	printf("*  3.查詢聯絡人        4.修改聯絡人    *\n");
	printf("*  5.展示通訊錄        6.按名字排序    *\n");
	printf("*               0.退出                *\n");
	printf("**************************************\n");
}

選單欄的樣式隨意設計即可。

接著我們定義一個列舉型別,把我們功能的名稱都寫入列舉型別中,注意這裡寫入時要注意順序,和我們規定的選單的功能編號一致,這樣可以保證輸入對應的序號實現對應的功能

enum Option
{
	EXIT,
	ADD,
	DEL,
	SERCH,
	MODIFY,
	SHOW,
	SORT
};

這裡的列舉型別從頭開始預設的初值是 0 每向下走一個型別遞增 1 ,數值順序對應我們的功能序號即可

最後我們編寫我們的主函數作為呼叫通訊錄功能的函數

具體程式碼如下:

#pragma warning(disable : 4996)
#include "contact.h"
void menu()
{
	printf("**************************************\n");
	printf("*  1.新增聯絡人        2.刪除聯絡人  *\n");
	printf("*  3.查詢聯絡人        4.修改聯絡人  *\n");
	printf("*  5.展示通訊錄        6.按名字排序  *\n");
	printf("*               0.退出               *\n");
	printf("**************************************\n");
}
enum OPTION
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};
int main()
{
	int input = 0;
	struct contact con;//建立一個通訊錄con變數
	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 SHOW:
			showcontact(&con);
			break;
		case SORT:
			sortcontact(&con);
			break;
		case EXIT:
			destorycontact(&con);
			printf("退出通訊錄\n");
			break;
		}
	} while (input);
	return 0;
}

我們在這裡定義了一個 input 輸入變數,根據使用者的輸入去實現不同的功能。建立了一個結構體變數con,變數 con 代表的就是我們的剛剛設定好的通訊錄。定義一個 initcontact 函數對我們的通訊錄進行初始化(開闢空間)。進入迴圈,使用者輸入不同的資料實現不同的功能,case後面的列舉型別代表的就是對應的功能序號,在每一個功能下面都有一個功能函數去實現不同的功能,最後迴圈以輸入的input數值最後迴圈終止的條件,如果輸入的是 0 退出通訊錄,結束迴圈。

3.下面我們對通訊錄進行初始化以及功能函數的編寫

①.我們先對通訊錄進行初始化(即給通訊錄分配空間)

具體程式碼如下:

void initcontact(struct contact* pc)
{
	pc->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));//動態分配給data一塊記憶體
	pc->sz = 0;//初始化時通訊錄沒人
	pc->capacity = size;//假設一開始的通訊錄容量為3後面不夠用隨時增容
}
#define size 3

我們看到這裡的引數傳進來的是我們通訊錄變數的地址,這裡定義了一個 pc 指標去接收。我們首先給結構體中的date資料(date代表多組聯絡人)進行空間的開闢,我們假設通訊錄的通訊的總容量為 3 先開闢 3 個空間,這三個空間的型別都是結構體型別(struct PeoInfo型別),所以開闢空間的總大小,就是個數 x 封裝成員基本資訊的結構體大小。然後利用malloc函數進行空間 的開闢,因為malloc函數的返回值是void*型別(開闢空間的首地址),我們需要把開闢的這上空間強制轉換為我們所需要的結構體指標型別,再賦值給我們 pc 指標指向的 data 空間,這樣就完成了空間的開闢。又因為開始沒有新增聯絡人的時候,通訊錄是空的,所以這裡的 pc 指向的 sz 先把它賦值成 0 ,這裡 pc 指向的 capacity 代表通訊錄的總容量,我們先把它賦值成 3 之後空間不夠,再進行補充。

②.初始化完成後,我們開始實現我們的通訊錄的代號為 1 的功能即add(新增聯絡人)函數的編寫

具體程式碼如下:

void addcontact(struct contact* pc)
{
	//如果通訊錄滿了
	if (pc->sz == pc->capacity)
	{
		//增容
		struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += 2;
			printf("通訊錄增容成功\n");
		}
		else
		{
			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].tel);
	printf("請輸入新增聯絡人的地址>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
}

程式碼解析:我們看到這裡的引數傳進來的是我們通訊錄變數的地址,這裡定義了一個 pc 指標去接收。進入函數先行判斷通訊錄滿沒滿,如果沒滿直接進入到下面的 scanf 和 printf 語句中進行成員基本資訊的錄入,最後成員數sz+1。如果滿了判斷的條件就是目前通訊錄的 sz 個數等於我們的通訊錄的總容量數,這樣我們的通訊錄就已經存滿了。進入到 if 語句中對空間重新分配,這裡用到了realloc函數,在realloc函數中傳入兩個引數,一個是需要進行重新分配的空間,另一個是重新開闢的空間大小,這裡的空間我們兩個兩個的給通訊錄增加(避免一次開闢過多對空間造成浪費),我們看到這裡的空間在原本的通訊錄容量上capacity+2就是給我們的通訊錄總容量再開闢兩個空間,有了需要開闢的空間個數,我們用個數 x 封裝成員基本資訊的結構體大小得到的就是我們需要重新開闢的空間大小,.realloc函數開闢空間後返回的是void*(開闢空間的首地址),我們在這裡把它強轉為我們需要的結構體指標型別,賦值給我們的定義的結構體指標,這裡新建立一個指標,不直接賦值給 pc 就是為了防止開闢空間失敗,把pc指標置空了,導致pc指標中的資料就清空了,為了防止這樣的情況發生,我們先定義一箇中間變數存放開闢的空間,然後進入判斷如果這裡返回的是空指標(NULL),證明空間開闢失敗了,直接返回空就可以了。如果開闢的不是空指標(NULL),就把這塊開闢的空間賦值給儲存多組成員資訊的結構體指標,然後對應通訊錄的總容量 + 2,並列印一下告知空間開闢成功。

③.功能2:通訊錄的刪除操作(這裡用到了strcmp函數)--->C語言相關字串庫函數用法

具體程式碼如下:

void delcontact(struct contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通訊錄為空無法刪除\n");
		return;
	}
	char name[namemax] = { 0 };
	printf("請您輸入想要刪除的聯絡人姓名>");
	scanf("%s", name);
	int pos = Findname(name, pc);
	if (pos == -1)
	{
		printf("沒找到此聯絡人\n");
	}
	else
	{
		int j = 0;
		for (j = pos; j < pc->sz; j++)
		{
			pc->data[j] = pc->data[j + 1];//所有訊息都進行交換
		}
		pc->sz--;
		printf("該聯絡人刪除成功\n");
	}
}

因為我們需要查詢到對應的成員名字再進行刪除

所以我們在這裡還需要再編寫一個查詢名字的函數(該函數在後面的查詢聯絡人,更改聯絡人中都有用到,因為他們都是通過名字去查詢,再進行操作)

int Findname(char* name, struct contact* pc)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
		{
			return i;
		}
	}
	return -1;
}

我們先看刪除函數,我們先進行判斷通訊錄是不是為空,如果sz為0的情況下,這時候通訊是無法進行刪除操作(因為通訊錄中沒有聯絡人資訊),如果為空就直接返回空。如果通訊錄有聯絡人的資訊,我們就定義一個由使用者輸入的名字,我們用這個名字去進行查詢,查詢到了就進行刪除操作,沒有這個名字就直接返回空(即刪除操作失敗了)。在查詢的過程中我們就用到我們的查詢函數,我們看到查詢函數中的引數一個是使用者輸入的名字,一個是通訊錄現有的成員資訊,我們進行迴圈判斷,這裡用到了strcmp函數進行字串比較,如果相等就返回對應這個名字在結構體中的下標位置,如果沒有查詢到就返回-1。返回到刪除函數我們定義一個pos變數對返回值進行接收,然後再進行一次判斷,如果是-1代表沒有查詢到函數返回空,如果不是 -1 證明查詢到了該聯絡人,即可以進行刪除操作,從pos(需要進行刪除操作的名字位置)位置開始依次把後面的結構體成員資訊向前一個賦值,把需要刪除的那個成員資訊被後面的成員資訊覆蓋掉即可,最後賦值操作完成後,目前得通訊錄人數 -1即完成了我們的刪除操作。

④.功能三:通訊錄的查詢操作

具體程式碼如下:

void searchcontact(struct contact* pc)
{
	char name[namemax] = { 0 };
	printf("請您輸入想要查詢的聯絡人姓名>");
	scanf("%s", name);
	int pos = Findname(name, pc);
	if (pos == -1)
	{
		printf("沒找到此聯絡人\n");
	}
	else
	{
		printf("%-15s\t%5s\t%8s\t%15s\t%30s\t\n\n",
			"姓名", "年齡", "性別", "電話", "地址");
		printf("%-15s\t%5d\t%8s\t%15s\t%30s\t\n"
			, pc->data[pos].name
			, pc->data[pos].age
			, pc->data[pos].sex
			, pc->data[pos].tel
			, pc->data[pos].addr);

	}

}

查詢函數依舊用到了我們的按名字查詢函數,在結構體查詢到使用者輸入的名字時,返回對應名字的成員下標,沒查詢到就返回 -1,返回到查詢函數中,進行判斷 -1 就是沒找到,不是 -1,就證明查詢到了該聯絡人,列印出來對應下標pos的結構體成員變數資訊即可。

⑤.功能四:修改指定聯絡人

具體程式碼如下:

void modifycontact(struct contact* pc)
{
	char name[namemax] = { 0 };
	printf("請您輸入想要修改的聯絡人姓名>");
	scanf("%s", name);
	int pos = Findname(name, pc);
	if (pos == -1)
	{
		printf("沒找到此聯絡人\n");
	}
	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].tel);
		printf("請輸入修改聯絡人的地址>");
		scanf("%s", pc->data[pos].addr);
		printf("該聯絡人資訊修改成功!!!\n");
	}
}

在修改指定聯絡人的程式碼中我們可以看到,依舊使用到了查詢函數,我們使用查詢名字函數進行查詢使用者輸入想要更改的聯絡人是不是在通訊錄中,如果不在返回 -1 ,如果在通訊錄裡面,返回該聯絡人對應的下標。返回到更改函數中,進行條件判斷,如果是 -1 返回空程式結束證明修改功能沒能實現。如果返回的不是 -1 就證明該聯絡人在通訊錄裡,將他對應的下標結構體資訊進行重新的錄入即可。

⑤.功能五:展示聯絡人

具體程式碼如下:

void showcontact(struct contact* pc)
{
	printf("%-15s\t%5s\t%8s\t%15s\t%30s\t\n\n",
		"姓名", "年齡", "性別", "電話", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-15s\t%5d\t%8s\t%15s\t%30s\t\n"
			, pc->data[i].name
			, pc->data[i].age
			, pc->data[i].sex
			, pc->data[i].tel
			, pc->data[i].addr);
	}

}

在列印資訊的上面先定義一行標題,再利用迴圈,迴圈條件是小於目前通訊錄的人數(pc所指向的sz個數),迴圈列印出來所有的資訊即可

⑥.功能六:按照名字對通訊錄進行排序(這裡用到了qsort函數)--> qsort函數的用法

具體程式碼如下:

int cmp_byname(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
void sortcontact(struct contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_byname);
	printf("%-15s\t%5s\t%8s\t%15s\t%30s\t\n\n",
		"姓名", "年齡", "性別", "電話", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-15s\t%5d\t%8s\t%15s\t%30s\t\n"
			, pc->data[i].name
			, pc->data[i].age
			, pc->data[i].sex
			, pc->data[i].tel
			, pc->data[i].addr);
	}
}

看到這裡的 qsort 函數第一個引數是需要進行排序的陣列名,第二個引數是陣列的容量,即我們陣列中的人數,第三個引數是陣列元素的大小,pc->data代表整個陣列,pc->data[0]代表的就是陣列的第一個元素,利用 sizeof 即可計算出來陣列元素的大小(單位:位元組),最後一個引數是我們自定義比較函數的函數名。比較函數中,由於qsort函數對任意型別的元素都可以進行排序,所以裡面引數的型別採用的都是 void* 型別(void*型別可以接收任意型別的指標),在比較的時候強制轉換我們需要比較的資料型別即可,由於這裡需要通過名字進行比較,所以這裡用到 strcmp 函數進行比較,如果相等返回 0 ,相異返回 -1/1。排序後迴圈列印出來排序後的通訊錄即可。

⑦.功能零:退出通訊錄並銷燬通訊錄

void destorycontact(struct contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

這裡把剛剛給 pc 所指向的data開闢的空間釋放掉這裡用到了 free 函數即釋放我們剛剛動態開闢的空間,然後把 pc->data 指標置空,最後清空通訊錄的人數和總容量即可,綜上就完成通訊錄的退出與銷燬。

四、成果展示

①.資訊錄入 + 通訊錄增容

②.刪除聯絡人 + 展示

③.查詢指定聯絡人

④.修改指定聯絡人 + 展示

⑤.按名字排序(按照字元的assic碼值進行比較的)

⑥.退出通訊錄



五、程式碼彙總

①.contact.h(所需標頭檔案,函數宣告,宏的定義)

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define namemax 20
#define sexmax 5
#define telemax 12
#define addrmax 30
#define size 3
struct PeoInfo//定義一個聯絡人基本資訊
{
	char name[namemax];
	int age;
	char sex[sexmax];
	char tel[telemax];
	char addr[addrmax];
};
//這三個資訊組成我們的通訊錄
struct contact
{
	struct PeoInfo* data;
	int sz ;//目前通訊錄有幾個
	int capacity;//通訊錄的總容量
};
//函數宣告
//初始化通訊錄
void initcontact(struct contact* pc);
//增加聯絡人
void addcontact(struct contact* pc);
//展示通訊錄
void showcontact(struct contact* pc);
//刪除指定聯絡人
void delcontact(struct contact* pc);
//查詢指定聯絡人
void searchcontact(struct contact* pc);
//修改指定聯絡人
void modifycontact(struct contact* pc);
//按名字進行排序
void sortcontact(struct contact* pc);
//銷燬通訊錄
void destorycontact(struct contact* pc);

這裡的是函數宣告:

②.test.c(測試函數)

#pragma warning(disable : 4996)
#include "contact.h"
void menu()
{
	printf("**************************************\n");
	printf("*  1.新增聯絡人        2.刪除聯絡人  *\n");
	printf("*  3.查詢聯絡人        4.修改聯絡人  *\n");
	printf("*  5.展示通訊錄        6.按名字排序  *\n");
	printf("*               0.退出               *\n");
	printf("**************************************\n");
}
enum OPTION
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};
int main()
{
	int input = 0;
	struct contact con;//建立一個通訊錄con變數
	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 SHOW:
			showcontact(&con);
			break;
		case SORT:
			sortcontact(&con);
			break;
		case EXIT:
			destorycontact(&con);
			printf("退出通訊錄\n");
			break;
		}
	} while (input);
	return 0;
}

③.contact.c(功能函數的編寫)

#pragma warning(disable : 4996)
#include "contact.h"
void initcontact(struct contact* pc)
{
	pc->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));//動態分配給data一塊記憶體
	pc->sz = 0;//初始化時通訊錄沒人
	pc->capacity = size;//假設一開始的通訊錄容量為3後面不夠用隨時增容
}
void addcontact(struct contact* pc)
{
	//如果通訊錄滿了
	if (pc->sz == pc->capacity)
	{
		//增容
		struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity += 2;
			printf("通訊錄增容成功\n");
		}
		else
		{
			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].tel);
	printf("請輸入新增聯絡人的地址>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
}
void showcontact(struct contact* pc)
{
	printf("%-15s\t%5s\t%8s\t%15s\t%30s\t\n\n",
		"姓名", "年齡", "性別", "電話", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-15s\t%5d\t%8s\t%15s\t%30s\t\n"
			, pc->data[i].name
			, pc->data[i].age
			, pc->data[i].sex
			, pc->data[i].tel
			, pc->data[i].addr);
	}

}
int Findname(char* name, struct contact* pc)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
		{
			return i;
		}
	}
	return -1;
}
void delcontact(struct contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通訊錄為空無法刪除\n");
		return;
	}
	char name[namemax] = { 0 };
	printf("請您輸入想要刪除的聯絡人姓名>");
	scanf("%s", name);
	int pos = Findname(name, pc);
	if (pos == -1)
	{
		printf("沒找到此聯絡人\n");
	}
	else
	{
		int j = 0;
		for (j = pos; j < pc->sz; j++)
		{
			pc->data[j] = pc->data[j + 1];//所有訊息都進行交換
		}
		pc->sz--;
		printf("該聯絡人刪除成功\n");
	}
}
void searchcontact(struct contact* pc)
{
	char name[namemax] = { 0 };
	printf("請您輸入想要查詢的聯絡人姓名>");
	scanf("%s", name);
	int pos = Findname(name, pc);
	if (pos == -1)
	{
		printf("沒找到此聯絡人\n");
	}
	else
	{
		printf("%-15s\t%5s\t%8s\t%15s\t%30s\t\n\n",
			"姓名", "年齡", "性別", "電話", "地址");
		printf("%-15s\t%5d\t%8s\t%15s\t%30s\t\n"
			, pc->data[pos].name
			, pc->data[pos].age
			, pc->data[pos].sex
			, pc->data[pos].tel
			, pc->data[pos].addr);

	}

}
void modifycontact(struct contact* pc)
{
	char name[namemax] = { 0 };
	printf("請您輸入想要修改的聯絡人姓名>");
	scanf("%s", name);
	int pos = Findname(name, pc);
	if (pos == -1)
	{
		printf("沒找到此聯絡人\n");
	}
	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].tel);
		printf("請輸入修改聯絡人的地址>");
		scanf("%s", pc->data[pos].addr);
		printf("該聯絡人資訊修改成功!!!\n");
	}
}
int cmp_byname(const void* e1, const void* e2)
{
	return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
void sortcontact(struct contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_byname);
	printf("%-15s\t%5s\t%8s\t%15s\t%30s\t\n\n",
		"姓名", "年齡", "性別", "電話", "地址");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-15s\t%5d\t%8s\t%15s\t%30s\t\n"
			, pc->data[i].name
			, pc->data[i].age
			, pc->data[i].sex
			, pc->data[i].tel
			, pc->data[i].addr);
	}
}
void destorycontact(struct contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

總結

這就是簡單通訊錄的實現,對C語言很多的知識進行了全面的應用,後面還會對通訊錄實現檔案的版本,還請持續關注,如果本篇文章存在問題請及時聯絡博主,或者評論區下方留言,謝謝大家的支援!!