溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么

發(fā)布時間:2021-11-20 11:23:54 來源:億速云 閱讀:139 作者:iii 欄目:開發(fā)技術

這篇文章主要講解了“C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么”吧!

靜態(tài)通訊錄

在我們學習完C語言的結構體、指針以及動態(tài)內(nèi)存管理之后,我們就可以實現(xiàn)一些有意思的小項目了,通過這些小項目可以加深我們對于相關知識的理解。

靜態(tài)通訊錄主要要求有

  • 靜態(tài)大小,可以記錄10個人的信息(大小自己定)

  • 記錄的信息如下:名字、性別、年齡、電話、住址

  • 可以實現(xiàn)聯(lián)系人的增刪查改

為了方便代碼的管理和維護,我們分文件實現(xiàn)以上的要求

  • contact.h 用于聲明相關的接口

  • contact.c 用于實現(xiàn)相關的接口

  • test.c 用于測試相關的接口

contact.h

在contact.h中,我們統(tǒng)一用預處理指令來確定好通訊錄的大小,以及每一個聯(lián)系人信息的范圍大小,方便后續(xù)的修改

在確定好范圍后,我們通過定義結構體類型的方式來實現(xiàn)對數(shù)據(jù)的統(tǒng)一管理

結構體類型確定后,就是相關接口的聲明了

//首先引入需要用到的頭文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//確定每一個聯(lián)系人名字、電話等信息的范圍大小
#define MAX_NAME 10
#define MAX_PHONE 20
#define MAX_ADDR 25

// 確定通訊錄的總大小
#define MAX_CAPACITY 10

//由于每一個聯(lián)系人都有多個信息,因此需要定義一個結構體類型來管理
//定義聯(lián)系人相關信息的結構體
 typedef struct PeoInfo {

	char name[MAX_NAME];
	char sex;
	int  age;
	char phone[MAX_PHONE];
	char address[MAX_ADDR];

}peo;


//通訊錄內(nèi)包含多個成員,因此也需要統(tǒng)一管理,所以還是使用結構體
 //定義一個通訊錄結構體,管理通訊錄和記錄有效聯(lián)系人個數(shù)信息
typedef struct Contact {

	peo data[MAX_CAPACITY];//這里是一個數(shù)組,數(shù)組的每一個元素都是一個結構體
	int size;
}con;





//------------------------------------------------------
//以下是相關接口的聲明

//菜單接口
void menu();

//對結構體變量進行初始化
void InitContact(con* con);

//打印通訊錄信息
void Print(con* con);

//實現(xiàn)增加聯(lián)系人的接口
void AddContact(con* con);

//實現(xiàn)刪除聯(lián)系人的接口
void DelContact(con* con);

//實現(xiàn)查找聯(lián)系人的接口
void SearchContact(con* con);

//實現(xiàn)修改聯(lián)系人的接口
void ModifyContact(con* con);

contact.c

contact.c是整個項目的關鍵,需要對相關接口進行定義

//通訊錄各個接口的實現(xiàn)
//首先引入.h文件
#include"Contact.h"

//菜單接口
void menu() {

	printf("*******************************\n");
	printf("********靜態(tài)簡易通訊錄*********\n");
	printf("*******   0.退出通訊錄   ******\n");
	printf("*******   1.增加聯(lián)系人   ******\n");
	printf("*******   2.刪除聯(lián)系人   ******\n");
	printf("*******   3.查找聯(lián)系人   ******\n");
	printf("*******   4.修改聯(lián)系人   ******\n");
	printf("*******   5.打印聯(lián)系人   ******\n");
	printf("*******************************\n");
	printf("\n");

}



//對結構體變量進行初始化
void InitContact(con* con) {

	//結構體的初始化一般用memset
	//我們首先讓通訊錄結構體變量的數(shù)組一開始為0
	memset(con->data, 0, sizeof(con->data));
	
	con->size = 0;//同時由于此時一個聯(lián)系人的信息都沒有,所以size也是0
}


//打印通訊錄信息
void Print(con* con){
	int i = 0;
	if (con->size == 0) {
		printf("暫無可打印信息\n");
		return ;
	}
	printf("name\tsex\tage\tphone\taddress\n");
	for (i = 0; i < con->size; i++) {
		printf("%s\t%c\t%d\t%s\t%s\n", 
			con->data[i].name, con->data[i].sex,
			con->data[i].age, con->data[i].phone, con->data[i].address);
	}

}


