1. 程式人生 > 其它 >C語言進階篇 進階小專案【通訊錄】

C語言進階篇 進階小專案【通訊錄】

技術標籤:C語言

目錄

一、專案結構和專案說明

二、具體實現

int main()

//初始化通訊錄void InitContact(struct Contact* ps);

//查詢函式static int FindByName(const struct Contact* ps, char name[MAX_NAME])

//新增資訊void AddContact(struct Contact* ps);

//刪除指定的聯絡人void DelContact(struct Contact* ps);

//查詢指定的聯絡人void SearchContact(struct Contact* ps);

//更新指定的聯絡人void ModifyContact(struct Contact* ps);

//排序通訊錄void SortContact(struct Contact* ps);

//展示通訊錄void ShowContact(struct Contact* ps);

三、個人總結及GitHub地址


一、專案結構和專案說明

專案結構依然是標準三段式:

本程式需要完成以下功能:

1、初始化通訊錄

2、新增友人資訊

3、刪除指定聯絡人

4、查詢指定聯絡人

5、更新指定聯絡人資訊

6、對通訊錄按姓氏名字排序

7、展示通訊錄

二、具體實現

首先展示主函式:

int main()

int main()
{
	int input = 0;
	//建立通訊錄
	struct Contact con;//con就是通訊錄,裡面包含存放1000個人的資訊和size。
	//初始化通訊錄
	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:
			printf("退出通訊錄\n");
			break;
		default:
			printf("選擇錯誤\n");
			break;
		}
	} while (input);
	return 0;
}

這裡使用了列舉變數,來一一對應0~6這7個數字,

增強了程式碼的可讀性。

然後我們來看一下標頭檔案:

struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
};

//通訊錄型別
struct Contact
{
	struct PeoInfo data[MAX];//存放一個資訊
	int size;//紀錄當前已經有的元素個數
};

我們用PeoInfo來表示個人,

然後用Contact這個結構體儲存個人資訊,將其用陣列儲存,

再新增一個計數器,用來計數已存放的人數。

接下來看函式實現:

//初始化通訊錄
void InitContact(struct Contact* ps);

void InitContact(struct Contact* ps)
{
	memset(ps->data, 0, sizeof(ps->data));
	ps->size = 0;
}

首先傳結構體的地址,這樣才能實際操作結構體。

然後使用記憶體設定函式,將這個結構體的資料域和大小域初始化。

//查詢函式
static int FindByName(const struct Contact* ps, char name[MAX_NAME])

//查詢函式
//找到返回名字所在元素的下標
//找不到返回 -1
//static修飾函式,使函式只能在該contact.cpp原始檔中使用,不暴露給外面。
static int FindByName(const struct Contact* ps, char name[MAX_NAME])
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->data[i].name, name))
		{
			return i;
		}
	}
	return -1;//找不到的情況
}

我們先寫一個查詢函式,引數型別有兩個,一個是結構體地址,一個是字串。

通過for迴圈,如果找到了,就返回其下標;

如果沒找到,就返回-1.

這樣封裝起來減少了程式碼的冗餘,

並且不需要在標頭檔案裡宣告,

寫成static即可,在本函式下方便使用。


//新增資訊
void AddContact(struct Contact* ps);

void AddContact(struct Contact* ps)
{
	if (ps->size == MAX)
	{
		printf("通訊錄已滿,無法增加\n");
	}
	else
	{
		printf("請輸入名字:>");
		scanf("%s", ps->data[ps->size].name);
		printf("請輸入年齡:>");
		scanf("%d", &(ps->data[ps->size].age));
		printf("請輸入性別:>");
		scanf("%s", ps->data[ps->size].sex);
		printf("請輸入電話:>");
		scanf("%s", ps->data[ps->size].tele);
		printf("請輸入地址:>");
		scanf("%s", ps->data[ps->size].addr);

		ps->size++;
		printf("新增成功\n");
	}
}


//刪除指定的聯絡人
void DelContact(struct Contact* ps);

