【C语言练习】DOS黑框框通讯录(使用结构体、动态内存管理联系人信息,函数指针等)

news2024/11/26 22:47:45

文章目录

  • 1. contacts.h 头文件、函数/常量/结构体声明
  • 2. test.c 主界面菜单打印、菜单功能选项选择
  • 3. contacts.c 函数实现
  • 4. 使用结构体、动态内存,函数指针实现时的注意点
  • 5. 运行演示

1. contacts.h 头文件、函数/常量/结构体声明

#pragma once

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

// 姓名和地址长度
#define NAME_LEN 20
#define ADDR_LEN 40

// 通讯录大小(能存储多少个联系人)
#define CONTACTS_SIZE 1000


/* 联系人信息:姓名、性别、年龄、电话、住址。 */
typedef struct PeopleInfo
{
	char* name;
	char gender;
	short age;
	char tele[11];
	char* addr;
} PeopleInfo;


/* 通讯录信息 */
typedef struct Contacts
{
	PeopleInfo* peopleInfo;
	int peopleNums;
} Contacts;


// 初始化通讯录
void InitContacts(Contacts* contacts);

// 添加联系人
void AddContacts(Contacts* contacts);

// 查找联系人
int SearchContactsByName(Contacts* contacts);

// 显示所有联系人
void ShowAllContacts(Contacts* contacts);

// 修改联系人
void ModifyByName(Contacts* contacts);

// 删除联系人
void DeleteContacts(Contacts* contacts);

// 对所有联系人按照某种方式排序
void SortContacts(Contacts* contacts);

2. test.c 主界面菜单打印、菜单功能选项选择

#define _CRT_SECURE_NO_WARNINGS 1

/*
 *(1)实现一个通讯录;
	通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址
 *(2)提供方法:
	1.添加联系人信息
	2.删除指定联系人信息
	3.查找指定联系人信息
	4.修改指定联系人信息
	5.显示所有联系人信息
	6.清空所有联系人
	7.以名字排序所有联系人
*/

#include "contacts.h"

// static修饰,不将该函数暴露在外部
static void menu()
{
	printf("\n----- OPTIONS ----- OPTIONS ----- OPTIONS -----\n");
	printf(" ************** 1.ADD ********************* \n");
	printf(" ************** 2.DELETE ****************** \n");
	printf(" ************** 3.SEARCH ****************** \n");
	printf(" ************** 4.MODIFY ****************** \n");
	printf(" ************** 5.SHOW ALL **************** \n");
	printf(" ************** 6.DELETE ALL ************** \n");
	printf(" ************** 7.SORT ******************** \n");
	printf(" ************** 0.EXIT ******************** \n");
	printf("----- OPTIONS ----- OPTIONS ----- OPTIONS -----\n\n");
}


/* 菜单选项作为枚举常量表示 */
enum Option
{
	EXIT,
	ADD,
	DELETE,
	SEARCH,
	MODIFY,
	SHOW_ALL,
	DELETE_ALL,
	SORT
};


int main()
{
	/* 初始化通讯录 */
	Contacts contacts;
	InitContacts(&contacts);

	short input = 0;
	do 
	{
		menu();
		printf("请选择:");
		scanf("%hd", &input);
		getchar();
		/* 根据选项执行相应操作 */
		switch (input)
		{
		case ADD:
			printf("\nADD.\n");
			AddContacts(&contacts);
			break;

		case DELETE:
			printf("\nDELETE.\n");
			DeleteContacts(&contacts);
			break;

		case SEARCH:
			printf("SEARCH.\n");
			printf("Who do you want to search?\n");
			int index = SearchContactsByName(&contacts);
			if (index < 0)
			{
				printf("The contacts you just searched doesn't exist in your contacts.\n\n");
			}
			else 
			{
				printf("SEARCH SUCCEED!\n");
				printf("| %-20s | %s | %s | %-11s | %-40s |\n",
					"NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");
				printf("------------------------------------------------------------------------------------------------\n");
				printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n\n",
					(contacts.peopleInfo + index)->name,
					(contacts.peopleInfo + index)->gender,
					(contacts.peopleInfo + index)->age,
					(contacts.peopleInfo + index)->tele,
					(contacts.peopleInfo + index)->addr);
			}
			break;

		case MODIFY:
			printf("\nMODIFY.\n");
			ModifyByName(&contacts);
			break;

		case SHOW_ALL:
			printf("\nSHOW ALL CONTACTS.\n");
			ShowAllContacts(&contacts);
			break;

		case DELETE_ALL:
			printf("\nDELETE ALL CONTACTS.\n");
			// 后续添加都会从0下标处开始
			contacts.peopleNums = 0;
			printf("DELETE ALL CONTACTS SUCCEED!\n\n");
			break;

		case SORT:
			printf("\nSORT.\n");
			SortContacts(&contacts);
			break;

		case EXIT:
			printf("\nEXIT.\n");
			break;

		default:
			printf("\nWRONG OPERATION.\n");
			break;
		}
	} while (input);

	/* 释放通讯录数据 */
	free(contacts.peopleInfo);
	contacts.peopleInfo = NULL;

	return 0;
}

