IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 用C语言实现 静态通讯录+动态通讯录(附上思路+项目展示+源代码) -> 正文阅读

[C++知识库]用C语言实现 静态通讯录+动态通讯录(附上思路+项目展示+源代码)

前言 : 在生活中我们经常会遇到通讯录的使用,比如存进一个新的联系人的信息,或者对其删除,修改,查找;那这些神奇的功能是如何实现的?我们不禁好奇。今天,这篇博文将教会大家实现一个静态的或者动态的通讯录,以后我们就可以靠自己实现一个通讯录啦 ~

1.静态通讯录讲解

1.1 静态通讯录的功能列表的实现(text.c)

1.1.1 菜单的实现

这里我们实现一个简易的功能菜单,运用print语句即可
功能有 1.新增联系人 2.删除联系人 3.查找指定联系人
4.修改指定联系人信息 5.展示目前存入的联系人 6.对联系人按照一定的标准排序 以及 0.退出通讯录

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

}

1.1.2 菜单功能的枚举

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

EXIT 从0开始向下递增,分别对应菜单上的各个功能,目的是为了下面的switch接口能更加方便直观看出各个功能,以防出错。

1.1.3 main函数的实现

这一块我们实现从键盘上输入各个数字代表不同功能,再实现循环输入,
代码如下:

int main()
{
	int input = 0;
	struct Contact 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 EXIT:
			//销毁通讯录
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

1.2 静态通讯录各个函数的声明包含 (contact.h)

1.2.1 #define 定义各个标号以及头文件的引用

#define DEFAULT_SZ 3
#define NAME_MAX 30
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000

分别定义了
默认存放联系人数量为3 (后面动态通讯录会使用到)
名字数组最大长度为 30‘
性别数组最大长度为 5
电话数组最大长度为 15
地址数组最大长度为 30
静态通讯录能存放最大联系人为 1000

头文件的引用:

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

引用整个工程所要使用到的函数头文件,避免重复引用(每个文件前面加上 #include "contact.h),这样就实现所有声明头文件放在一个头文件中,分开管理,提升工程书写效率;

1.2.2 定义联系人信息结构体

struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};

1.2.3定义静态通讯录结构体

// 静态通讯录版本
struct Contact
{
	struct PeoInfo date[MAX];
	int sz;
};

包含了可以存放1000个人信息的联系人结构体以及当前存放进去的有效联系人个数 sz ;

1.2.4 各个功能函数的声明


// 初始化通讯录 
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 DestroyContact(struct Contact* pc);


1.3 功能函数的实现讲解 (contact.c)

1.3.1 静态通讯录初始化函数讲解

 // 静态直接开辟存放1000个人信息的版本
 
void InitContact(struct Contact* pc)
{
	pc->sz = 0; //默认没有信息
	memset(pc->date, 0, MAX * sizeof(struct PeoInfo));
	//memset(pc->date, 0, sizeof(pc->date));
}

结构体传参,传的一般是结构体地址,结构体指针接受,实现对结构体本身的修改 。(传址调用)
初始化有效联系人个数sz为0;
用memset内存设置函数,将1000个联系人信息结构体初始化为0;

1.3.2 Add新增联系人函数的实现讲解

// 静态版本
void Addcontact(struct Contact* pc)
{
	struct Contact tmp = { 0 };
	if (pc->sz == MAX)
	{
		printf("通讯录可用空间已满\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->date[pc->sz].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->date[pc->sz].age));
		printf("请输入性别:>");
		scanf("%s", pc->date[pc->sz].sex);
		printf("请输入电话:>");
		scanf("%s", pc->date[pc->sz].tele);
		printf("请输入地址:>");
		scanf("%s", pc->date[pc->sz].addr);
		printf("添加成功\n");
		pc->sz++;
	}
}

用pc->date[pc->sz].xxx找到各个联系人信息位置,将信息存入
后有效联系人个数sz++;
实现对下一个联系人信息的存放

1.3.3 展示当前存入的联系人信息函数讲解

void ShowContact(struct Contact* pc)
{
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
		"name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->date[i].name,
			pc->date[i].age,
			pc->date[i].sex,
			pc->date[i].tele,
			pc->date[i].addr);
	}
}

printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
“name”, “age”, “sex”, “tele”, “addr”);
实现初始化联系人信息表头的域宽
接下来打印每一个数据即可;

1.3.4 通过姓名查找当前存放进去的联系人信息位置函数实现讲解

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

strcmp库函数实现对字符串的比较,相同的话返回数字0;
返回数字0即代表查找成功,此时返回位置 i 即可;
查找不成功返回-1;

1.3.5 删除指定联系人函数实现讲解

