【C语言】通讯录的简单实现

news2024/11/25 0:57:49

通讯录的内容


contect.h 

#pragma once
// 包含头文件
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>


// 使用枚举常量定义功能
enum Function
{
	quit, // 注意这是逗号,不是分号
	save,
	addition,
	delete,
	search,
	revise,
	sort,
	show // 最后一个没有逗号
};

// 人的信息
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
typedef struct People_Information
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char addr[ADDR_MAX];
}People; // 通过typedef将struct People_Informtion定义为了People

// 通讯录
#define DATA_MAX 1000
typedef struct Contact
{
	People data[DATA_MAX]; // data数组里面存放的是每个人的信息
	int sz; // 用于记录通讯录中有几个人的信息
}Contact; // 通过typedef将struct Contact定义为了Contact


// 函数声明
// 初始化通讯录
void InitContact(Contact* contact);
// 增加个人信息
void AddContact(Contact* contact);
// 显示通讯录
void ShowContact(const Contact* contact);
// 删除指定信息
void DelContact(Contact* contact);
// 查找指定信息
void SeaContact(const Contact* contact);
// 修改指定联系人
void RevContact(Contact* contact);
// 排序通讯录
void SorContact(Contact* contact);

contact.c 

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
	printf("..............................\n");
	printf("....0:quit........1:save......\n");
	printf("....2:addition....3:delete....\n");
	printf("....4:search......5:revise....\n");
	printf("....6:sort........7:show......\n");
	printf("..............................\n");
}
int main()
{
	
	// 利用do{}while();循环和switch语句进行多次选择
	int input;
	
	// 进入main函数就要创建通讯录
	Contact contact; // contact就是一个通讯录

	// 初始化通讯录
	InitContact(&contact); // 将通讯录的地址传过去,不仅节省地址,而且可以通过形参改变实参

	do
	{
		// 有哪些功能
		// 通过菜单将功能展现出来
		menu();

		printf("请输入功能序号:");
		scanf("%d", &input);
		switch (input)
		{
			// 通过枚举常量定义会更直观
		case quit:
			printf("退出通讯录!\n");
			break;
		case save:
			break;
		case addition:
			AddContact(&contact);
			break;
		case delete:
			DelContact(&contact);
			break;
		case search:
			SeaContact(&contact);
			break;
		case revise:
			RevContact(&contact);
			break;
		case sort:
			SorContact(&contact);
			break;
		case show:
			ShowContact(&contact);
			break;
		default:
			printf("无此序号,请重新输入。\n");
		}
	} while (input);
	return 0;
}

test.c 

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"

// 初始化通讯录
void InitContact(Contact* contact)
{
	assert(contact);
	// contact->data = 0; // contact->data表示的是首元素地址
	// 初始化一块连续的内存空间可以使用memset
	memset(contact->data, 0, sizeof(contact->data));
	contact->sz = 0;
}

// 增加个人信息
void AddContact(Contact* contact)
{
	assert(contact);

	// 进入函数进行判断
	if (contact->sz == DATA_MAX)
	{
		printf("通讯录已满,无法增加个人信息!\n");
		return;
	}
	// 没有满则进行增加个人信息
	printf("请输入姓名:");
	scanf("%s", &(contact->data[contact->sz].name));
	printf("请输入年龄:");
	scanf("%d", &(contact->data[contact->sz].age));
	printf("请输入性别:");
	scanf("%s", &(contact->data[contact->sz].sex));
	printf("请输入电话:");
	scanf("%s", &(contact->data[contact->sz].tele));
	printf("请输入地址:");
	scanf("%s", &(contact->data[contact->sz].addr));

	// 增加完一条信息后sz要加1
	contact->sz++;
	printf("增加成功!\n");
}

// 显示通讯录
void ShowContact(const Contact* contact)
{
	assert(contact);

	// 进入函数进行判断
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 显示信息
	// 标题
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < contact->sz; i++)
	{
		printf("%-10s %-5d %-5s %-12s %-30s\n",
			contact->data[i].name,
			contact->data[i].age,
			contact->data[i].sex,
			contact->data[i].tele,
			contact->data[i].addr
		);
	}
}

// 通过名字查找联系人下标
int FindByName(const Contact* contact, char* name)
{
	assert(contact);
	for (int i = 0; i < contact->sz; i++)
	{
		if (strcmp(contact->data[i].name, name) == 0)
		{
			// 找到返回数组下标

			return i;
		}
	}
	return -1;
}

// 删除指定信息
void DelContact(Contact* contact)
{
	assert(contact);

	char name[NAME_MAX];
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 通过名字查找
	printf("请输入要删除人的姓名:");
	scanf("%s", name);
	int ret = FindByName(contact, name);

	// 没找到
	if (ret == -1)
	{
		printf("要删除的人不存在!\n");
	}
	// 找到了
	// 删除这个人(其实是覆盖)
	for (int i = ret; i < contact->sz - 2; i++) // 减2这里不是很懂
	{
		contact->data[i] = contact->data[i + 1];
	}
	contact->sz--;
	printf("删除成功!\n");
	// 最后一个直接覆盖当前这个
	// 结构体类型相同可以直接赋值
	/*contact->data[ret] = contact->data[contact->sz];
	contact->sz--;*/
}