3. contacts.c 函数实现

#define _CRT_SECURE_NO_WARNINGS 1

#include "contacts.h"


/* getchar()目的为了把输入缓冲区的换行字符清空 */


/* 初始化通讯录(以动态内存方式) */
void InitContacts(Contacts* contacts)
{
	/* calloc会把成员变量的值初始化为0(如果成员为指针变量则指向NULL) */
	contacts->peopleInfo = (PeopleInfo*)calloc(CONTACTS_SIZE, sizeof(PeopleInfo));
	contacts->peopleNums = 0;
	/*
	* 由于指针变量成员指向NULL,必须要为指针变量(每一个联系人的姓名、地址)申请一块内存,
	* 这样的话calloc会将内存分配后,给指针变量指向一个空串(内容仅仅只有\0的串)。
	*/
	for (int i = 0; i < CONTACTS_SIZE; i++) {
		(contacts->peopleInfo + i)->name = (char*)calloc(NAME_LEN, sizeof(char));
		(contacts->peopleInfo + i)->addr = (char*)calloc(ADDR_LEN, sizeof(char));
	}
}


/* 添加联系人 */
void AddContacts(Contacts* contacts)
{
	assert(contacts);
	int size = contacts->peopleNums;
	PeopleInfo* peopleInfo = contacts->peopleInfo + size;

	printf("NAME:");
	scanf("%[^\n]s", peopleInfo->name);
	getchar();

	printf("GENDER:");
	scanf("%c", &(peopleInfo->gender));
	getchar();

	printf("AGE:");
	scanf("%hd", &(peopleInfo->age));
	getchar();

	printf("TELEPHONE:");
	scanf("%s", peopleInfo->tele);
	getchar();

	printf("ADDRESS:");
	scanf("%[^\n]s", peopleInfo->addr);
	getchar();

	(contacts->peopleNums)++;
	printf("\nADD SUCCEED!\n");
}


/*
 * 查找联系人
 * @返回值:如果不存在返回-1,找到返回下标。
*/
int SearchContactsByName(Contacts* contacts)
{
	char name[NAME_LEN];
	printf("\nPlease enter the contacts' name:");
	scanf("%[^\n]s", name);
	getchar();
	for (int i = 0; i < contacts->peopleNums; i++)
	{
		if (strcmp(name, contacts->peopleInfo->name) == 0)
		{
			return i;
		}
	}
	return -1;
}


/* 显示所有联系人 */
void ShowAllContacts(Contacts* contacts)
{
	printf("| %-20s | %s | %s | %-11s | %-40s |\n",
		"NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");
	printf("-----------------------------------------------------------------------------------------------------\n");
	for (int i = 0; i < contacts->peopleNums; i++)
	{
		printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n",
			(contacts->peopleInfo + i)->name,
			(contacts->peopleInfo + i)->gender,
			(contacts->peopleInfo + i)->age,
			(contacts->peopleInfo + i)->tele,
			(contacts->peopleInfo + i)->addr);
	}
}


