【C语言】通讯录的实现(基本版和动态版)

🦄个人主页:小米里的大麦-CSDN博客

🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html

🎁代码托管:C语言: C语言方向(基础知识和应用) (gitee.com)

⚙️操作环境:Visual Studio 2022

目录

一、引言

二、基本版

1. 成员基本信息的构建

2.简易的菜单实现

3. 通讯录管理系统的核心功能函数声明

4. 初始化通讯录

5. 增加联系人信息

6.显示联系人信息

6. 查找指定联系人信息

7. 删除指定联系人信息

8. 修改指定联系人信息

9. 对所有联系人进行排序

10. 清空所有联系人信息

三、完整代码及部分功能展示

1. Contacts.h

2. Contacts.c

3. Contacts_text.c

4. 效果展示: 

四、动态升级版通讯录展示

1. Contacts_plus.h

2. Contacts_plus.c

3. Contacts_text_plus.c

五、总结

共勉


一、引言

通过使用C语言来创建一个通讯录的管理系统,管理人员可对成员信息进行管理。成员信息包括姓名、年龄、电话、性别以及住址,执行操作有增删改查这四项基本操作以及成员信息全览和信息排序。为此,作者准备了两个版本:基本版和动态版。我们一起来看看吧:

二、基本版

1. 成员基本信息的构建

既是通讯录,肯定要有基本的成员(联系人)信息,所以我们选择通过创建一个结构体来构建这个通讯录基本成员的信息。通讯录结构体内部会嵌套一个成员信息结构体和一个表示成员数量的变量。

typedef struct Information		//Information:信息
{
	char name[name_max];		//name:姓名
	int age;					//age:年龄
	char gender[gender_max];	//gender:性别
	char address[address_max];	//address:地址
	char phone[phone_max];		//phone:电话
}Information;

typedef struct Contact
{
	Information data[number];//存放20个人的信息		number:数量		data:数据
	int sz;//当前已经放的信息的个数
}Contact;

2.简易的菜单实现

对于我们要创建的通讯录管理系统来说,建立一个菜单无疑是非常简单明了的,可以让用户自行选择功能,这就好比在一个餐厅里,店员提供了一份菜单,顾客就可以根据自己的意愿进行点菜,同理,在操作界面显示一个完整的菜单,才能更好地管理通讯录系统,当然,尽管终端显示的菜单没那么美观,哈哈,要注重功能的实现!

为了方便,这里可以使用一个枚举类型进行表示,也是先浅浅透漏一点基本逻辑,即使没看明白,后面也会重新点播哦!

void menu()
{
	printf("*********************************************\n");//add:增加
	printf("**       1.add             2.delete        **\n");//delete:删除
	printf("**       3.search          4.modify        **\n");//search:搜索	
	printf("**       5.show            6.sort          **\n");//modify:修改	
	printf("**                0.exits                  **\n");//show:显示
	printf("*********************************************\n");//sort:排序
	//exit:退出
}



/*
enum pick				//pick:选择
{
	exits = 0,
	add,
	delete,
	search,
	modify,
	show,
	sort
};

int main()
{
	int input = 0;						//input:输入
	Contact temp;						//temp:临时
	initialize(&temp);					//initialize:初始化
	do
	{
		menu();							//menu:菜单
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case add:
			AddContacts(&temp);
			break;
		case delete:
			DeleteContacts(&temp);
			break;
		case search:
			SearchContacts(&temp);
			break;
		case modify:
			ModifyContacts(&temp);
			break;
		case show:
			ShowContacts(&temp);
			break;
		case sort:
			SortContacts(&temp);
			break;
		case exits:
			printf("已退出通讯录!\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);

	return 0;
}
*/

3. 通讯录管理系统的核心功能函数声明

 能够看到:除了核心函数,还有五个排序所用函数比较的指针,这是什么呢?其实这是用了qsort函数的原因,先在这里给大家做个铺垫,对qsort不了解的,可以看看:【C语言】qsort详解——能给万物排序的神奇函数-CSDN博客

//此版本是固态不可变版本,所以五个define的阿拉伯数字内容可自行修改成个人所需
#define number 20
#define name_max 10
#define gender_max 5
#define address_max 15
#define phone_max 12


void initialize(Contact* p);//初始化