void DelContact(struct Contact* pc)
{
	if (pc->sz == 0) //有效联系人个数为0
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[NAME_MAX] = {0};
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	// 查找
	int pos=FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("指定的联系人不存在\n");
	}
	else
	{
		// 删除
		//将数组中要被删除的元素后面的元素相应向前放
		int j = 0;
		for (j = pos; j<pc->sz-1; j++)
		{
			pc->date[j] = pc->date[j + 1];
		}
		pc->sz--;
		printf("删除成功\n");
	}
}

相应讲解在代码中以注释形式给出;

1.3.6 查找指定联系人函数实现讲解

void SearchContact(const struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
			"name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->date[pos].name,
			pc->date[pos].age,
			pc->date[pos].sex,
			pc->date[pos].tele,
			pc->date[pos].addr);
	}
}

查找成功的话将此位置(pos)打印出即可,格式和增加联系人函数的类似;

1.3.7 修改指定联系人信息函数实现讲解

void ModifyContact(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要修改的联系人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的联系人不存在\n");
	}
	else
	{
		printf("请输入新的名字:>");
		scanf("%s", pc->date[pos].name);
		printf("请输入新的年龄:>");
		scanf("%d", &(pc->date[pos].age));
		printf("请输入新的性别:>");
		scanf("%s", pc->date[pos].sex);
		printf("请输入新的电话:>");
		scanf("%s", pc->date[pos].tele);
		printf("请输入新的地址:>");
		scanf("%s", pc->date[pos].addr);
		printf("修改成功\n");
	}
}

查找指定联系人成功的话,将此位置(pos)对应的联系人信息修改即可,
格式依旧和新增联系人函数类似;

到此为止,静态通讯录各个模块实现讲解基本完毕;
我们大致可以看一下效果 ;

2.动态通讯录实现讲解

动态通讯录与静态通讯录实现上大致相同,我们就把不同的地方区分出来进行详细讲解 :
动态通讯录与静态通讯录区别就在于: 静态通讯录一开始就创建好一个可以存放1000个人信息的空间,存不满的话对内存浪费就会比较大;
而动态通讯录可以实现随着放入的联系人信息的增多而相应的增加内存空间,用malloc函数实现,这样对内存空间的浪费就避免了,是更好的实现方法,下面我们就对动态通讯录进行讲解 :

2.1 动态通讯录结构体实现

//动态通讯录版本
struct Contact
{
	struct PeoInfo* date;
	int sz;
	int capacity;
};

实现一个 date结构体指针,指向联系人信息结构体
实现一个当前有效联系人信息个数 sz
实现一个当前通讯录最大联系人容量 capacity

2.2 初始化动态通讯录函数讲解

// 动态开辟的版本
void InitContact(struct Contact* pc)
{
	pc->sz = 0;
	pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
	pc->capacity = DEFAULT_SZ; // 3
}

有效联系人个数sz制为0;
在这里插入图片描述

pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));

malloc函数实现一开始动态内存开辟3个联系人空间大小,写法上
DEFAULT_SZ (元素个数:3)* sizeof(struct PeoInfo)(每个元素的大小)
返回开辟空间的地址,date结构体指针来接收;

一开始最大容量capacity制为 3 ;

2.3 动态通讯录新增联系人函数实现讲解

动态通讯录与静态通讯录不同就在新增联系人函数实现方式上有所变化,
其他函数一致保持不变 ;

 // 动态版本