/* 修改联系人 */
void ModifyByName(Contacts* contacts)
{
	if (contacts->peopleNums <= 0)
	{
		printf("No contacts in your contacts book.\n\n");
		return;
	}
	assert(contacts->peopleInfo);
	printf("\nWhose information you want to modify?\n");
	int index = SearchContactsByName(contacts);
	if (index < 0)
	{
		printf("\nCannot find the information.\n\n");
		return;
	}

	PeopleInfo* peopleInfo = contacts->peopleInfo + index;

	printf("\nORIGINAL INFORMATION:\n");
	printf("| %-20s | %s | %s | %-11s | %-40s |\n",
		"NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");
	printf("------------------------------------------------------------------------------------------------\n");
	printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n\n",
		peopleInfo->name,
		peopleInfo->gender,
		peopleInfo->age,
		peopleInfo->tele,
		peopleInfo->addr);

	/* 选择修改指定信息 */
	printf("----- MODIFICATION OPTIONS ----- \n");
	printf(" *********** 1.NAME *********** \n");
	printf(" *********** 2.GENDER *********** \n");
	printf(" *********** 3.AGE *********** \n");
	printf(" *********** 4.TELEPHONE *********** \n");
	printf(" *********** 5.ADDRESS *********** \n");
	printf(" *********** 0.EXIT MODIFICATION *********** \n");
	printf("----- MODIFICATION OPTIONS ----- \n\n");

	short input;
	do
	{
		printf("What information you want to modify?:");
		scanf("%hd", &input);
		getchar();
		switch (input)
		{
		case 0:
			printf("\nEXIT MODIFICATION.\n");
			break;

		case 1:
			printf("\nMODIFY NAME:");
			scanf("%[^\n]s", peopleInfo->name);
			getchar();
			break;

		case 2:
			printf("\nMODIFY GENDER:");
			scanf("%c", &(peopleInfo->gender));
			getchar();
			break;

		case 3:
			printf("\nMODIFY AGE:");
			scanf("%hd", &(peopleInfo->age));
			getchar();
			break;

		case 4:
			printf("\nMODIFY TELEPHONE:");
			scanf("%s", peopleInfo->tele);
			getchar();
			break;

		case 5:
			printf("\nMODIFY ADDRESS:");
			scanf("%[^\n]s", peopleInfo->addr);
			getchar();
			break;

		default:
			printf("\nWRONG OPERATION.\n");
			break;
		}
	} while (input);

	printf("\nMODIFIED INFORMATION:\n");
	printf("| %-20s | %s | %s | %-11s | %-40s |\n",
		"NAME", "GENDER", "AGE", " TELEPHONE ", "ADDRESS");
	printf("------------------------------------------------------------------------------------------------\n");
	printf("| %-20s | %3c    | %2hd  | %-11s | %-40s |\n\n",
		peopleInfo->name,
		peopleInfo->gender,
		peopleInfo->age,
		peopleInfo->tele,
		peopleInfo->addr);
	printf("\nMODIFY SUCCEED!\n");
}


/* 删除联系人 */
void DeleteContacts(Contacts* contacts)
{
	if (contacts->peopleNums <= 0)
	{
		printf("You don't have any contacts.\n\n");
		return;
	}
	assert(contacts->peopleInfo);
	ShowAllContacts(contacts);
	printf("\nWho do you want to delete?\n");
	int index = SearchContactsByName(contacts);
	if (index < 0)
	{
		printf("\nThe contacts you just searched doesn't exist in your contacts.\n\n");
		return;
	}

	PeopleInfo* peopleInfo = contacts->peopleInfo;
	for (int i = index; i < contacts->peopleNums - 1; i++)
	{	// 只要成员一样,结构体可以直接赋值另一个结构体
		*(peopleInfo + i) = *(peopleInfo + i + 1);
	}
	contacts->peopleNums--;
	printf("\nDELETE SUCCEED!\n\n");
}


/* 根据年龄升序排序 */
static int CmpByAge(PeopleInfo* p1, PeopleInfo* p2)
{
	return p1->age - p2->age;
}
/* 根据姓名中的字母升序排序 */
static int CmpByName(PeopleInfo* p1, PeopleInfo* p2)
{
	return strcmp(p1->name, p2->name);
}
/* 对联系人排序 */
static void SortPeopleInfo(Contacts* contacts, int (*pfCmp)(PeopleInfo*, PeopleInfo*))
{
	PeopleInfo* peopleInfo = contacts->peopleInfo;
	int size = contacts->peopleNums;

	int sortedBorder = size - 1;
	int lastExchange = 0;
	for (int i = 0; i < size - 1; i++)
	{
		bool flg = true;
		for (int j = 0; j < sortedBorder; j++)
		{
			if (pfCmp(peopleInfo + j, peopleInfo + j + 1) > 0)
			{
				flg = false;
				PeopleInfo tmp = *(peopleInfo + j);
				*(peopleInfo + j) = *(peopleInfo + j + 1);
				*(peopleInfo + j + 1) = tmp;
				lastExchange = j;
			}

		}
		if (flg)
		{
			break;
		}
		sortedBorder = lastExchange;
	}
}
/* 按照选择的方式排序 */
void SortContacts(Contacts* contacts)
{
	printf("Sorting by what?Please Choose:\n");
	printf("********** 1. the age.\n");
	printf("********** 2. the name.\n\n");
	short input;
	scanf("%hd", &input);
	switch (input)
	{
	case 1:
		printf("Sorting by age...\n\n");
		SortPeopleInfo(contacts, CmpByAge);
		break;
	case 2:
		printf("Sorting by name...\n\n");
		SortPeopleInfo(contacts, CmpByName);
		break;

	default:
		printf("\nWRONG CHOICE.\n");
		break;
	}
	printf("The contacts information after sorting:\n\n");
	ShowAllContacts(contacts);
}