//實現(xiàn)增加聯(lián)系人的接口
void AddContact(con* con) {
	if (con->size == MAX_CAPACITY) {

		printf("容量已滿,無法增加\n");
		return;
	}

	printf("請輸入姓名:\n");
	scanf("%s", con->data[con->size].name);

	getchar();

	printf("請選擇性別:(m表示男,w表示女)\n");
	scanf("%c", &(con->data[con->size].sex));

	printf("請輸入年齡:\n");
	scanf("%d", &(con->data[con->size].age));

	printf("請輸入手機號碼:\n");
	scanf("%s", con->data[con->size].phone);

	printf("請輸入住址:\n");
	scanf("%s", con->data[con->size].address);

	con->size++;
}

//實現(xiàn)刪除聯(lián)系人的接口
void DelContact(con* con) {

	if (con->size == 0) {
		printf("暫無可以刪除的信息");
		return;
	}

	printf("請輸入你要刪除的聯(lián)系人的姓名:\n");
	char name[MAX_NAME] = {0};

	scanf("%s", name);
	int i = 0;
	for (i = 0; i < con->size; i++) {
		if (strcmp(name, (con->data)[i].name) == 0) {
			int j = 0;
			for (j = i; j < con->size - 1; j++) {
				memmove(&(con->data[j]), &(con->data[j + 1]), sizeof(con->data[0]));
			}
			con->size--;
			return;

		}
	}
	printf("你輸入的聯(lián)系人不存在\n");
	
}


//實現(xiàn)查找聯(lián)系人的接口
void SearchContact(con* con) {

	if (con->size == 0) {
		printf("暫無查找的信息");
		return;
	}

	printf("請輸入你要查找的聯(lián)系人的姓名:\n");
	char name[MAX_NAME] = { 0 };

	scanf("%s", name);
	int i = 0;
	for (i = 0; i < con->size; i++) {
		if (strcmp(name, (con->data)[i].name) == 0) {
			printf("%s\t%c\t%d\t%s\t%s\n",
				con->data[i].name, con->data[i].sex,
				con->data[i].age, con->data[i].phone, con->data[i].address);
			return;

		}
	}
	printf("你想要查找的聯(lián)系人不存在\n");
}

//實現(xiàn)修改聯(lián)系人的接口
void ModifyContact(con* con) {

	if (con->size == 0) {
		printf("暫無可以修改的信息");
		return;
	}

	printf("請輸入你要修改的聯(lián)系人的姓名:\n");
	char name[MAX_NAME] = { 0 };

	scanf("%s", name);
	int i = 0;
	for (i = 0; i < con->size; i++) {
		if (strcmp(name, (con->data)[i].name) == 0) {

			printf("請重新輸入姓名:\n");
			scanf("%s", con->data[i].name);

			getchar();

			printf("請重新選擇性別:(m表示男,w表示女)\n");
			scanf("%c", &(con->data[i].sex));

			printf("請重新輸入年齡:\n");
			scanf("%d", &(con->data[i].age));

			printf("請重新輸入手機號碼:\n");
			scanf("%s", con->data[i].phone);

			printf("請重新輸入住址:\n");
			scanf("%s", con->data[i].address);
			return;

		}
	}
	printf("你想要修改的聯(lián)系人不存在\n");

}

提示

我們在實現(xiàn)接口的時候,如果形參傳入的是指針,一般都需要先判斷一下傳入的指針是否為空指針,以免造成非法訪問,但是由于我的疏忽,就沒有寫上去了!

test.c

test.c就是用來測試相關接口的文件,可以根據(jù)自己的想法來設定

#include"Contact.h"


int main() {

	//創(chuàng)建結構體并且初始化
	con c;
	InitContact(&c);

	menu();
	int input = 0;


	while (1) {

		printf("請輸入你的選擇:\n");
		scanf("%d", &input);

		switch (input) {
		case 1:
			AddContact(&c);
			break;
		case 2:
			DelContact(&c);
			break;
		case 3:
			SearchContact(&c);
			break;
		case 4:
			ModifyContact(&c);
			break;
		case 5:
			Print(&c);
			break;
		case 0:
			printf("退出通訊錄\n");
			break;
		default:
			printf("你的輸入有誤,請重新選擇\n");
			break;

		}

		if (input == 0) {
			break;
		}
	}

	return 0;
}

動態(tài)通訊錄

靜態(tài)通訊錄有一個缺點,那就是通訊錄的大小,也就是只能存儲的聯(lián)系人是要求確定大小的,大小給多了浪費空間,給少了又不夠用。

動態(tài)通訊錄就是通過動態(tài)內(nèi)存管理的函數(shù)來實現(xiàn)動態(tài)開辟空間大小,以滿足需要的。

contact.h