void AddContacts(Contact* p);//增加联系人

void DeleteContacts(Contact* p);//删除指定联系人

void SearchContacts(const Contact* p);//查找联系人

void ModifyContacts(Contact* p);//修改联系人

void ShowContacts(const Contact* p);//显示通讯录信息

void SortContacts(Contact* p);//对联系人排序


//排序所用函数比较的指针
int compareName(const void* a, const void* b);
int compareAge(const void* a, const void* b);
int compareGender(const void* a, const void* b);
int compareAddress(const void* a, const void* b);
int comparePhone(const void* a, const void* b);

4. 初始化通讯录

为什么要对通讯录进行初始化呢?因为在创建了通讯录之后,里边所有信息的会以随机值的形式存在,通讯录的存储还没满,这样的话没存东西的地方就会打印出一些奇奇怪怪的东西,所以要进行初始化。

void initialize(Contact* p)
{
	assert(p);
	p->sz = 0;
	memset(p->data, 0, sizeof(p->data));
}

5. 增加联系人信息

手动输入,逻辑比较简单,一看就懂。

//增加联系人
void AddContacts(Contact* p)
{
	assert(p);
	if (p->sz == number)
	{
		printf("通讯录已满,无法添加新的联系人!\n");
		return;
	}

	printf("请输入姓名:");
	scanf("%s", &p->data[p->sz].name);
	printf("请输入年龄:");
	scanf("%d", &p->data[p->sz].age);
	printf("请输入性别:");
	scanf("%s", &p->data[p->sz].gender);
	printf("请输入地址:");
	scanf("%s", &p->data[p->sz].address);
	printf("请输入电话:");
	scanf("%s", &p->data[p->sz].phone);

	p->sz++;
}

6.显示联系人信息

先打印表头信息可增加美观性和可读性,再打印通讯录当前已有信息,代码中的阿拉伯数字主要是为限定格式进行对齐增加美观的,可自行更改。