4. 使用结构体、动态内存,函数指针实现时的注意点

  1. 初始化在这里插入图片描述
  2. 避免后续使用时参数太长在这里插入图片描述
  3. 结构体赋值结构体在这里插入图片描述
  4. 配合函数指针在这里插入图片描述

5. 运行演示

  1. 添加联系人:在这里插入图片描述
  2. 查找联系人:在这里插入图片描述
  3. 显示所有联系人:在这里插入图片描述
  4. 根据年龄或姓名排序:在这里插入图片描述
    在这里插入图片描述
  5. 修改联系人信息:在这里插入图片描述
  6. 删除所有联系人:
    在这里插入图片描述

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

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

相关文章

浏览器原生JavaScript离线文字转语音TTS播放,支持Windows自带TTS语音和移动端(安卓、IOS)

前言 JS已经可以实现语音合成(文字转语音)和语音识别(语音转文字),各个浏览器支持列表如下所示: 语音识别支持列表: 因此,浏览器上面使用语音合成非常简单。 页面效果示例: 实现功能 1、支持速度,音调设置 2、支持下拉选择语音模板 3、文字转语音 代码实现 …

自学视觉SLAM(1)

引言 小编研究生的研究方向是视觉SLAM&#xff0c;目前在自学&#xff0c;已经学了Linux系统的基本操作&#xff0c;vim编辑器以及高翔老师的一些视屏。本篇文章为初学笔记。 文章目录 引言1 熟悉 Linux1.1 如何在 Ubuntu 中安装软件&#xff08;命令⾏界⾯&#xff09;&#x…

算法竞赛备赛之动态规划训练提升,DP基础掌握

1.背包问题 1.1.01背包问题 01背包问题是在M件物品中选择若干件放在空间为W的背包中&#xff0c;每件物品的体积为W1&#xff0c;W2至Wn&#xff0c;价值为P1&#xff0c;P2至Pn&#xff0c;01背包的约束条件是给定几种物品&#xff0c;每种物品有且只有一个&#xff0c;并且…

(4) OpenCV图像处理kNN近邻算法-识别数字0和1

我们的目标是构建一个可以读取手写数字的应用程序。为此,我们需要创建一个手写数字的图片文件 “ digits.png ”,图像的像素为:( 320*40 ), 其中包含 32个手写数字(每个数字16个),每个数字都是20x20的图像,如下图。 因此,我们的第 1 步是将图像分割成 32 个不…

华为OD机试 - 第k个排列 - 全排列递归(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

C语言刷题篇(备赛中......)--------( 篇章1 )

前言: 博主报名了一个小比赛&#xff0c;用来写一些基础的C语言题目&#xff0c;正好借此巩固一下基础 希望这些题对你们也有帮助 猫猫跟你说:该学习了 目录 前言: 题目&#xff08; 1 &#xff09; 解题思路 题目&#xff08; 2 &#xff09; 解题思路 题目&#xff…

Linux虚拟机磁盘空间不足怎么办

我是一个目录 1. 在虚拟机客户端扩充磁盘空间2. 检查磁盘空间3. 扩展空间而无需重启虚拟机4. 创建新磁盘分区5. 创建物理卷6. 扩展逻辑卷 对大多数系统管理员来说&#xff0c;扩充 Linux 服务器的磁盘空间是日常的工作之一&#xff0c;下面会通过使用 Linux 命令&#xff0c;在…

Text-to-SQL小白入门(七)PanGu-Coder2论文——RRTF

论文概述 学习这个RRTF之前&#xff0c;可以先学习一下RLHF。 顺带一提&#xff1a;eosphoros-ai组织「DB-GPT开发者」最新有个新项目Awesome-Text2SQL&#xff1a;GitHub - eosphoros-ai/Awesome-Text2SQL: Curated tutorials and resources for Large Language Models, Text2…

ps 去除图标背景色

百度安全验证 https://baijiahao.baidu.com/s?id1766678909759797922&wfrspider&forpc 使用魔术橡皮擦工具&#xff0c;超级简单 最后&#xff0c;保存为PNG格式&#xff0c;因为PNG格式支持透明背景。

大二毕设.3-网盘系统-文件模块讲解

目录 模块功能介绍 抽象文件存储引擎顶级接口 高性能单文件上传-sendfile零拷贝 为什么要分片上传 文件存储引擎模块讲解 文件模块具体实现讲解 项目演示博客 模块功能介绍 文件列表查询 聚簇索引和非聚簇索引回表查询最左前缀原则覆盖索引创建文件夹文件重命名文件删除 …

jvs-rules(规则引擎)和jvs智能bi(自助式数据分析)9.22更新内容

规则引擎更新功能 新增: 1.新增节点匹配筛选 用于做多个条件的数据筛选&#xff0c;以便将符合条件的数据传递给下一个节点进行处理&#xff0c;通常用于实现复杂的查询逻辑。 2.复合变量节点新增判断条件选项说明 用户可以根据自己的需求&#xff0c;为复合变量节点添加不…

全球化、国际化、本地化和翻译:GILT 的方法

为促进公司走向全球市场&#xff0c;您需要与客户沟通&#xff0c;并成功传达您的信息。您可能会认为&#xff0c;您需要的只是一支强大的翻译团队。但是&#xff0c;翻译并不像看起来那么简单。 将公司信息翻译成另一种语言&#xff0c;需要了解一些细微差别和文化背景。要想在…

合合信息、上海大学、华南理工大学发布业内首个古彝文编码“大字典” ,为古文字打造“身份证”

“乌蒙山连着山外山&#xff0c;月光洒向了响水滩。”近期在各大短视频平台爆火的《奢香夫人》你听过吗&#xff1f;奢香夫人是一位彝族“巾帼英雄”&#xff0c;这首同名歌曲早在2009年便已发布&#xff0c;如今突然“翻红”&#xff0c;不仅体现了大众对于少数民族文化高涨的…

竞赛 基于生成对抗网络的照片上色动态算法设计与实现 - 深度学习 opencv python

文章目录 1 前言1 课题背景2 GAN(生成对抗网络)2.1 简介2.2 基本原理 3 DeOldify 框架4 First Order Motion Model5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于生成对抗网络的照片上色动态算法设计与实现 该项目较为新颖&am…

计算糖果(牛客)

一、题目 计算糖果_牛客题霸_牛客网 二、代码 #include <iostream> using namespace std;int main() {int x, y, m, n;cin >> x >> y >> m >> n;//A-Bx B-Cy ABm BCnif ((x > 30 || x < -30) && (y > 30 || y < -30) &am…

【Vue】模板语法,插值、指令、过滤器、计算属性及监听属性(内含面试题及毕设等实用案例)上篇

一、引言 1、什么是模板语法&#xff1f; Vue 的模板语法是一种用于在 HTML 中声明式地渲染 Vue 组件的语法。它基于 HTML&#xff0c;并通过特定的模板语法扩展了 HTML。Vue 使用了一种称为 “Mustache” 语法的模板插值来绑定数据到 HTML 元素上。 在 Vue 的模板语法中&…

像专业人士一样部署:掌握代码部署的最佳实践

作为开发人员&#xff0c;您知道部署代码可能是一个耗时且复杂的过程。简化生产部署对于确保您的代码尽快有效地到达用户手中至关重要。但如何实现这一目标呢&#xff1f;在本文中&#xff0c;我们将讨论简化生产部署的一些基本提示和技巧。 从自动化构建过程到优化发布策略&am…

Java高级应用——多线程

目录 多线程 相关名词解释 程序、进程与线程 并行与并发 单核与多核 Java多线程概述 Test测试框架测试多线程的注意事项 主线程和子线程的概念 Test测试类需要使用.join()方法来确保子线程执行完毕 线程调度&#xff08;目前仅了解&#xff09; 守护线程&#xff08;…

【Linux】Linux 常用命令

Linux 常用命令 1. 复制/粘贴2. 查看目录和文件: ls3. 查看当前目录: pwd4. 切换目录: cd5. Linux 目录结构6. 绝对路径 vs 相对路径7. tab 键补全8. ctrl c 重新输入9. 创建文件: touch10. 查看文件内容: cat11. 写内容 echo12. 创建目录: mkdir12. 删除文件: rm13. 拷贝文件…

易基因直播预告|细菌微生物基因表达调控表观研究易基因科技

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 DNA甲基化是在半个多世纪前在细菌中发现的。DNA碱基可以作为一个表观遗传调节因子——也就是说&#xff0c;它可以赋予相同的基因序列不同的和可逆的调控状态。在真核生物中&#xff0c;…