//動態(tài)版本通訊錄的實現(xiàn)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>


#define MAX_NAME 15
#define MAX_PHONE 15
#define MAX_ADDR 25

//給定通訊錄默認大小為5,不夠可以增容
#define DefaultSize 5

//聯(lián)系人結構體的聲明
typedef struct PeoInfo {

	char name[MAX_NAME];
	char sex;
	short age;
	char phone[MAX_PHONE];
	char addr[MAX_ADDR];

}peo;

//通訊錄結構體的聲明
typedef struct Contact {

	peo* p;//我們通過指針的方式來管理聯(lián)系人數(shù)組
	int capacity;
	int size;
}con;


//菜單函數(shù)
void menu();

//初始化通訊錄
void InitCon(con* c);

//銷毀通訊錄
void DestoryCon(con* c);

//檢查容量的接口
void CheckCapacity(con* c);

//打印聯(lián)系人信息
void Print(con* c);

//聯(lián)系人的增加
void AddCon(con* c);

//聯(lián)系人的刪除
void DelCon(con* c);

//聯(lián)系人的查找
void SearchCon(con* c);

//聯(lián)系人的修改
void ModifyCon(con* c);

//-------------------------------------------
//下面是我通過快排的原理,手寫的快排來實現(xiàn)一下通過聯(lián)系人名字和年齡排序的接口

//通過名字來排序
void SortByname(con* c);

//通過年齡來排序
void SortByage(con* c);


void Swap(char* p1, char* p2, int width);


void QSort(void* p, int num, int width, int(*cmp)(const void* , const void* ));


int cmpbyname(const void* p1,const void* p2);


int cmpbyage(const void* p1,const void* p2);

contact.c

關鍵接口的實現(xiàn)和靜態(tài)通訊錄的大同小異,只不過我們需要多定義一個檢查空間的接口

每次增加聯(lián)系人的時候,就調(diào)用這個接口,做到滿了就增容

其中增容接口使用的時realloc函數(shù)

#include"contact.h"

//菜單函數(shù)
void menu() {

	printf("******************************************\n");
	printf("*************   動態(tài)版通訊錄   ***********\n");
	printf("*************   1.增加聯(lián)系人   ***********\n");
	printf("*************   2.刪除聯(lián)系人   ***********\n");
	printf("*************   3.查找聯(lián)系人   ***********\n");
	printf("*************   4.修改聯(lián)系人   ***********\n");
	printf("*************   5.按名字排序   ***********\n");
	printf("*************   6.按年齡排序   ***********\n");
	printf("*************   7.打印聯(lián)系人   ***********\n");
	printf("*************   0.退出通訊錄   ***********\n");
	printf("******************************************\n");


}

//初始化通訊錄
void InitCon(con* c) {

	//這里也可以用relloc函數(shù)來初始化,這樣的話就會有初始值
	c->p = (con*)malloc(DefaultSize * sizeof(peo));
	c->capacity = DefaultSize;
	c->size = 0;
}


//銷毀通訊錄
void DestoryCon(con* c) {

	free(c->p);
	c->p = NULL;
	c->capacity = 0;
	c->size = 0;

}

//檢查容量的接口
void CheckCapacity(con* c) {

	if (c->capacity == c->size) {

		//每次增容二倍
		peo* tmp = (peo*)realloc(c->p, 2 * (c->capacity) * sizeof(peo));
		if (tmp != NULL) {
			c->p = tmp;
			c->capacity = 2 * c->capacity;
			printf("增容成功\n");
		}
		else {
			printf("增容失敗\n");
			exit(1);
		}
	}
}

//打印聯(lián)系人信息
void Print(con* c) {

	if (c->size == 0) {
		printf("暫無可以打印的信息\n");
		return;
	}

	printf("name\tsex\tage\tphone\taddress\n");

	int i = 0;
	for (i = 0; i < c->size; i++) {
		printf("%s\t%c\t%d\t%s\t%s\n", 
			c->p[i].name, c->p[i].sex, c->p[i].age, c->p[i].phone, c->p[i].addr);

	}
}

//聯(lián)系人的增加
void AddCon(con* c) {

	//每一次增加聯(lián)系人都要先檢查容量是否足夠
	CheckCapacity(c);

	printf("請輸入名字:>\n");
	scanf("%s", c->p[c->size].name);
	getchar();
	printf("請輸入性別:>(m表示男,w表示女)\n");
	scanf("%c", &(c->p[c->size].sex));
	printf("請輸入年齡:>\n");
	scanf("%d", &(c->p[c->size].age));
	printf("請輸入電話:>\n");
	scanf("%s", c->p[c->size].phone);
	printf("請輸入地址:>\n");
	scanf("%s", c->p[c->size].addr);

	c->size++;
	printf("添加成功\n");
}

