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

news2024/11/14 16:35:53

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

共勉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1995216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

教育法、义务教育法、教师法、未成年人保护法、预防未成年人犯罪法、学生伤害事故处理办法

《中华人民共和国教育法》 《中华人民共和国义务教育法》 《中华人民共和国教师法》 《中华人民共和国未成年人保护法》 《中华人民共和国预防未成年人犯罪法》 《学生伤害事故处理办法》

C++:string

1.STL简介 STL&#xff08;standard template library标准模版库&#xff09;&#xff0c;是c标准库的重要组成部分&#xff0c;是一个包罗数据结构与算法的软件框架。 STL有很多版本&#xff0c;我们学习STL要阅读部分源代码&#xff0c;主要参考SGI版本。 STL的六大组件&a…

Volana:一款基于Go开发的Shell命令代码混淆工具

关于Volana Volana是一款功能强大的Shell命令代码混淆工具&#xff0c;该工具基于Go语言开发&#xff0c;可以帮助广大研究人员实现对Shell命令或脚本代码的混淆处理。 在红队测试过程中&#xff0c;隐蔽性是非常重要的一个方面&#xff0c;许多基础设施会记录命令并实时将其发…

Java 中的泛型 集合(List,Set) Map

泛型的本质是参数化类型,即允许在编译时对集合进行类型检查,从而避免安全问题,提高代码的复用性 泛型的具体定义与作用 定义:泛型是一种在编译阶段进行类型检查的机制,它允许在类,方法,接口后通过<> 来声明类型参数.这些参数在编译时会被具体的类型替换.java在运行时,会通…

Java生成Word->PDF->图片:基于poi-tl 进行word模板渲染

文章目录 引言I Java生成Word、PDF、图片文档获取标签渲染数据生成文档案例II 工具类封装2.1 word 渲染和word 转 pfd2.2 pdf转成一张图片III poi-tl(word模板渲染) 标签简介文本标签{{var}}图片标签表格标签引用标签IV poi-tl提供了类 Configure 来配置常用的设置标签类型前后…

dwg图纸识别,提取建筑外轮廓坐标数据

1.业务流程说明 目的是通过dwg图纸&#xff0c;在网页端绘制出一个包括建筑外轮了的白模。为了达到这个目的&#xff0c;我们需要dwg图纸识别&#xff0c;提取到图纸中的建筑外轮廓的坐标数据。 2. 实施步骤 1.1 根据dwg图纸&#xff0c;转换成dxf文件&#xff0c;通过对dxf文…

区域与语言CultureInfo

CultureInfo 类 命名空间: System.Globalization 程序集: System.Globalization.dll 提供有关特定区域性&#xff08;对于非托管代码开发&#xff0c;则称为“区域设置”&#xff09;的信息。 这些信息包括区域性的名称、书写系统、使用的日历、字符串的排序顺序以及对日期…

56 锐键交换机开局

锐键交换机开局 一 锐键视图切换 1 Ruijie> 用户视图 2 Ruijie# 特权模式 3 Ruijie(config)# 全局配置模式 4 Ruijie(config-if-GigabitEthernet 1/1/1)# 接口配置模式 5 Ruijie(config)#show vlan 6 exit (退出) 7 enable(进入)

【电子数据取证】支持最新版微信、企业微信、钉钉等重点应用数据提取分析!

文章关键词&#xff1a;电子数据取证、手机取证、云取证、电子物证、仿真取证 针对取证调查员目前在案件现场无法提取通讯聊天数据的情况&#xff0c;为了更好地适应这一实战需求&#xff0c;龙信科技快速响应对A303“鹰眼”介质快取系统和A315计算机快速采集系统全面升级&…

java10-集合框架

1. 集合的简介 1.1什么是集合 集合Collection&#xff0c;也是一个数据容器&#xff0c;类似于数组&#xff0c;但是和数组是不一样的。集合是一个可变的容器&#xff0c;可以随时向集合中添加元素&#xff0c;也可以随时从集合中删除元素。另外&#xff0c;集合还提供了若干个…

