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语言版本)

动态通讯录(C语言版本)

之前的版本静态存储的通讯录(C语言实现)

如果不懂得同学可以回顾一下这个博客,里面的知识点讲的很详细,特别适合新手入门。

动态通讯录更改部分(在静态版本上进行更改)

结构体的变动:

//一个人的信息
typedef struct PeoInfo
{
	char name[20];
	char sex[5];
	char tele[12];
	int age;
	char addr[30];
}PeoInfo;
通讯录(静态版本)
//typedef struct Contact
//{
//	PeoInfo data[100];
//	int sz;
//}Contact;

//动态版本
typedef struct Contact
{
	struct PeoInfo* data;
	int sz;//已经放了几个
	int capacity;//现在的容量
}Contact;

因为静态版本只能给出固定的容量,超出容量就不可以扩容,这就很不人性,如果给的空间太大就过于浪费,但是给的太少又不符合实际应用,因为随机性很多。
VS不支持给数组一个变量的下标比如 :arr[n],像这样使用只能在C99平台下运行,不过大多数OJ平台下都可以运行(面试或者考试可以放心)。

解释:

我们只给了一个struct PeoInfo* data 这是一个结构体指针的形式,之后可以用malloc进行扩容。

初始化通讯录

#define DEFAULT 3//应该在contact.h文件中,放到这里方便观看。
//静态版本
//void InitContact(Contact* pc)
//{
//	pc->sz = 0;
//	memset(pc->data, 0, 100 * sizeof(PeoInfo));
//}

//动态版本
void InitContact(Contact* pc)
{
	assert(pc);
	pc->data = (PeoInfo*)malloc(DEFAULT*sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContact");
		return;
	}
	pc->capacity = DEFAULT;
	pc->sz = 0;
}

解释:

我们直接在pc->data指针所指的位置上开辟空间,记住不是在pc->data上开辟空间,因为pc->data只是一个结构体指针,开辟的大小是个人信息结构体大小的三倍(default=3),以后要开辟空间一定要检验是否开辟成功,没有成功要perror,给出标记,如果开辟成功就可以给容量赋值了,并且给sz初始化为0.

增加联系人信息

//增加联系人(静态)
//void AddContact(Contact* pc)
//{
//	if (pc->sz == MAX)
//	{
//		printf("已经满了\n");
//		return;
//	}
//	else
//	{
//		printf("请输入名字;》\n");
//		scanf("%s", pc->data[pc->sz].name);
//		printf("请输入性别:》\n");
//		scanf("%s", pc->data[pc->sz].sex);
//		printf("请输入年龄:》\n");
//		scanf("%d", &(pc->data[pc->sz].age));
//		printf("请输入电话:》\n");
//		scanf("%s", pc->data[pc->sz].tele);
//		printf("请输入地址:》\n");
//		scanf("%s", pc->data[pc->sz].addr);
//		pc->sz++;
//		printf("成功增加联系人\n");
//
//
//	}
//}

//检查容量
int CheckCapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		printf("已经满了\n");
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, 2 * pc->capacity * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity *= 2;
			printf("增容成功\n");
			return 1;
		}
		else
		{
			perror("ADDContact");
			return 0;
		}
	}
	else
		return 1;
}
//动态增加
void AddContact(Contact* pc)
{
	assert(pc);
	if(CheckCapacity(pc))
	{

		printf("请输入名字;》\n");
		scanf("%s", pc->data[pc->sz].name);
		printf("请输入性别:》\n");
		scanf("%s", pc->data[pc->sz].sex);
		printf("请输入年龄:》\n");
		scanf("%d", &(pc->data[pc->sz].age));
		printf("请输入电话:》\n");
		scanf("%s", pc->data[pc->sz].tele);
		printf("请输入地址:》\n");
		scanf("%s", pc->data[pc->sz].addr);
		pc->sz++;
		printf("成功增加联系人\n");
	}
	else
	{
		return;
	}
}

解释:

静态增加信息因为容量有限,容量满了之后无法增加所以只需要在函数最早加一个判断sz是否等于MAX,如果不等于便可以增加,等于的话就会提示。
动态版本增加信息的函数前面也要有一个检验容量的信息如果不满可以进行增加,满了呢当然也不会退出,会直接进行扩容。因为后面也会用到检查容量的函数所以我直接将其封装成一个小函数,随用随取很方便。其他的就和静态一样增加个人信息即可,但是再也不会因为容量满了而退出程序了。

销毁整个通讯录

//销毁整个顺序表
void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

解释:

因为是顺序表,而且动态开辟了空间,使用完之后一定要释放,不然会把内存空间浪费掉使电脑性能下降的。
在这里也要声明pc->data开辟的空间被free之后,也一定要pc->data = NULL,因为会有野指针的风险,甚至你下次调用pc->data打印信息还能有一定几率打印出之前存的消息这是因为栈帧的原因,千万不要有侥幸心理,使用完开辟分空间之后一定要free和NULL。

修改好的主函数

#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;
	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 SORT:
			SortContact(&con);
			break;
		case EXIT:
			DestroyContact(&con);
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}

修改点:

在这里最重要的是在退出选项的下面增加了一个DestroyContact(&con);函数,这是因为使用完动态分配的空间一定要释放。
还增加了枚举,这是因为你给出菜单选项是,别人阅读你的代码一是难免会忘记所以总要翻看查询会有很多不便,但是这里增加了枚举可以直接通过枚举来调用。

枚举的解释:

枚举如果你没有给里面的量赋值的话,他会主动给你赋值,从0,1,2…一直往下,当然你也可以直接赋值,我在这里没有赋值所以是按照 菜单的复制情况给他们拍的顺序(EXIT放在了最开始的位置也就是0)。

预告

之后还会有文件的版本敬请期待!也希望同学们要复习好知识哦。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-30 00:33:07  更:2022-09-30 00:35:06 
 
开发: 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 3:16:06-

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