//聯(lián)系人的刪除
void DelCon(con* c) {

	printf("請輸入你想要刪除的聯(lián)系人的名字\n");
	char name[MAX_NAME];
	scanf("%s", name);

	int i = 0;
	for (i = 0; i < c->size; i++) {

		if (strcmp(name, c->p[i].name) == 0) {

			
			int j = i;
			for (j = i; j < c->size - 1; j++) {
				memmove(&(c->p[j]), &(c->p[j + 1]), sizeof(c->p[0]));
			}
			c->size--;
			return;
		}

	}

	printf("你想要刪除的聯(lián)系人不存在\n");
}

//聯(lián)系人的查找
void SearchCon(con* c) {

	printf("請輸入你想要查找的人的名字:\n");
	char name[MAX_NAME];
	scanf("%s", name);

	int i = 0;
	for (i = 0; i < c->size; i++) {

		if (strcmp(name, c->p[i].name) == 0) {

			printf("%s\t%c\t%d\t%s\t%s\n",
				c->p[i].name, c->p[i].sex, c->p[i].age, c->p[i].phone, c->p[i].addr);
			return;
		}

	}

	printf("你想要查找的聯(lián)系人不存在\n");

}

//聯(lián)系人的修改
void ModifyCon(con* c) {

	printf("請輸入你想要修改的人的名字:\n");
	char name[MAX_NAME];
	scanf("%s", name);

	int i = 0;
	for (i = 0; i < c->size; i++) {

		if (strcmp(name, c->p[i].name) == 0) {

			printf("請重新輸入名字:>\n");
			scanf("%s", c->p[i].name);
			getchar();
			printf("請重新輸入性別:>(m表示男,w表示女)\n");
			scanf("%c", &(c->p[i].sex));
			printf("請重新輸入年齡:>\n");
			scanf("%d", &(c->p[i].age));
			printf("請重新輸入電話:>\n");
			scanf("%s", c->p[i].phone);
			printf("請重新輸入地址:>\n");
			scanf("%s", c->p[i].addr);
			return;
		}

	}

	printf("你想要修改的聯(lián)系人不存在\n");

}



//通過名字來排序
void SortByname(con* c) {

	QSort(c->p, c->size, sizeof(c->p[0]),cmpbyname );

}

//通過年齡來排序
void SortByage(con* c) {

	QSort(c->p, c -> size, sizeof(c->p[0]), cmpbyage);

}

qsort.c

這是我根據(jù)快速排序的原理,手寫的快速排序

#include"contact.h"


//快排的交換函數(shù)
void Swap(char* p1, char* p2, int width) {

	int i = 0;
	for (i = 0; i < width; i++) {
		char tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2++;
	}

}

//手寫快排來進行通訊錄排序
void QSort(void* p, int num, int width, int(*cmp)(const void*, const void*)) {

	int i = 0;
	for (i = 0; i < num - 1; i++) {

		int j = 0;
		for (j = 0; j < num - 1 - i; j++) {

			if (cmp((char*)p + j * width, (char*)p + (j + 1) * width) > 0) {
				Swap((char*)p + j * width, (char*)p + (j + 1) * width, width);
			}
		}

	}
}

int cmpbyage(const void* p1, const void* p2) {

	return (*(peo*)p1).age - (*(peo*)p2).age;
}

int cmpbyname(const void* p1, const void* p2) {

	return strcmp(((peo*)p1)->name,((peo*)p2)->name);
}

test.c

test.c用于測試相關的接口,可以根據(jù)自己的想法來測試

#include"contact.h"


int main() {


	menu();
	int input = 0;
		


	con c;
	InitCon(&c);

	while (1) {
		
		printf("請輸入你的選擇:\n");
		scanf("%d", &input);

		switch (input) {
		case 1:
			AddCon(&c);
			break;
		case 2:
			DelCon(&c);
			break;
		case 3:
			SearchCon(&c);
			break;
		case 4:
			ModifyCon(&c);
			break;
		case 5:
			SortByname(&c);
			break;
		case 6:
			SortByage(&c);
			break;
		case 7:
			Print(&c);
			break;
		case 0:
			printf("退出通訊錄\n");
			break;

		}
		if (input == 0) {
			DestoryCon(&c);
			break;
		}
	}

	return 0;
}

感謝各位的閱讀,以上就是“C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對C語言靜態(tài)與動態(tài)通訊錄的實現(xiàn)方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI