【C语言】动态通讯录(超详细)

news2024/12/29 16:38:40

通讯录是一个可以很好锻炼我们对结构体的使用,加深对结构体的理解,在为以后学习数据结构打下结实的基础

这里我们想设计一个有添加联系人,删除联系人,查找联系人,修改联系人,展示联系人,排序这几种功能的通讯录

目录

  • 整体框架:
  • 菜单:
  • 创建通讯录:
  • 初始化:
  • 实现功能:
    • 添加联系人:
    • 删除联系人:
      • find()的定义:
    • 查找联系人:
    • 修改联系人:
    • 展示联系人:
    • 排序:
    • free空间:
  • 源代码:

注意:我们按照三个区域划分

在这里插入图片描述

上图所示进行区域划分

  • con.c用来放实现功能的函数
  • con.h用来放头文件的声明
  • test.c用来放整体框架

整体框架:

使用do...while循环创建整体框架

整体框架在test.c中,这部分我们用来测试代码

int main()
{
	int input = 0;
	InitContact(&Con);
	do
	{
		menu();
		printf("请输入你的选项\n");
		scanf("%d", &input);
		switch (input)
		{
		case Add:
			break;
		case Del:
			break;
		case Search:
			break;
		case Modify:
			break;
		case Show:
			break;
		case Sort:
			break;
		case Exit:
			printf("你已成功退出\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}
注意
我在使用case语句时没有用数字1,2,3…
而是使用了枚举常量,因为枚举常量会更方便程序员查看与操作要与菜单的数字相匹配,不然就会弄巧成拙
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");
	printf("**************************\n");
}

创建通讯录:

此部分我们在Contact.h中创建,在另外两个里include就可以

创建通讯录之前要先创建一个联系人的结构体:
假设我们的结构体包含了一个人的姓名,年龄,性别,电话,住址
那么久可以很好的进行创建:

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

其中的常量用define按需求进行定义,避免牵一发而动全身的情况

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30

因为要动态通讯录
故设计通讯录时不能使用PeoInfo创建数组的方式进行
可以创建结构体指针,指向动态内存分配的空间

typedef struct Contact
{
	PeoInfo* Data;
	int sz;
	int capacity;
}Contact;

最后在test.c文件中创建通讯录 Contact Con;

初始化:

con.c中进行设计,不要忘记在test.c中调用,在con.h中声明
实现功能皆是如此设计,将不在赘述

	void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = START;
	PeoInfo* p = (PeoInfo*)malloc(sizeof(PeoInfo) * START);
	//start为初始化大小,define定义为3
	if (p != NULL)
	{
		pc->Data = p;
	}
	else
	{
		perror("InitContact->malloc");
	}
}

实现功能:

添加联系人:

void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* str = (PeoInfo*)realloc
		(pc->Data, sizeof(PeoInfo) * 
		(pc->capacity + START_ADD));
		//START_ADD为define定义,为一次扩容数量
		if (str != NULL)
		{
			pc->Data = str;
			pc->capacity = pc->capacity + START_ADD;
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");
			return;
		}
	}
	printf("输入名字\n");
	scanf("%s", pc->Data[pc->sz].name);
	printf("输入年龄\n");
	scanf("%d", &pc->Data[pc->sz].age);
	printf("输入性别\n");
	scanf("%s", &pc->Data[pc->sz].sex);
	printf("输入电话\n");
	scanf("%s", &pc->Data[pc->sz].tele);
	printf("输入住址\n");
	scanf("%s", &pc->Data[pc->sz].addr);
	printf("输入成功\n");
	pc->sz++;
}

删除联系人:

void DelContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}
	char name[NAME_MAX];
	printf("输入你要删除人的姓名\n");
	scanf("%s", name);
	int ret = find(pc, name);
	//我们这里使用了find函数
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	for (int i = ret; i < pc->sz-1; i++)
	{
		pc->Data[i] = pc->Data[i + 1];
	}
	pc->sz--;
}

我们在输入查找姓名后要进行查找,因此我们设计了一个find函数,方便别的函数的使用

find()的定义:

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

查找联系人:

void SearchContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	char name[NAME_MAX];
	printf("输入你要查找人的姓名\n");
	scanf("%s", name);
	int ret = find(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
	printf(" % -20s % -5d % -5s % -20s % -20s\n",
		pc->Data[ret].name, pc->Data[ret].age, pc->Data[ret].sex, pc->Data[ret].tele, pc->Data[ret].addr);
}

修改联系人:

void ModifyContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	char name[NAME_MAX];
	printf("输入你要修改人的姓名\n");
	scanf("%s", name);
	int ret = find(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	printf("输入名字\n");
	scanf("%s", pc->Data[ret].name);
	printf("输入年龄\n");
	scanf("%d", &pc->Data[ret].age);
	printf("输入性别\n");
	scanf("%s", &pc->Data[ret].sex);
	printf("输入电话\n");
	scanf("%s", &pc->Data[ret].tele);
	printf("输入住址\n");
	scanf("%s", &pc->Data[ret].addr);
	printf("输入成功\n");
}

展示联系人:

void ShowContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需打印\n");
		return;
	}
	printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf(" % -20s % -5d % -5s % -20s % -20s\n",
			pc->Data[i].name, pc->Data[i].age, pc->Data[i].sex, pc->Data[i].tele, pc->Data[i].addr);
	}
}

排序:

排序可以按照名字排,或是年龄,亦或是性别等等
这里我们只进行名字的排序,使用方法大同小异(快排)

int cmp_name(void* e1,void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	qsort(pc->Data, pc->sz, sizeof(PeoInfo), cmp_name);
}

free空间:

最后一步就是释放空间有始有终

void DestoryContact(Contact* pc)
{
	free(pc);
}

源代码:

con.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"

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


//void InitContact(Contact* pc)
//{
//	assert(pc);
//	pc->sz = 0;
//	memset(pc->Data, 0, sizeof(pc->Data));
//}
void InitContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = START;
	PeoInfo* p = (PeoInfo*)malloc(sizeof(PeoInfo) * START);
	if (p != NULL)
	{
		pc->Data = p;
	}
	else
	{
		perror("InitContact->malloc");
	}
}

void DestoryContact(Contact* pc)
{
	free(pc);
}


void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->sz == pc->capacity)
	{
		PeoInfo* str = (PeoInfo*)realloc(pc->Data, sizeof(PeoInfo) * (pc->capacity + START_ADD));
		if (str != NULL)
		{
			pc->Data = str;
			pc->capacity = pc->capacity + 2;
			printf("增容成功\n");
		}
		else
		{
			perror("AddContact->realloc");
			return;
		}
	}
	printf("输入名字\n");
	scanf("%s", pc->Data[pc->sz].name);
	printf("输入年龄\n");
	scanf("%d", &pc->Data[pc->sz].age);
	printf("输入性别\n");
	scanf("%s", &pc->Data[pc->sz].sex);
	printf("输入电话\n");
	scanf("%s", &pc->Data[pc->sz].tele);
	printf("输入住址\n");
	scanf("%s", &pc->Data[pc->sz].addr);
	printf("输入成功\n");
	pc->sz++;
}

void ShowContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需打印\n");
		return;
	}
	printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < pc->sz; i++)
	{
		printf(" % -20s % -5d % -5s % -20s % -20s\n",
			pc->Data[i].name, pc->Data[i].age, pc->Data[i].sex, pc->Data[i].tele, pc->Data[i].addr);
	}
}

void DelContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空,无需删除\n");
		return;
	}
	char name[NAME_MAX];
	printf("输入你要删除人的姓名\n");
	scanf("%s", name);
	int ret = find(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	for (int i = ret; i < pc->sz-1; i++)
	{
		pc->Data[i] = pc->Data[i + 1];
	}
	pc->sz--;
}

void SearchContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	char name[NAME_MAX];
	printf("输入你要查找人的姓名\n");
	scanf("%s", name);
	int ret = find(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	printf(" % -20s % -5s % -5s % -20s % -20s\n", "姓名", "年龄", "性别", "电话", "住址");
	printf(" % -20s % -5d % -5s % -20s % -20s\n",
		pc->Data[ret].name, pc->Data[ret].age, pc->Data[ret].sex, pc->Data[ret].tele, pc->Data[ret].addr);
}

void ModifyContact(Contact* pc)
{
	if (pc->sz == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	char name[NAME_MAX];
	printf("输入你要修改人的姓名\n");
	scanf("%s", name);
	int ret = find(pc, name);
	if (ret == -1)
	{
		printf("查无此人\n");
		return;
	}
	printf("输入名字\n");
	scanf("%s", pc->Data[ret].name);
	printf("输入年龄\n");
	scanf("%d", &pc->Data[ret].age);
	printf("输入性别\n");
	scanf("%s", &pc->Data[ret].sex);
	printf("输入电话\n");
	scanf("%s", &pc->Data[ret].tele);
	printf("输入住址\n");
	scanf("%s", &pc->Data[ret].addr);
	printf("输入成功\n");
}

int cmp_name(void* e1,void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	qsort(pc->Data, pc->sz, sizeof(PeoInfo), cmp_name);
}

con.h

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

#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30

#define START 3
#define START_ADD 2

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


typedef struct Contact
{
	PeoInfo* Data;
	int sz;
	int capacity;
}Contact;

//init
void InitContact(Contact* pc);

//add
void AddContact(Contact* pc);

//show
void ShowContact(Contact* pc);

//del
void DelContact(Contact* pc);

//search
void SearchContact(Contact* pc);

//modify
void ModifyContact(Contact* pc);

//sort
void SortContact(Contact* pc);

//destory
void DestoryContact(Contact* pc);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"

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");
	printf("**************************\n");
}
int main()
{
	int input = 0;
	Contact Con;
	InitContact(&Con);
	do
	{
		menu();
		printf("请输入你的选项\n");
		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:
			DestoryContact(&Con);
			printf("你已成功退出\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;

		}
	} while (input);
	return 0;
}

欢迎纠错与讨论

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

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

相关文章

数据挖掘(3)特征化

从数据分析角度&#xff0c;DM分为两类&#xff0c;描述式数据挖掘&#xff0c;预测式数据挖掘。描述式数据挖掘是以简介概要的方式描述数据&#xff0c;并提供数据的一般性质。预测式数据挖掘分析数据建立模型并试图预测新数据集的行为。 DM的分类&#xff1a; 描述式DM&#…

arm代码

RISC精简指令集 长度和执行周期固定 长度为一条机器指令在计算机占用的内存大小 指令周期为CPU执行一条机器指令所发费的时间(时钟周期由CPU工作频率决定) CISC复杂指令集 其架构一般用于PC端 X86和X64都是负载指令集CPU 更注重指令的功能性 指令周期和长度都不固定 ar…

014-第二代软件开发

第二代软件开发 文章目录 第二代软件开发项目介绍正式开始我们的Debian Qt 软件开发主题色QSS U盘检测QFileSystemWatcher 屏幕键盘LibUSB 使用 总结 关键字&#xff1a; Qt、 Qml、 U盘检测、 屏幕键盘、 LibUSB 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这…

Qt 综合练习小项目--反金币(2/2)

目录 4 选择关卡场景 4.2 背景设置 4.3 创建返回按钮 4.3 返回按钮 4.4 创建选择关卡按钮 4.5 创建翻金币场景 5 翻金币场景 5.1 场景基本设置 5.2 背景设置 5.3 返回按钮 5.4 显示当前关卡 5.5 创建金币背景图片 5.6 创建金币类 5.6.1 创建金币类 MyCoin 5.6.…

GPT系列论文解读:GPT-2

GPT系列 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一系列基于Transformer架构的预训练语言模型&#xff0c;由OpenAI开发。以下是GPT系列的主要模型&#xff1a; GPT&#xff1a;GPT-1是于2018年发布的第一个版本&#xff0c;它使用了12个Transformer…

JavaEE 网络原理——TCP的工作机制(中篇 三次握手和四次挥手)

文章目录 一、TCP 内部工作机制——连接管理1. 连接(三次握手)(1).有连接和确认应答之间的关系(2). 通过客户端和服务器详细描述三次握手 2. 断开连接(四次挥手)(1)讨论“四次握手”中间步骤的合并问题。(2) 根据简单的 TCP 代码解释断开连接(3) 四次挥手中的两个重要的 TCP 状…

计算机网络-计算机网络体系结构-物理层

目录 一、通信基础 通信方式 传输方式 码元 传输率 *二 准则 2.1奈氏准则(奈奎斯特定理) 2.2香农定理 三、信号的编码和调制 *数字数据->数字信号 数字数据->模拟信号 模拟数据->数字信号 模拟数据->模拟信号 *四、数据交换方式 电路交换 报文交换…

【刷题笔记10.5】LeetCode:排序链表

LeetCode&#xff1a;排序链表 一、题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 二、分析 这题咱们默认要求&#xff1a;空间复杂度为O(1)。所以这把咱们用自底向上的方法实现归并排序&#xff0c;则可以达到O(1) 的空间复杂…

[极客大挑战 2019]FinalSQL - 异或盲注