//显示/打印通讯录信息
void ShowContacts(const Contact* p)
{
	assert(p);
	printf("%-10s\t%-5s\t%-5s\t%-15s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	for (int i = 0; i < p->sz; i++)
	{
		printf("%-10s\t%-5d\t%-5s\t%-15s\t%-12s\n", p->data[i].name, p->data[i].age, p->data[i].gender, p->data[i].address, p->data[i].phone);
	}
}

6. 查找指定联系人信息

这个函数的存在就是为了通讯录管理人员通过成员姓名来查找该成员信息所处的位置。 注意函数之间的调用关系(SearchContacts  ->  lookup_name)。

//查找指定联系人信息

//查找姓名函数
int lookup_name(const Contact* p, char name[])
{
	assert(p);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(p->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}


void SearchContacts(const Contact* p)
{
	assert(p);
	char name[name_max] = { 0 };
	printf("请输入需要查找联系人的姓名:");
	scanf("%s", name);

	int temp = lookup_name(p, name);

	if (temp == -1)
	{
		printf("抱歉,要查找的联系人不存在!\n");
	}
	else
	{
		printf("%-10s\t%-5s\t%-5s\t%-15s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
		printf("%-10s\t%-5d\t%-5s\t%-15s\t%-12s\n", p->data[temp].name, p->data[temp].age, p->data[temp].gender, p->data[temp].address, p->data[temp].phone);
	}
	
}

7. 删除指定联系人信息

注意:这里依旧使用 lookup_name 函数来对联系人的姓名进行查找,再进行删除操作。

//删除指定联系人信息
void DeleteContacts(Contact* p)
{
	assert(p);
	char name[name_max] = { 0 };
	if (p->sz == 0)
	{
		printf("通讯录是空的,无法进行删除操作!\n");
		return;
	}

	printf("请输入需要删除的联系人的姓名:");
	scanf("%s", name);

	int temp=lookup_name(p, name);
	if (temp == -1)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}

	for (int i = temp; i < p->sz - 1; i++)
	{
		p->data[i] = p->data[i + 1];
	}
	p->sz--;

	printf("删除联系人成功!\n");
}

8. 修改指定联系人信息

注意我们的  looup_name  函数哦!

//修改指定联系人
void ModifyContacts(Contact* p)
{
	assert(p);

	if (p->sz == 0)
	{
		printf("通讯录是空的,无法进行修改操作!\n");
		return;
	}

	char name[name_max] = { 0 };
	printf("请输入需要修改的联系人的姓名:");
	scanf("%s", name);

	int index = lookup_name(p, name);

	if (index == -1)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}

	Information* info = &p->data[index];

	printf("请选择需要修改的信息类型:\n");
	printf("1. 姓名\n2. 年龄\n3. 性别\n4. 地址\n5. 电话\n");
	int modifyInput;
	printf("请输入数字选择修改的信息类型:");
	scanf("%d", &modifyInput);

	switch (modifyInput)
	{
	case 1: // 修改姓名
		printf("请输入新的姓名:");
		scanf("%s", info->name);
		break;
	case 2: // 修改年龄
		printf("请输入新的年龄:");
		scanf("%d", &info->age);
		break;
	case 3: // 修改性别
		printf("请输入新的性别:");
		scanf("%s", info->gender);
		break;
	case 4: // 修改地址
		printf("请输入新的地址:");
		scanf("%s", info->address);
		break;
	case 5: // 修改电话
		printf("请输入新的电话:");
		scanf("%s", info->phone);
		break;
	default:
		printf("输入错误,请重新输入!\n");
		break;
	}

	printf("联系人信息已更新!\n");
}

9. 对所有联系人进行排序

排序原理:qsort (【C语言】qsort详解——能给万物排序的神奇函数-CSDN博客) 。文章开篇的五个排序所用函数比较的指针声明来自于此,足以看到 qsort 函数的强大了吧。

//对所有联系人进行排序
int compareName(const void* a, const void* b) {
	return strcmp(((Information*)a)->name, ((Information*)b)->name);
}

int compareAge(const void* a, const void* b) {
	return ((Information*)a)->age - ((Information*)b)->age;
}

int compareGender(const void* a, const void* b) {
	return strcmp(((Information*)a)->gender, ((Information*)b)->gender);
}

int compareAddress(const void* a, const void* b) {
	return strcmp(((Information*)a)->address, ((Information*)b)->address);
}

int comparePhone(const void* a, const void* b) {
	return strcmp(((Information*)a)->phone, ((Information*)b)->phone);
}
	

void SortContacts(Contact* p)
{
	assert(p);
	printf("请选择排序方式:\n");
	printf("1. 姓名\n2. 年龄\n3. 性别\n4. 地址\n5. 电话\n");
	int sortInput;
	printf("请输入数字选择排序依据:");
	scanf("%d", &sortInput);

	switch (sortInput)
	{
		case 1:
			qsort(p->data, p->sz, sizeof(Information), compareName);
			break;
		case 2:
			qsort(p->data, p->sz, sizeof(Information), compareAge);
			break;
		case 3:
			qsort(p->data, p->sz, sizeof(Information), compareGender);
			break;
		case 4:
			qsort(p->data, p->sz, sizeof(Information), compareAddress);
			break;
		case 5:
			qsort(p->data, p->sz, sizeof(Information), comparePhone);
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
	}
	ShowContacts(p);
}

10. 清空所有联系人信息

 emptyContact 函数属于临时想到,还没测试,可自行添加。

//清空所有联系人
void emptyContact(Contact* pc)
{
	char name[NAME_MAX];
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
	printf("删除成功\n");
 
}

三、完整代码及部分功能展示

代码托管地址:简单的通讯录 · 2f94fc2 · 黄灿灿/C语言 - Gitee.com

1. Contacts.h

#pragma once

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

#define number 20
#define name_max 10
#define gender_max 5
#define address_max 15
#define phone_max 12

typedef struct Information		//Information:信息
{
	char name[name_max];		//name:姓名
	int age;					//age:年龄
	char gender[gender_max];	//gender:性别
	char address[address_max];	//address:地址
	char phone[phone_max];		//phone:电话
}Information;

typedef struct Contact
{
	Information data[number];//存放20个人的信息		number:数量		data:数据
	int sz;//当前已经放的信息的个数
}Contact;

void initialize(Contact* p);//初始化

void AddContacts(Contact* p);//增加联系人

void DeleteContacts(Contact* p);//删除指定联系人

void SearchContacts(const Contact* p);//查找联系人

void ModifyContacts(Contact* p);//修改联系人

void ShowContacts(const Contact* p);//显示通讯录信息

void SortContacts(Contact* p);//对联系人排序


//排序所用函数比较的指针
int compareName(const void* a, const void* b);
int compareAge(const void* a, const void* b);
int compareGender(const void* a, const void* b);
int compareAddress(const void* a, const void* b);
int comparePhone(const void* a, const void* b);

2. Contacts.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contacts.h"

void initialize(Contact* p)
{
	assert(p);
	p->sz = 0;
	memset(p->data, 0, sizeof(p->data));
}

void AddContacts(Contact* p)
{
	assert(p);
	if (p->sz == number)
	{
		printf("通讯录已满,无法添加新的联系人!\n");
		return;
	}

	printf("请输入姓名:");
	scanf("%s", &p->data[p->sz].name);
	printf("请输入年龄:");
	scanf("%d", &p->data[p->sz].age);
	printf("请输入性别:");
	scanf("%s", &p->data[p->sz].gender);
	printf("请输入地址:");
	scanf("%s", &p->data[p->sz].address);
	printf("请输入电话:");
	scanf("%s", &p->data[p->sz].phone);

	p->sz++;
}

//查找姓名函数
int lookup_name(const Contact* p, char name[])
{
	assert(p);
	for (int i = 0; i < p->sz; i++)
	{
		if (strcmp(p->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DeleteContacts(Contact* p)
{
	assert(p);
	char name[name_max] = { 0 };
	if (p->sz == 0)
	{
		printf("通讯录是空的,无法进行删除操作!\n");
		return;
	}

	printf("请输入需要删除的联系人的姓名:");
	scanf("%s", name);

	int temp=lookup_name(p, name);
	if (temp == -1)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}

	for (int i = temp; i < p->sz - 1; i++)
	{
		p->data[i] = p->data[i + 1];
	}
	p->sz--;

	printf("删除联系人成功!\n");
}


void SearchContacts(const Contact* p)
{
	assert(p);
	char name[name_max] = { 0 };
	printf("请输入需要查找联系人的姓名:");
	scanf("%s", name);

	int temp = lookup_name(p, name);

	if (temp == -1)
	{
		printf("抱歉,要查找的联系人不存在!\n");
	}
	else
	{
		printf("%-10s\t%-5s\t%-5s\t%-15s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
		printf("%-10s\t%-5d\t%-5s\t%-15s\t%-12s\n", p->data[temp].name, p->data[temp].age, p->data[temp].gender, p->data[temp].address, p->data[temp].phone);
	}
	
}

void ModifyContacts(Contact* p)
{
	assert(p);

	if (p->sz == 0)
	{
		printf("通讯录是空的,无法进行修改操作!\n");
		return;
	}

	char name[name_max] = { 0 };
	printf("请输入需要修改的联系人的姓名:");
	scanf("%s", name);

	int index = lookup_name(p, name);

	if (index == -1)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}

	Information* info = &p->data[index];

	printf("请选择需要修改的信息类型:\n");
	printf("1. 姓名\n2. 年龄\n3. 性别\n4. 地址\n5. 电话\n");
	int modifyInput;
	printf("请输入数字选择修改的信息类型:");
	scanf("%d", &modifyInput);

	switch (modifyInput)
	{
	case 1: // 修改姓名
		printf("请输入新的姓名:");
		scanf("%s", info->name);
		break;
	case 2: // 修改年龄
		printf("请输入新的年龄:");
		scanf("%d", &info->age);
		break;
	case 3: // 修改性别
		printf("请输入新的性别:");
		scanf("%s", info->gender);
		break;
	case 4: // 修改地址
		printf("请输入新的地址:");
		scanf("%s", info->address);
		break;
	case 5: // 修改电话
		printf("请输入新的电话:");
		scanf("%s", info->phone);
		break;
	default:
		printf("输入错误,请重新输入!\n");
		break;
	}

	printf("联系人信息已更新!\n");
}

void ShowContacts(const Contact* p)
{
	assert(p);
	printf("%-10s\t%-5s\t%-5s\t%-15s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	for (int i = 0; i < p->sz; i++)
	{
		printf("%-10s\t%-5d\t%-5s\t%-15s\t%-12s\n", p->data[i].name, p->data[i].age, p->data[i].gender, p->data[i].address, p->data[i].phone);
	}
}



int compareName(const void* a, const void* b) {
	return strcmp(((Information*)a)->name, ((Information*)b)->name);
}

int compareAge(const void* a, const void* b) {
	return ((Information*)a)->age - ((Information*)b)->age;
}

int compareGender(const void* a, const void* b) {
	return strcmp(((Information*)a)->gender, ((Information*)b)->gender);
}

int compareAddress(const void* a, const void* b) {
	return strcmp(((Information*)a)->address, ((Information*)b)->address);
}

int comparePhone(const void* a, const void* b) {
	return strcmp(((Information*)a)->phone, ((Information*)b)->phone);
}
	

void SortContacts(Contact* p)
{
	assert(p);
	printf("请选择排序方式:\n");
	printf("1. 姓名\n2. 年龄\n3. 性别\n4. 地址\n5. 电话\n");
	int sortInput;
	printf("请输入数字选择排序依据:");
	scanf("%d", &sortInput);

	switch (sortInput)
	{
		case 1:
			qsort(p->data, p->sz, sizeof(Information), compareName);
			break;
		case 2:
			qsort(p->data, p->sz, sizeof(Information), compareAge);
			break;
		case 3:
			qsort(p->data, p->sz, sizeof(Information), compareGender);
			break;
		case 4:
			qsort(p->data, p->sz, sizeof(Information), compareAddress);
			break;
		case 5:
			qsort(p->data, p->sz, sizeof(Information), comparePhone);
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
	}
	ShowContacts(p);
}

3. Contacts_text.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Contacts.h"//Contacts:通讯录

void menu()
{
	printf("*********************************************\n");//add:增加
	printf("**       1.add             2.delete        **\n");//delete:删除
	printf("**       3.search          4.modify        **\n");//search:搜索	
	printf("**       5.show            6.sort          **\n");//modify:修改	
	printf("**                0.exits                  **\n");//show:显示
	printf("*********************************************\n");//sort:排序
	//exit:退出
}

enum pick				//pick:选择
{
	exits = 0,
	add,
	delete,
	search,
	modify,
	show,
	sort
};

int main()
{
	int input = 0;						//input:输入
	Contact temp;						//temp:临时
	initialize(&temp);					//initialize:初始化
	do
	{
		menu();							//menu:菜单
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case add:
			AddContacts(&temp);
			break;
		case delete:
			DeleteContacts(&temp);
			break;
		case search:
			SearchContacts(&temp);
			break;
		case modify:
			ModifyContacts(&temp);
			break;
		case show:
			ShowContacts(&temp);
			break;
		case sort:
			SortContacts(&temp);
			break;
		case exits:
			printf("已退出通讯录!\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);

	return 0;
}

4. 效果展示: 

四、动态升级版通讯录展示

代码托管地址:通讯录动态升级版 · 0f0b02c · 黄灿灿/C语言 - Gitee.com

1. Contacts_plus.h

#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#define DEFAULT_SZ 20
#define INC_SZ 10
#define name_max 10
#define gender_max 5
#define address_max 15
#define phone_max 12

typedef struct Information {
    char name[name_max];   // name: 姓名
    int age;               // age: 年龄
    char gender[gender_max]; // gender: 性别
    char address[address_max]; // address: 地址
    char phone[phone_max];    // phone: 电话
} Information;

typedef struct Contact {
    Information* data;      // 动态分配的数组,存放联系人信息
    int sz;                 // 当前已经存放的信息的个数
    int capacity;           // 数组的最大容量
} Contact;

// 初始化通讯录
void InitContact(Contact* p);

// 销毁通讯录
void DestroyContact(Contact* p);

// 检查并扩大通讯录容量
void check_capacity(Contact* p);

// 添加联系人
void AddContact(Contact* p);

// 删除联系人
void DeleteContact(Contact* p);

// 搜索联系人
void SearchContacts(const Contact* p);

// 修改联系人信息
void ModifyContact(Contact* p);

// 显示通讯录信息
void ShowContacts(const Contact* p);

// 对联系人排序
void SortContacts(Contact* p);

// 字符串比较函数
int compareStr(const void* a, const void* b);

// 整数比较函数
int compareInt(const void* a, const void* b);

// 通用比较函数
int compare(const void* a, const void* b, int (*cmp)(const void*, const void*));

2. Contacts_plus.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contacts_plus.h"

// 初始化通讯录
void InitContact(Contact* p) 
{
    assert(p);
    p->sz = 0;
    p->capacity = DEFAULT_SZ;
    p->data = (Information*)calloc(p->capacity, sizeof(Information));

    if (p->data == NULL) 
    {
        perror("InitContact::calloc");
        exit(EXIT_FAILURE);
    }
}

// 销毁通讯录
void DestroyContact(Contact* p) 
{
    free(p->data);
    p->data = NULL;
    p->capacity = 0;
    p->sz = 0;
}

// 检查并扩大通讯录容量
void check_capacity(Contact* p) 
{
    assert(p);
    if (p->sz == p->capacity) 
    {
        Information* newData = (Information*)realloc(p->data, (p->capacity + INC_SZ) * sizeof(Information));

        if (newData == NULL) 
        {
            perror("check_capacity::realloc");
            exit(EXIT_FAILURE);
        }

        p->data = newData;
        p->capacity += INC_SZ;
    }
}

// 添加联系人
void AddContact(Contact* p) 
{
    assert(p);
    check_capacity(p);

    printf("请输入名字:");
    scanf("%s", p->data[p->sz].name);
    printf("请输入年龄:");
    scanf("%d", &(p->data[p->sz].age));
    printf("请输入性别:");
    scanf("%s", p->data[p->sz].gender);
    printf("请输入地址:");
    scanf("%s", p->data[p->sz].address);
    printf("请输入电话:");
    scanf("%s", p->data[p->sz].phone);

    p->sz++;
}

// 删除联系人
void DeleteContact(Contact* p) 
{
    assert(p);
    char name[name_max] = { 0 };

    if (p->sz == 0) 
    {
        printf("通讯录是空的,无法进行删除操作!\n");
        return;
    }

    printf("请输入需要删除的联系人的姓名:");
    scanf("%s", name);

    int index = -1;
    for (int i = 0; i < p->sz; i++) 
    {
        if (strcmp(p->data[i].name, name) == 0) 
        {
            index = i;
            break;
        }
    }

    if (index == -1) 
    {
        printf("要删除的联系人不存在!\n");
        return;
    }

    for (int i = index; i < p->sz - 1; i++) 
    {
        p->data[i] = p->data[i + 1];
    }
    p->sz--;

    printf("删除联系人成功!\n");
}

//查找姓名函数
int lookup_name(const Contact* p, char name[])
{
    assert(p);
    for (int i = 0; i < p->sz; i++)
    {
        if (strcmp(p->data[i].name, name) == 0)
        {
            return i;
        }
    }
    return -1;
}

// 搜索联系人
void SearchContacts(const Contact* p)
{
    assert(p);
    char name[name_max] = { 0 };
    printf("请输入需要查找联系人的姓名:");
    scanf("%s", name);

    int temp = lookup_name(p, name);

    if (temp == -1)
    {
        printf("抱歉,要查找的联系人不存在!\n");
    }
    else
    {
        printf("%-10s\t%-5s\t%-5s\t%-15s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
        printf("%-10s\t%-5d\t%-5s\t%-15s\t%-12s\n", p->data[temp].name, p->data[temp].age, p->data[temp].gender, p->data[temp].address, p->data[temp].phone);
    }

}

// 修改联系人信息
void ModifyContact(Contact* p) 
{
    assert(p);

    if (p->sz == 0) 
    {
        printf("通讯录是空的,无法进行修改操作!\n");
        return;
    }

    char name[name_max] = { 0 };
    printf("请输入需要修改的联系人的姓名:");
    scanf("%s", name);

    int index = -1;
    for (int i = 0; i < p->sz; i++) 
    {
        if (strcmp(p->data[i].name, name) == 0) 
        {
            index = i;
            break;
        }
    }

    if (index == -1) 
    {
        printf("要修改的联系人不存在!\n");
        return;
    }

    Information* info = &p->data[index];

    printf("请选择需要修改的信息类型:\n");
    printf("1. 姓名\n2. 年龄\n3. 性别\n4. 地址\n5. 电话\n");
    int modifyInput;
    printf("请输入数字选择修改的信息类型:");
    scanf("%d", &modifyInput);

    switch (modifyInput) 
    {
    case 1: // 修改姓名
        printf("请输入新的姓名:");
        scanf("%s", info->name);
        break;
    case 2: // 修改年龄
        printf("请输入新的年龄:");
        scanf("%d", &info->age);
        break;
    case 3: // 修改性别
        printf("请输入新的性别:");
        scanf("%s", info->gender);
        break;
    case 4: // 修改地址
        printf("请输入新的地址:");
        scanf("%s", info->address);
        break;
    case 5: // 修改电话
        printf("请输入新的电话:");
        scanf("%s", info->phone);
        break;
    default:
        printf("输入错误,请重新输入!\n");
        break;
    }

    printf("联系人信息已更新!\n");
}

// 显示通讯录信息
void ShowContacts(const Contact* p) 
{
    assert(p);
    printf("%-10s\t%-5s\t%-5s\t%-15s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
    for (int i = 0; i < p->sz; i++) 
    {
        printf("%-10s\t%-5d\t%-5s\t%-15s\t%-12s\n",
            p->data[i].name, p->data[i].age,
            p->data[i].gender, p->data[i].address,
            p->data[i].phone);
    }
}

// 对联系人排序
void SortContacts(Contact* p) 
{
    assert(p);
    printf("请选择排序方式:\n");
    printf("1. 姓名\n2. 年龄\n3. 性别\n4. 地址\n5. 电话\n");
    int sortInput;
    printf("请输入数字选择排序依据:");
    scanf("%d", &sortInput);

    switch (sortInput) 
    {
    case 1:
        qsort(p->data, p->sz, sizeof(Information), (int (*)(const void*, const void*))compareStr);
        break;
    case 2:
        qsort(p->data, p->sz, sizeof(Information), (int (*)(const void*, const void*))compareInt);
        break;
    case 3:
        qsort(p->data, p->sz, sizeof(Information), (int (*)(const void*, const void*))compareStr);
        break;
    case 4:
        qsort(p->data, p->sz, sizeof(Information), (int (*)(const void*, const void*))compareStr);
        break;
    case 5:
        qsort(p->data, p->sz, sizeof(Information), (int (*)(const void*, const void*))compareStr);
        break;
    default:
        printf("输入错误,请重新输入!\n");
        break;
    }
    ShowContacts(p);
}

// 字符串比较函数
int compareStr(const void* a, const void* b) 
{
    return strcmp(*(char**)a, *(char**)b);
}

// 整数比较函数
int compareInt(const void* a, const void* b) 
{
    return *(int*)a - *(int*)b;
}

// 通用比较函数
int compare(const void* a, const void* b, int (*cmp)(const void*, const void*)) 
{
    return cmp(a, b);
}

3. Contacts_text_plus.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contacts_plus.h"

int main() 
{
    int input = 0;
    Contact temp;
    InitContact(&temp);

    do {
        printf("*********************************************\n");
        printf("**       1.add             2.delete        **\n");
        printf("**       3.search          4.modify        **\n");
        printf("**       5.show            6.sort          **\n");
        printf("**                0.exit                   **\n");
        printf("*********************************************\n");

        printf("请选择:");
        scanf("%d", &input);

        switch (input) 
        {
        case 1:
            AddContact(&temp);
            break;
        case 2:
            DeleteContact(&temp);
            break;
        case 3:
            SearchContacts(&temp); 
            break;
        case 4:
            ModifyContact(&temp);
            break;
        case 5:
            ShowContacts(&temp);
            break;
        case 6:
            SortContacts(&temp);
            break;
        case 0:
            printf("已退出通讯录!\n");
            break;
        default:
            printf("输入错误,请重新输入!\n");
            break;
        }
    } while (input != 0);

    DestroyContact(&temp);
    return 0;
}

升级版的功能就不演示了,更多更全面的功能等你来发现!

五、总结

通过这个项目,不仅巩固了C语言的基础知识,还学会了如何构建一个实用的应用程序。如果可以自行轻松实现以上通讯录的功能,就可以进阶数据结构了!做个铺垫:数据结构的核心一定一定要学会画图观察的思想!!!在未来的学习和工作中,这些经验将是非常宝贵的。希望读者也能从这个项目中学到有用的东西,并尝试自己动手实践。

共勉

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小米里的大麦

您的支持是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值