// 查找指定信息
void SeaContact(const Contact* contact)
{
	assert(contact);

	char name[NAME_MAX];
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 通过名字查找
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByName(contact, name);
	// 没找到
	if (ret == -1)
	{
		printf("要查找的人不存在!\n");
	}
	// 找到了
	// 显示出来
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
	printf("%-10s %-5d %-5s %-12s %-30s\n",
		contact->data[ret].name,
		contact->data[ret].age,
		contact->data[ret].sex,
		contact->data[ret].tele,
		contact->data[ret].addr
	);
}

// 修改指定联系人
void RevContact(Contact* contact)
{
	assert(contact);

	char name[NAME_MAX];
	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 通过名字修改
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByName(contact, name);
	// 没找到
	if (ret == -1)
	{
		printf("要修改的人不存在!\n");
	}
	// 找到了
	// 修改
	printf("请输入姓名:");
	scanf("%s", &(contact->data[contact->sz].name));
	printf("请输入年龄:");
	scanf("%d", &(contact->data[contact->sz].age));
	printf("请输入性别:");
	scanf("%s", &(contact->data[contact->sz].sex));
	printf("请输入电话:");
	scanf("%s", &(contact->data[contact->sz].tele));
	printf("请输入地址:");
	scanf("%s", &(contact->data[contact->sz].addr));

	printf("修改成功!\n");
}


int compare_name(const void* x, const void* y)
{
	return strcmp((char*)x, (char*)y);
}

// 排序通讯录
void SorContact(Contact* contact)
{
	assert(contact);

	if (contact->sz == 0)
	{
		printf("通讯录为空!\n");
		return;
	}
	// 排序通讯录
	qsort(contact, contact->sz, sizeof(contact->data[0]), compare_name);
	// 显示信息
	// 标题
	printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
	for (int i = 0; i < contact->sz; i++)
	{
		printf("%-10s %-5d %-5s %-12s %-30s\n",
			contact->data[i].name,
			contact->data[i].age,
			contact->data[i].sex,
			contact->data[i].tele,
			contact->data[i].addr
		);
	}
}

  注意:

传址还是传值

通讯录初始化涉及到传递参数,那我们到底是传址还是传值呢?

InitContact(&contact);  // 传递的是地址

// 传址:因为更节省内存空间(地址只占4/8个字节),而且可以通过形参来改变实参;

// 传值:所需的内存空间更大,并且改变形参并不会影响实参;


memset初始化连续空间

// 这里使用的是memset初始化数组,也可以通过循环将数组一个一个制成0;

memset的用法

 


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

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

相关文章

TCP 协议的相关(部分)特性

TCP的报文结构 首部长度&#xff1a; 与UDP不同&#xff0c;TCP没有有描述数据的长度的变量&#xff08;UDP的是UDP长度&#xff09;&#xff0c;但有描述TCP的报头的长度&#xff0c;为什么要和UDP不同呢&#xff1f;其实是UDP的报头长度是固定的&#xff0c;而TCP的报头是“变…

2023-2024-1 for循环-1

7-1 求N分之一序列前N项和 本题要求编写程序&#xff0c;计算序列 1 1/2 1/3 ... 的前N项之和。 输入格式: 输入在一行中给出一个正整数N。 输出格式: 在一行中按照“sum S”的格式输出部分和的值S&#xff0c;精确到小数点后6位。题目保证计算结果不超过双精度范围。…

Golang中gRPC使用及原理探究

文章目录 概述gRPC的优势&#xff1a; 1、gRPC入门1.1 protobuf安装1.2 使用gRPC1.2.1 定义proto文件1.2.2 编译proto文件1.2.3 编写客户端和服务端代码 2、gRPC的通信模式2.1 一元RPC模式2.2 客户端流RPC模式2.3 服务端流RPC模式2.4双向流RPC模式 3、 gRPC的底层原理探究3.1 H…

基于php 进行每半小时钉钉预警

前言 业务场景&#xff1a;监控当前业务当出现并发情况时技术人员可以可以及时处理 使用技术栈&#xff1a; laravelredis 半小时触发一次报警信息实现思路 1、xshell脚本 具体参数就不详细解释了&#xff0c;想要详细了解可以自行百度 curl -H "Content-Type:appl…

10.数学环境排列数学公式

1.\begin{gathered} \begin{gathered} 是 LaTeX 中的数学环境&#xff0c;通常用于排列多行数学公式或方程组&#xff0c;这些公式或方程组需要在某种程度上垂直居中对齐。这个环境通常用于多行公式&#xff0c;与 align 或 eqnarray 不同&#xff0c;它不会自动对齐等号&…

OAuth2.0、和jwt、spring security之间的区别和联系