1、这题的关键是找注入点&#xff0c;如果选择用户名、密码作为输入点就麻烦了 2、注入点&#xff1a;按钮&#xff0c;点击就传id&#xff1b;当id1时&#xff0c;提示Click others   可以利用id的特性&#xff0c;构造异或匹配   payload: f"1^(ord(substr((select…

nodejs+vue中医体质的社区居民健康管理系统elementui

可以实现首页、中医体质量表、健康文章、健康视频、我的等&#xff0c;在我的页面可以对医生、小区单元、医疗药品等功能进行操作。目前主要的健康管理系统是以西医为主&#xff0c;而为了传扬中医文化&#xff0c;提高全民健康意识&#xff0c;解决人民日益增长的美好生活需要…

基于SpringBoot的图书进销存管理系统

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 图书类型管理 商品退货管理 客户信息管理 图书添加 客户添加 应收金额 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实…

Ubuntu无法引导启动的修复

TLDR&#xff1a;使用Boot-Repair工具。 Boot-Repair Boot-Repair是一个简单的工具&#xff0c;用于修复您在Ubuntu中可能遇到的常见启动问题&#xff0c;例如在安装Windows或其他Linux发行版后无法启动Ubuntu时&#xff0c;或者在安装Ubuntu后无法启动Windows时&#xff0c;…

[CISCN 2019华北Day2]Web1 - 布尔盲注

考点&#xff1a;布尔盲注【注意&#xff0c;sql中的substr初始位置是1不是0】 1、页面提示用id传参&#xff0c;而且我们发现是post传参 2、我们传了id1后提示“Hello, glzjin wants a girlfriend.“ 3、由于这题直接输入查询字符&#xff0c;可以通过字典爆破过滤&#xff0…

深度学习基础之参数量(3)

一般的CNN网络的参数量估计代码 class ResidualBlock(nn.Module):def __init__(self, in_planes, planes, norm_fngroup, stride1):super(ResidualBlock, self).__init__()print(in_planes, planes, norm_fn, stride)self.conv1 nn.Conv2d(in_planes, planes, kernel_size3, …

人机关系不是物理关系也不是数理关系

人机关系是一种复杂的社会技术系统&#xff0c;涉及到人类和机器、环境之间的相互作用和影响。它不仅限于物理接触和数理规律&#xff0c;同时还包括了思维、情感、意愿等方面的交流和互动。在人机关系中&#xff0c;人类作为使用者和机器作为工具&#xff08;将来可能会上升到…

rust入门一:安装 Hello World

环境&#xff1a; window 11 专业版rust 1.72.1 一、下载安装 直接去官网&#xff1a; https://www.rust-lang.org/tools/install 下载完成后如下&#xff1a; 双击运行一步步安装就行。 如果是更新或卸载&#xff0c;在命令行中运行&#xff1a; rustup update&#xff1a…

ChatGPT基础使用总结

文章目录 一、ChatGPT基础概念大型语言模型LLMs---一种能够以类似人类语言的方式“说话”的软件ChatGPT定义---OpenAI 研发的一款聊天机器人程序&#xff08;2022年GPT-3.5&#xff0c;属于大型语言模型&#xff09;ChatGPT4.0---OpenAI推出了GPT系列的最新模型ChatGPT典型使用…

[GXYCTF2019]禁止套娃 无回显 RCE 过滤__FILE__ dirname等

扫除git 通过githack 获取index.php <?php include "flag.php"; echo "flag在哪里呢&#xff1f;<br>"; if(isset($_GET[exp])){if (!preg_match(/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i, $_GET[exp])) {if(; preg_replace(/[a-z,_]\(…

DevicData-D-XXXXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

引言&#xff1a; 在数字时代&#xff0c;数据安全成为一项至关重要的挑战。DevicData-D-XXXXXXXX勒索病毒&#xff08;以下简称DevicData病毒&#xff09;是这场战斗中的新敌人&#xff0c;它能够以毁灭性的方式加密您的数据&#xff0c;迫使您在数据和时间之间做出艰难的选择…

nodejs+vue游戏测评交流系统elementui

可以实现首页、发布招募、公司资讯、我的等&#xff0c;另一方面来说也可以提高在游戏测评交流方面的效率给相关管理人员的工作带来一定的便利。在我的页面可以对游戏攻略、我的收藏管理、实际上如今信息化成为一个未来的趋势或者可以说在当前现代化的城市典范中,发布招募等功能…