void Addcontact(struct Contact* pc)
{
	// 空间满了就扩容
	if (pc->sz == pc->capacity)
	{
		struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
		if (ptr != NULL) // 扩容成功的话 
		{
			pc->date = ptr; // 扩容出来的新地址 ptr 赋给 date 
			pc->capacity += 2; // 相应最大容量 +2 
			printf("扩容成功\n");
		}
		else
		{
			return; // 返回空指针 null 则 return 
		}
	}
	// 录入新增人的信息
	// 实现上和静态通讯录无异
	printf("请输入名字:>");
	scanf("%s", pc->date[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->date[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->date[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->date[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->date[pc->sz].addr);
	printf("添加成功\n");
	pc->sz++;
}
struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));

扩容代码讲解:如果空间满了就用realloc函数实现扩容,realloc函数的意思是扩容为xx,不是扩容xx ;
realloc函数传入需要扩容的地址dete,扩容一次扩容+2个联系人空间,pc->capacity + 2,每个联系人大小为 sizeof(struct PeoInfo) ;
返回的地址强制类型转换为 (struct PeoInfo*)
存放在结构体指针 ptr 中 ;
其他讲解在代码中以注释形式给出 ;

2.4 退出(销毁动态开辟的内存空间)通讯录函数实现讲解

void DestroyContact(struct Contact* pc)
{
	free(pc->date);
	pc->date = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}

在这里插入图片描述
释放+制空:
free(pc->date);
pc->date = NULL;
实现避免对内存空间的浪费使用 ;
pc->sz = 0;
pc->capacity = 0;
将有效联系人个数以及最大联系人个数制为 0 ;
退出通讯录 ;

3.整体工程源代码展示

3.1 text.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

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

}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};
int main()
{
	int input = 0;
	struct Contact 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 EXIT:
			//销毁通讯录
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

3.2 contact .c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

 静态直接开辟存放1000个人信息的版本
 
//void InitContact(struct Contact* pc)
//{
//	pc->sz = 0; //默认没有信息
//	memset(pc->date, 0, MAX * sizeof(struct PeoInfo));
//	//memset(pc->date, 0, sizeof(pc->date));
//}


//动态开辟的版本
void InitContact(struct Contact* pc)
{
	pc->sz = 0;
	pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
	pc->capacity = DEFAULT_SZ; // 3
}

// 静态版本
void Addcontact(struct Contact* pc)
{
	struct Contact tmp = { 0 };
	if (pc->sz == MAX)
	{
		printf("通讯录可用空间已满\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", pc->date[pc->sz].name);
		printf("请输入年龄:>");
		scanf("%d", &(pc->date[pc->sz].age));
		printf("请输入性别:>");
		scanf("%s", pc->date[pc->sz].sex);
		printf("请输入电话:>");
		scanf("%s", pc->date[pc->sz].tele);
		printf("请输入地址:>");
		scanf("%s", pc->date[pc->sz].addr);
		printf("添加成功\n");
		pc->sz++;
	}
}
// 动态版本
//void Addcontact(struct Contact* pc)
//{
//	 空间满了就扩容
//	if (pc->sz == pc->capacity)
//	{
//		struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
//		if (ptr != NULL)
//		{
//			pc->date = ptr;
//			pc->capacity += 2;
//			printf("扩容成功\n");
//		}
//		else
//		{
//			return;
//		}
//	}
//	 录入新增人的信息
//	printf("请输入名字:>");
//	scanf("%s", pc->date[pc->sz].name);
//	printf("请输入年龄:>");
//	scanf("%d", &(pc->date[pc->sz].age));
//	printf("请输入性别:>");
//	scanf("%s", pc->date[pc->sz].sex);
//	printf("请输入电话:>");
//	scanf("%s", pc->date[pc->sz].tele);
//	printf("请输入地址:>");
//	scanf("%s", pc->date[pc->sz].addr);
//	printf("添加成功\n");
//	pc->sz++;
//}
void ShowContact(struct Contact* pc)
{
	int i = 0;
	printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
		"name", "age", "sex", "tele", "addr");
	for (i = 0; i < pc->sz; i++)
	{
		//打印每一个数据
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->date[i].name,
			pc->date[i].age,
			pc->date[i].sex,
			pc->date[i].tele,
			pc->date[i].addr);
	}
}
int FindContactByName(const struct Contact* pc, const char* name)
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->date[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DelContact(struct Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	char name[NAME_MAX] = {0};
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	// 查找
	int pos=FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("指定的联系人不存在\n");
	}
	else
	{
		// 删除
		//将数组中要被删除的元素后面的元素相应向前放
		int j = 0;
		for (j = pos; j<pc->sz-1; j++)
		{
			pc->date[j] = pc->date[j + 1];
		}
		pc->sz--;
		printf("删除成功\n");
	}
}

void SearchContact(const struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要查找的联系人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("查无此人\n");
	}
	else
	{
		printf("%15s\t%5s\t%8s\t%15s\t%30s\n",
			"name", "age", "sex", "tele", "addr");
		printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
			pc->date[pos].name,
			pc->date[pos].age,
			pc->date[pos].sex,
			pc->date[pos].tele,
			pc->date[pos].addr);
	}
}

void ModifyContact(struct Contact* pc)
{
	char name[NAME_MAX] = { 0 };
	printf("请输入要修改的联系人的名字:>");
	scanf("%s", name);
	int pos = FindContactByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的联系人不存在\n");
	}
	else
	{
		printf("请输入新的名字:>");
		scanf("%s", pc->date[pos].name);
		printf("请输入新的年龄:>");
		scanf("%d", &(pc->date[pos].age));
		printf("请输入新的性别:>");
		scanf("%s", pc->date[pos].sex);
		printf("请输入新的电话:>");
		scanf("%s", pc->date[pos].tele);
		printf("请输入新的地址:>");
		scanf("%s", pc->date[pos].addr);
		printf("修改成功\n");
	}
}

void DestroyContact(struct Contact* pc)
{
	free(pc->date);
	pc->date = NULL;
	pc->sz = 0;
	pc->capacity = 0;
}




3.3 contact.h

#pragma once

#define DEFAULT_SZ 3 
#define NAME_MAX 30
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
#define MAX 1000

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

struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
};

// 静态通讯录版本
//struct Contact
//{
//	struct PeoInfo date[MAX];
//	int sz;
//};

//动态通讯录版本
struct Contact
{
	struct PeoInfo* date;
	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 DestroyContact(struct Contact* pc);






4.尾声

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-01 16:38:20  更:2021-10-01 16:39:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 18:33:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码