OAuth2.0的概念 OAuth 2.0开放授权&#xff0c;OAuth 2.0 是一种授权框架&#xff0c;用于授权第三方应用程序访问用户资源&#xff0c;而无需共享用户的凭据。它为用户提供了更好的隐私和安全性&#xff0c;并允许用户对授权进行细粒度的控制&#xff0c;颁发的token是第三方应…

Vue-2.9单页应用程序

单页应用程序&#xff08;SPA-Single Page Application&#xff09; 所有功能在一个html页面上实现 具体示例&#xff1a;网易云音乐https://music.163.com 京东淘宝等是多页面应用 单页VS多页 单页面应用&#xff1a;系统类网站、内部网站、文档类网站、移动端站点 多页面…

蓝桥杯 枚举算法 (c++)

枚举就是根据提出的问题&#xff0c;——列出该问题的所有可能的解&#xff0c;并在逐一列出的过程中&#xff0c;检验每个可能解是否是问题的真正解&#xff0c; 如果是就采纳这个解&#xff0c;如果不是就继续判断下一个。 枚举法一般比较直观&#xff0c;容易理解&#xff0…

python+django医患档案电子病历管理系统7ld2o

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台 1.运行环境&#xff1a;python3.7/python3.8。 2.IDE环境&#xff1a;pycharmmysql5.7; …

从Docker初识K8S

什么是Docker&#xff1f; 假设现在有一个服务场景&#xff0c;你是一个程序猿&#xff0c;你编写代码实现一个机器人喝水的功能&#xff0c;然后你需要将这份代码部署到每个机器人身上&#xff0c;你部署的时候需要一个个安装代码所需的依赖包&#xff0c;然后运行测试你的代码…

面向C++模块的开源 IFC SDK

早在 VS2019 v16.10 版本的时候&#xff0c;我们就官宣了对 C 模块(以及几乎所有其他 C 20 特性)的全面支持&#xff0c;包括 MSVC 编译器工具集&#xff0c;静态分析&#xff0c;智能感知和调试器等&#xff0c;而实现模块需要将 C 代码实现为一种内部的临时表示形式。 今天&…

【苍穹外卖 | 项目日记】第四天

前言&#xff1a; 今天状态还可以&#xff0c;既有自己实战独立写接口&#xff0c;又听了课&#xff0c;学习了新的知识 目录 前言&#xff1a; 今日完结任务&#xff1a; 今日收获&#xff1a; 实现店铺状态接口 杂项知识点&#xff1a; 总结&#xff1a; 今日完结任务…

华为9.20笔试 复现

第一题 丢失报文的位置 思路&#xff1a;从数组最小索引开始遍历 #include <iostream> #include <vector> using namespace std; // 求最小索引值 int getMinIdx(vector<int> &arr) {int minidx 0;for (int i 0; i < arr.size(); i){if (arr[i] …

重新认识面向对象

一、重新认识面向对象 1、重新认识面向对象1.1、理解隔离的变化1.2、各司其职1.3、对象是什么 2、面向对象设计基本原则&#xff08;八个原则&#xff09;先介绍分而治之的思想构造类介绍抽象类的方法构造类2.1、依赖倒置原则(DIP )2.2、开放封闭原则(OCP )2.3、单一职责原则&a…

推荐《咒术回战》

电视动画片《咒术回战》改编自芥见下下著作的同名漫画作品&#xff0c;于2019年11月25日宣布电视动画化的消息 [1] &#xff0c;该系列由MAPPA负责制作。第1期于2020年10月3日—2021年3月27日播出 [8] &#xff0c;全24集。 动画电影《咒术回战 0》于2021年3月27日宣布制作决…

实施 DevSecOps 最佳实践

DevSecOps 是一个框架&#xff0c;它将开发 (Dev)、IT 运营 (Ops) 和安全 (Sec) 流程的实践融合到一个简化的流程中。使用这种方法&#xff0c;DevSecOps 团队能够确保将安全性集成到软件开发生命周期中&#xff0c;确保以“安全第一”的心态构建、部署和维护软件。在本教程中&…

自动驾驶学习笔记(四)——变道绕行仿真

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 仿真内容 启动Dreamview 开启Sim…

网络安全(黑客技术)——如何高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…

ChatGPT AIGC 实现数据分析可视化三维空间展示效果

使用三维空间图展示数据有以下一些好处&#xff1a; 1可视化复杂性&#xff1a;三维图可以展示三个或更多的变量&#xff0c;一眼就能看出数据各维度之间的关系&#xff0c;使复杂数据的理解和分析变得更为直观。 2检测模式和趋势&#xff1a;通过三维图&#xff0c;用户可以…

从零开始的stable diffusion

stable diffusion真的是横空出世&#xff0c;开启了AIGC的元年。不知你是否有和我一样的困惑&#xff0c;这AI工具好像并不是那么听话&#xff1f; 前言 我们该如何才能用好stable diffusion这个工具呢&#xff1f;AI究竟在stable diffusion中承担了什么样的角色&#xff1f;如…