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语言实训通讯录(静态和动态版本)

作者:旧梦拾遗186

专栏:C语言编程----小比特成长日记

相关链接:自定义类型下(枚举、联合)C语言

?

每日励志:

改变,永远不嫌晚。无论你是几岁,也无论你目前所处的境况有多糟,只要立定目标、一步一步往前走,人生随时都有翻盘的可能性。

目录

一.前言:

二.设计要求:

三.准备工作:

四. 静态通讯录:

test.c

contact.h

contact.c?

?编辑

五.动态版通讯录:

test.c?

contact.h

?contact.c

六.总体效果:?

1.增加

2.删除

3.查找

?4.修改

5.展示

6.排序

结语:?


一.前言:

前面我们对c语言有了系统性的学习和了解,今天小编手把手教大家如何使用c语言实现静态和动态版本的通讯录。

二.设计要求:

我们设计的通讯录必须符合以下几点要求:

1.使用静态内存开辟通讯录,通讯录的初始默认大小为 1000联系人类型。

? ? 使用动态内存开辟通讯录,通讯录的初始默认大小为 3 个联系人类型。
2.联系人的信息包括:姓名、性别、年龄、电话、住址。
3.通讯录拥有添加联系人功能。
4.通讯录拥有删除联系人功能。
5.通讯录拥有按姓名查找联系人并输出此联系人所有信息的功能。
6.通讯录拥有修改联系人信息的功能。
7.通讯录拥有按年龄排序的功能。
8.通讯录拥有清空所有联系人信息、内存的功能。
9.通讯录拥有显示通讯录的功能。

三.准备工作:

静态通讯录和动态通讯录,需要的布局基本相同

采用,模块化的方式我们需要创建test.c,contact.c和contact.c文件

其中test.c是主函数的入口,contact.c是函数功能的实现,contact.c是函数声明,结构体声明和头文件的使用。

四. 静态通讯录:

test.c

主函数中我们通过do?while循环和switch?case两种语法实现了基本的使用逻辑,同时,我们在设计时可能会忘记了数字所代表的功能,所以我们采用枚举类型来解决这个问题使我们的设计更加方便。枚举不是我们今天所要讲的重点,想要更深入了解枚举可点击相关链接(

自定义类型下(枚举、联合)C语言

#include "contact.h"
//
//1. 静态的版本



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

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");
}

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:
			
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);

	return 0;
}

主函数中我们通过do?while循环和switch?case两种语法实现了基本的使用逻辑,同时,我们在设计时可能会忘记了数字所代表的功能,所以我们采用枚举类型来解决这个问题使我们的设计更加方便。枚举不是我们今天所要讲的重点,想要更深入了解枚举可点击相关链接(

自定义类型下(枚举、联合)C语言

contact.h

分析:contact.h就是对通讯录结构体的设计以及函数功能的声明,以及一些头文件的引入,同时,对于一些变量,为了方便修改,我们采用#define来进行定义。对于人的信息,我们使用结构体定义了名字,年龄,姓名,电话,地址等信息。然后我们还需要存放起来,定义另一个结构体,包括存放信息的数组可以理解为结构体数组,以及当前的个数。以及对功能函数的声明。

#define _CRT_SECURE_NO_WARNINGS


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


#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;


typedef struct Contact
{
	PeoInfo data[MAX];
    int count;
}Contact;


//初始化
void InitContact(Contact* pc);

//添加
void AddContact(Contact* pc);

//打印
void ShowContact(const Contact* pc);

//删除
void DelContact(Contact* pc);

//查找
void SearchContact(Contact* pc);

//修改
void ModifyContact(Contact*pc);

//清空
void ClearContact(Contact* pc);

//排序
void SortContact(Contact* pc);

?

分析:contact.h就是对通讯录结构体的设计以及函数功能的声明,以及一些头文件的引入,同时,对于一些变量,为了方便修改,我们采用#define来进行定义。对于人的信息,我们使用结构体定义了名字,年龄,姓名,电话,地址等信息。然后我们还需要存放起来,定义另一个结构体,包括存放信息的数组可以理解为结构体数组,以及当前的个数。以及对功能函数的声明。

contact.c?

分析:contact.c其实就是对contact.h中声明的各种函数包括增,删,查,加,展示等等的实现还有一些函数没有在contact.h中声明,他们是专门用于某些函数的特殊功能

例如static int FindByName(Contact* pc, char name[])函数是为了通过姓名查找是否存在此人,如果存在则返回那个人的下标在删除函数中进行删除。

#define _CRT_SECURE_NO_WARNINGS

#include "contact.h"
void InitContact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	memset(pc->data, 0, sizeof(pc->data));
}

void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->count == MAX)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}
	printf("请输入名字:");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:");
	scanf("%d", &pc->data[pc->count].age);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入地址:");
	scanf("%s", pc->data[pc->count].addr);

	pc->count++;
	printf("增加成功\n");
}