人工智能安全态势和趋势

吴世忠 中工院士 国家保密科技委主任 重大风险隐患呼唤加强安全研究&#xff0c;人工智能面临未来担忧 1 总体态势 1.1 相对于技术发展&#xff0c;安全研究严重滞后 1.2 我国研究十分活跃&#xff0c;论文数量遥遥领先 1.3 影响力美国排名第一&#xff0c;大厂大学作用大 1…

【python】Python操作Redis数据库的详细教程与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

三防平板助力MES系统,实现工厂移动式生产报工

在当今竞争激烈的制造业环境中&#xff0c;提高生产效率、优化生产流程以及实现精准的生产管理已经成为企业生存和发展的关键。 MES系统作为连接企业计划层和控制层的桥梁&#xff0c;在实现生产过程的信息化、数字化和智能化方面发挥着重要作用。与此同时&#xff0c;三防平板…

JNPF快速开发平台助力企业实现工作流自动化

随着企业信息化建设的不断深入&#xff0c;工作流自动化已成为提升企业效率、优化业务流程的关键手段。JNPF快速开发平台凭借其强大的功能和灵活的配置&#xff0c;为众多企业提供了实现工作流自动化的高效解决方案。 关于低代码开发平台的普及应用 随着信息技术的迅猛发展&…

高中数学必修一函数部分重难点(上)

高中数学必修一函数部分重难点&#xff08;上&#xff09; 本文主要引出映射的概念&#xff0c;明确函数即为映射的一种方式&#xff0c;同时本篇叙述了我在初学时的困难点—定义域等以及当时所觉的难题&#xff0c;最后一图为纯手整理的干货&#xff0c;需要可以留下三联自行取…

Swagger 自动生成 Dubbo 服务的接口文档,以及测试调用

1. 概述 在使用 SpringMVC 构建 HTTP API 时&#xff0c;我们可以通过 Swagger 自动生成 HTTP 接口文档&#xff0c;通过 Swagger UI 界面上进行 HTTP 接口调试。如下图所示&#xff1a; Swagger HTTP 界面 秃头提示&#xff1a;对 Swagger 不太了解的胖友&#xff0c;可以去阅…

论文阅读笔记:Semi-Supervised Semantic Segmentation Using Unreliable Pseudo-Labels

论文阅读笔记&#xff1a;Semi-Supervised Semantic Segmentation Using Unreliable Pseudo-Labels 1 背景2 创新点3 方法4 模块4.1 伪标签4.2 使用不可靠的伪标签 5 效果5.1 与SOTA方法对比5.2 消融实验5.3 定性结果 6 结论 论文&#xff1a;https://arxiv.org/pdf/2203.03884…

北京崇文门中医院贾英才主任:战胜头晕,重获“清醒人生”

头晕&#xff0c;这个看似常见却又恼人的症状&#xff0c;常常让患者的生活陷入困境。在北京崇文门中医院&#xff0c;有个叫贾英才的医生&#xff0c;他凭借医术&#xff0c;给不少头晕患者带去了希望。 北京崇文门中医院贾英才主任在医学领域辛勤耕耘多年&#xff0c;对于头晕…

ubuntu20从docker安装到制作自己的镜像使用记录

ubuntu20从docker安装到制作自己的镜像使用记录 第一章&#xff1a;配置环境 1.ubuntu20 2.docker镜像18.04 3.参考&#xff1a;https://www.runoob.com/docker/docker-tutorial.html 第二章&#xff1a;安装docker 一、安装docker 参考1&#xff1a;Ubuntu安装docker并运…

Spring Cloud微服务项目文件上传/下载

在现代的微服务架构中&#xff0c;文件上传与下载是常见的需求&#xff0c;尤其是在需要处理大量文件数据的系统中。Spring Cloud 提供了灵活的工具和组件&#xff0c;使得在微服务中实现文件上传和下载变得高效而简便。 本文博主将详细介绍如何在 Spring Cloud 微服务项目中实…