void DelContact(struct Contact* ps)
{
	char name[MAX_NAME];
	printf("請輸入要刪除的人的名字:>");
	scanf("%s", name);
	//1.查詢要刪除的人在什麼位置

	int pos = FindByName(ps, name);

	//2.刪除
	if (pos == -1)
	{
		printf("要刪除的人不存在\n");
	}
	else
	{
		//刪除資料,後面的元素往前覆蓋
		int j = 0;
		//注意這裡陣列的下標
		for (j = pos; j < ps->size-1; j++)
		{
			ps->data[j] = ps->data[j + 1];
		}
		ps->size--;
	}
}

這裡的刪除,我們用的方法是,先刪除該元素,然後依次將後面的元素往前挪。

注意陣列下標!

建議畫個草圖算一下。


//查詢指定的聯絡人
void SearchContact(struct Contact* ps);

void SearchContact(struct Contact* ps)
{
	char name[MAX_NAME];
	printf("請輸入要查詢的人的名字:>");
	scanf("%s", name);

	int pos = FindByName(ps, name);

	if (pos == -1)
	{
		printf("要查詢的人不存在!\n");
	}
	else
	{
		printf("%-20s\t%-s\t%-5s\t%-12s\t%-20s\n", "名字", "年齡", "性別", "電話", "地址");
		printf("%-20s\t%-4d\t%-5t\t%-12s\t%-20s\n",
			ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].tele,
			ps->data[pos].addr);
	}
}

這裡\t的意思是 橫向跳到下一製表符位置。


//更新指定的聯絡人
void ModifyContact(struct Contact* ps);

void ModifyContact(struct Contact* ps)
{
	char name[MAX_NAME];
	printf("請輸入要修改的人的名字:>");
	scanf("%s", name);
	int pos = FindByName(ps, name);

	if (pos == -1)
	{
		printf("要修改的人不存在!\n");
	}
	else
	{
		printf("請輸入名字:>");
		scanf("%s", ps->data[pos].name);
		printf("請輸入年齡:>");
		scanf("%d", &(ps->data[pos].age));
		printf("請輸入性別:>");
		scanf("%s", ps->data[pos].sex);
		printf("請輸入電話:>");
		scanf("%s", ps->data[pos].tele);
		printf("請輸入地址:>");
		scanf("%s", ps->data[pos].addr);

		printf("修改完成\n");
	}

}


//排序通訊錄
void SortContact(struct Contact* ps);

void SortContact(struct Contact* ps)
{
	int i = 0;
	for (i = 0; i < ps->size-1; i++)
	{
		int j = 0;
		for (j = 0; j < ps->size - 1 - i; j++)
		{
			char cmp = strcmp(ps->data[j].name, ps->data[j+1].name);
			if (cmp > 0)
			{
				struct Contact temp = { 0 };
				temp.data[0] = ps->data[j + 1];
				ps->data[j + 1] = ps->data[j];
				ps->data[j] = temp.data[0];
			}
		}
	}
	printf("已按姓名排序\n");
}


//展示通訊錄
void ShowContact(struct Contact* ps);

void ShowContact(struct Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通訊錄為空!\n");
	}
	else
	{
		int i = 0;
		printf("%-20s\t%-s\t%-5s\t%-12s\t%-20s\n", "名字", "年齡", "性別", "電話", "地址");
		for (i = 0; i < ps->size; i++)
		{
			printf("%-20s\t%-4d\t%-5t\t%-12s\t%-20s\n",
				ps->data[i].name,
				ps->data[i].age,
				ps->data[i].sex,
				ps->data[i].tele,
				ps->data[i].addr);
		}
	}
}

三、個人總結及GitHub地址

這個小專案實現了對資料的增刪改查,還有排序功能,已經是操作資料庫的雛形了。但是還有很多需要完善的地方,比如遇到同名怎麼辦?是否可以節約記憶體?是否可以實現用檔案的方式來處理通訊錄?我會再接下來的學習中改進這份通訊錄。

GitHub:https://github.com/kukeoo/Contact.git