void ShowContact(const Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n","名字","年龄","性别","电话","地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-3d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name, pc->data[i].age,
			pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

static int FindByName(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };	
	assert(pc);
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空,没有信息可以删除\n");
		return;
	}
	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	//查找
	int pos = FindByName(pc, name);

	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//删除
	for (i = pos; i < pc->count-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->count--;
	printf("删除成功\n");
}


void SearchContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	else
	{
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
			printf("%-20s\t%-3d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name, pc->data[pos].age,
				pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
	}

}


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

}


void ClearContact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	memset(pc->data, 0, sizeof(pc->data));
	printf("清空成功!\n");
	
}



int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	assert(pc);
	for (int i = 0; i < pc->count-1; i++)
	{
		qsort(pc->data, pc->count, sizeof(pc->data[0]), cmp_by_name);
	}
	printf("排序成功!\n");
}

?

分析:contact.c其实就是对contact.h中声明的各种函数包括增,删,查,加,展示等等的实现还有一些函数没有在contact.h中声明,他们是专门用于某些函数的特殊功能

例如static int FindByName(Contact* pc, char name[])函数是为了通过姓名查找是否存在此人,如果存在则返回那个人的下标在删除函数中进行删除。

静态的到这里小编就讲完了~~~

?

五.动态版通讯录:

动态版通讯录与静态版通讯录最大的不同就在于结构体的定义,多了一个容量的变量。而且添加联系人的时候要判断容量是否足够,所以我们可以封装一个函数来判断容量是否足够,不够的话进行扩容

而且涉及到了动态内存,那我们就要封装一个函数DestroyContact(&con)进行内存的释放

test.c?

#include "contact.h"
//

//2. 动态的版本

//

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

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");
}

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);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);

	return 0;
}

动态版通讯录与静态版通讯录最大的不同就在于结构体的定义,多了一个容量的变量。而且添加联系人的时候要判断容量是否足够,所以我们可以封装一个函数来判断容量是否足够,不够的话进行扩容

而且涉及到了动态内存,那我们就要封装一个函数DestroyContact(&con)进行内存的释放

?

contact.h

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


#define DEFAULT_SZ 3
#define INC_SZ 2
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;


//typedef struct Contact
//{
//	PeoInfo data[MAX];
//	int count;
//}Contact;

//动态版本
typedef struct Contact
{
	PeoInfo* data;
	int count;
	int capacity;
}Contact;

//初始化
int InitContact(Contact* pc);

//添加
void AddContact(Contact* pc);

//打印
void ShowContact(const Contact* pc);

//删除
void DelContact(Contact* pc);

//查找
void SearchContact(Contact* pc);

//修改
void ModifyContact(Contact* pc);

//清空
void ClearContact(Contact* pc);

//排序
void SortContact(Contact* pc);


//销毁
void DestroyContact(Contact* pc);

?contact.c

#include "contact.h"
int InitContact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	pc->data = (PeoInfo*)calloc(3,sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		printf("InitContact:%s\n", strerror(errno));
		return 1;
	}
	pc->capacity = DEFAULT_SZ;
	return 0;
}


void CheckCapacity(Contact* pc)
{
	if (pc->count == pc->capacity)
	{
		PeoInfo* ptr = realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			printf("ADDContact:%s\n", strerror(errno));
			return;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
		}
	}
}

//动态的版本
void AddContact(Contact* pc)
{
	assert(pc);
	CheckCapacity(pc);
	printf("请输入名字:");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:");
	scanf("%d", &pc->data[pc->count].age);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入地址:");
	scanf("%s", pc->data[pc->count].addr);

	pc->count++;
	printf("增加成功\n");
}



void ShowContact(const Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-3d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name, pc->data[i].age,
			pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

static int FindByName(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空,没有信息可以删除\n");
		return;
	}
	printf("请输入要删除人的名字:>");
	scanf("%s", name);

	//查找
	int pos = FindByName(pc, name);

	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//删除
	for (i = pos; i < pc->count - 1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->count--;
	printf("删除成功\n");
}


void SearchContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	else
	{
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		printf("%-20s\t%-3d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name, pc->data[pos].age,
			pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
	}

}


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

}


void ClearContact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	memset(pc->data, 0, sizeof(pc->data));
	printf("清空成功!\n");

}



int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	assert(pc);
	for (int i = 0; i < pc->count - 1; i++)
	{
		qsort(pc->data, pc->count, sizeof(pc->data[0]), cmp_by_name);
	}
	printf("排序成功!\n");
}



void DestroyContact(Contact* pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;

}

六.总体效果:?

1.增加

?

2.删除

?

3.查找

?

?4.修改

?

5.展示

?

?

6.排序

?

??

结语:?

以上一两种版本的通讯录,希望同学们保持空杯心,谦虚学习。

每个人的成长都是能力和想要得到的东西,不断匹配的过程,当你的才华和欲望不匹配时,你就该静下心来学习了,如果小编的总结能对你有所帮助,希望小伙伴们三连加关注哦,你的支持是小编创作的最大动力。

?

?

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

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