通讯录(C 语言)

目录

  • 一、通讯录设计思路
    • 1. 伪代码设计思路
    • 2. 代码设计思路
  • 二、代码实现
  • 三、程序运行演示
  • 四、整体分析

一、通讯录设计思路

1. 伪代码设计思路

通讯录可以用来存储 100 个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。

提供方法:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 查找指定联系人信息
  4. 修改指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 以名字排序所有联系人

2. 代码设计思路

通过对上述伪代码的分析,我们使用结构体 info_person 来表示个人信息。

// 个人信息结构声明
typedef struct info_person
{
	char name[20];  // 姓名
	char sex[5];  // 性别
	size_t age;  // 年龄
	char phone[12];  // 电话
	char address[40];  // 住址
}info_person;

接着再使用一个结构体 ContacksList 来表示通讯录,该通讯录包含一个结构体 info_person 数组,大小为 100,用来存储 100 个人的信息。此外还应该包含一个 size_t 类型的成员 size 用来表示当前存储个人信息的数量,这也方便了上述伪代码中要求的方法设计。

// 常量声明
#define SIZE_INFO 100

// 通讯录结构声明
typedef struct ContacksList
{
	info_person infos[SIZE_INFO];
	size_t size;
}ContacksList;

下面就是使用有意义的函数名来表示上述方法。

// 方法

// 1. 添加联系人信息
void AddContack(ContacksList* cl);

// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl, char* name);

// 3. 查找指定联系人信息
void FindContack(const ContacksList* cl, char* name);

// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl, char* name);

// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl);

// 6. 清空所有联系人
void ClearContack(ContacksList* cl);

// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl);

以上就是头文件 ContacksList.h 包含的基本内容,剩下的就是方法的实现和代码的测试。

二、代码实现

整体代码分成三个文件:头文件 ContacksList.h,方法定义文件 ContacksList.c,测试文件 test.c。由于头文件在前面已经给出,下面就只给出剩下两个文件。

方法定义文件 ContacksList.c

// 头文件
#include "ContacksList.h"
#include <assert.h>
#include <string.h>

// 方法

// 1. 添加联系人信息
void AddContack(ContacksList* cl)
{
	assert(cl);
	// 通讯录已满
	if (CAPACITY == cl->size)
	{
		printf("通讯录已满,添加失败!\n");
		return;
	}
	// 添加
	// 
	// 输入联系人的相关信息
	info_person tmp;
	printf("请输入联系人的信息->");
	printf("姓名: ");
	scanf("%s", tmp.name);
	printf("性别: ");
	scanf("%s", tmp.sex);
	printf("年龄: ");
	scanf("%zd", &tmp.age);
	printf("电话: ");
	scanf("%s", tmp.phone);
	printf("地址: ");
	scanf("%s", tmp.address);
	// 拷贝
	cl->infos[cl->size] = tmp;
	// 人数 +1
	++cl->size;
	printf("添加成功!\n");
}

// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl)
{
	assert(cl);
	// 删除
	//
	// 查找指定联系人
	char name[20];
	printf("请输入删除人的姓名: ");
	scanf("%s", name);
	int i = FindContack(cl, name);
	// 找到了
	if (-1 != i)
	{
		// 把该位置往后的联系人往前移
		while (i < cl->size - 1)
		{
			// 前移
			cl->infos[i] = cl->infos[i + 1];
			// 下一个
			++i;
		}
		// 联系人 -1
		--cl->size;
		printf("删除成功!\n");
	}
	else
	{
		printf("删除失败!\n");
	}
}

// 3. 查找指定联系人信息
int FindContack(const ContacksList* cl, char* name)
{
	assert(cl);
	// 通讯录为空
	if (0 == cl->size)
		return -1;

	// 输入查找人的姓名
	char tmp[20] = { 0 };
	if (NULL == name)
	{
		name = tmp;
		printf("请输入查找人的姓名: ");
		scanf("%s", name);
	}

	// 查找
	int i;
	for (i = 0; i < cl->size; ++i)
	{
		// 找到
		if (strcmp(cl->infos[i].name, name) == 0)
		{
			return i;
		}
	}
	// 没找到
	return -1;
}

// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl)
{
	assert(cl);
	// 查找指定联系人
	char name[20];
	printf("请输入修改人的姓名: ");
	scanf("%s", name);
	int i = FindContack(cl, name);
	// 找到了
	if (-1 != i)
	{
		// 输入联系人修改后的相关信息
		info_person tmp;
		printf("请输入联系人的信息->");
		printf("姓名: ");
		scanf("%s", tmp.name);
		printf("性别: ");
		scanf("%s", tmp.sex);
		printf("年龄: ");
		scanf("%zd", &tmp.age);
		printf("电话: ");
		scanf("%s", tmp.phone);
		printf("地址: ");
		scanf("%s", tmp.address);
		// 修改
		cl->infos[i] = tmp;
		printf("修改成功!\n");
	}
	else
	{
		printf("修改失败!\n");
	}
}

// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl)
{
	assert(cl);
	// 标题行
	printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");
	// 输出
	int i;
	for (i = 0; i < cl->size; ++i)
	{
		printf("%-10s%-8s%-8zd%-15s%-10s\n", cl->infos[i].name, cl->infos[i].sex, cl->infos[i].age, cl->infos[i].phone, cl->infos[i].address);
	}
}

// 6. 清空所有联系人
void ClearContack(ContacksList* cl)
{
	assert(cl);
	// 清空
	cl->size = 0;
}

// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl)
{
	assert(cl);
	// 冒泡排序
	int i;
	for (i = 0; i < cl->size - 1; ++i)
	{
		int j;
		for (j = 0; j < cl->size - 1 - i; ++j)
		{
			// 相邻比较
			if (strcmp(cl->infos[j].name, cl->infos[j + 1].name) > 0)
			{
				// 交换
				info_person tmp = cl->infos[j];
				cl->infos[j] = cl->infos[j + 1];
				cl->infos[j + 1] = tmp;
			}
		}
	}
	printf("按名字身升序排序成功!\n");
}

测试文件 test.c

// 头文件
#include "ContacksList.h"

// 菜单
void menu()
{
	printf("****************************************************\n");
	printf("***********1. Add          2. Delete   *************\n");
	printf("***********3. Find         4. Modify   *************\n");
	printf("***********5. Print        6. Clear    *************\n");
	printf("***********7. Sort         0. Exit     *************\n");
	printf("****************************************************\n");
}

int main()
{
	// 创建通讯录
	ContacksList cl = { {0}, 0 };
	// 选择操作
	int select = 0;
	int i = 0;
	do
	{
		// 菜单
		menu();
		// 选择
		printf("请选择: ");
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			AddContack(&cl);
			break;
		case 2:
			DeleteContack(&cl);
			break;
		case 3:
			i = FindContack(&cl, NULL);
			printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");
			printf("%-10s%-8s%-8zd%-15s%-10s\n", cl.infos[i].name, cl.infos[i].sex, cl.infos[i].age, cl.infos[i].phone, cl.infos[i].address);
			break;
		case 4:
			ModifyContack(&cl);
			break;
		case 5:
			PrintContack(&cl);
			break;
		case 6:
			ClearContack(&cl);
			break;
		case 7:
			SortByName(&cl);
			break;
		case 0:
			printf("退出通讯录!\n");
			break;
		default:
			printf("选择错误,请重新选择!\n");
			break;
		}
	} while (select);

	return 0;
}

三、程序运行演示

在这里插入图片描述

四、整体分析

该通讯录是一个静态通讯录,容量是固定的,当数据超出容量时不够存储,当数据少于容量时造成空间的浪费。后面作者会把该通讯录升级为动态通讯录,当容量不够的时候会进行增容。

在方法实现中,删除指定联系人函数 DeleteContack() 和修改指定联系人函数 ModifyContack() 都需要先找到指定的联系人,所以可以稍微修改一下查找指定联系人函数 FindContack(),然后再前面两个函数中调用该函数,这样就减少了代码的冗余。删除操作需要判断通讯录是否为空,插入操作需要判断通讯录是否已满。

当然读者可以自行根据需要进行修改,这里只提供一个大概思路和基础功能的实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入解析四种核心网络设备:集线器、桥接器、路由器和交换机

计算机网络系列课程《网络核心设备》 在现代网络技术中&#xff0c;集线器、桥接器、路由器和交换机扮演着至关重要的角色。本文&#xff0c;将深入探讨这四种设备的功能、工作原理及其在网络架构中的重要性。 集线器&#xff1a;基础网络连接设备 集线器&#xff08;Hub&…

01 Oracle 数据库存储结构深度解析:从数据文件到性能优化的全链路探究

文章目录 Oracle 数据库存储结构深度解析&#xff1a;从数据文件到性能优化的全链路探究一、Oracle存储结构的物理层次1.1 控制文件&#xff08;Control File&#xff09;1.2 联机重做日志文件&#xff08;Online Redo Log File&#xff09;1.3 数据文件&#xff08;Data File&…

Type-C转DP线方案

在现代数字化生活中&#xff0c;高清视频传输已成为日常需求的重要组成部分。无论是工作中的多屏协作&#xff0c;还是娱乐中的沉浸式体验&#xff0c;高清显示器都扮演着不可或缺的角色。然而&#xff0c;随着设备接口的多样化&#xff0c;如何高效地将Type-C设备连接至Displa…

【c++篇】:栈、队列、优先队列:容器世界里的秩序魔法 - stack,queue与priority_queue探秘

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;c篇–CSDN博客 文章目录 前言一.容器stack1.介绍2.成员函数3.模拟实现4.注意事项 二.容器qu…

Java基础——循环switch大数值更改器访问器深浅拷贝

目录 1.循环 2.switch多分支选择结构 3.大数值 4.浅拷贝&深拷贝 5.Arrays.sort排序 6.面向对象 7.更改器&访问器 1.循环 for-each循环 在 Java 中&#xff0c;for-each 循环&#xff08;也称为增强型 for 循环&#xff09;是一种用于遍历数组或集合&#xff08…

引入 axios,根据 api 文档生成调用接口

起步 | Axios Docs 安装 axios npm install axios 生成 api 调用接口【可选】 https://github.com/ferdikoomen/openapi-typescript-codegen 安装 npm install openapi-typescript-codegen --save-dev 然后执行生成代码 # http://localhost:8805/api/user/v3/api-docs&a…

wsl2+Ubuntu安装图形化界面(VNC方式)

本章教程,记录在wsl2+Ubuntu操作系统中安装可视化界面步骤。 一、安装桌面环境 尽量以root用户进行安装,避免因权限不足导致部分依赖无法安装。 sudo apt update sudo apt upgrade -y sudo apt install ubuntu-desktop由于可视化桌面程序安装包比较大,网速慢的小伙伴,需要耐…

Linux应用——线程池

1. 线程池要求 我们创建线程池的目的本质上是用空间换取时间&#xff0c;而我们选择于 C 的类内包装原生线程库的形式来创建&#xff0c;其具体实行逻辑如图 可以看到&#xff0c;整个线程池其实就是一个大型的 CP 模型&#xff0c;接下来我们来完成它 2. 整体模板 #pragma …

学习日记_241110_局部线性嵌入(Locally Linear Embedding, LLE)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

【我的 Anti-AV 学习手札】DLL注入

无敌舍友s神免杀学了一个阶段&#xff0c;达者为师&#xff0c;向s师傅学习&#xff01;&#xff01; ps&#xff1a;我的基础实在薄弱&#xff0c;WIN编程甚至都没做过&#xff0c;所以笔记翔实些 一、注入思路 1.在进程中开辟一段空间 2.存入dll绝对路径地址的字符串 3.使用…

【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)

关键词&#xff1a;一多、响应式、媒体查询、栅格布局、断点、UI 随着设备形态的逐渐增多&#xff0c;应用界面适配也面临着很大问题&#xff0c;在以往的安卓应用开发过程中&#xff0c;往往需要重新开发一套适用于大屏展示的应用&#xff0c;耗时又耗力&#xff0c;而鸿蒙提供…

linux 安装 mongodb

选择MongoDB版本 https://www.mongodb.com/try/download/community-kubernetes-operator 我的系统是centos7.9 这里只能最高只能选择mongo7 复制下载链接&#xff1a;https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-7.0.15.tgz 获取安装教程&#xff1a; h…

《深入浅出Apache Spark》系列②:Spark SQL原理精髓全解析

导读&#xff1a;SQL 诞生于 20 世纪 70 年代&#xff0c;至今已有半个世纪。SQL 语言具有语法简单&#xff0c;低学习门槛等特点&#xff0c;诞生之后迅速普及与流行开来。由于 SQL 具有易学易用的特点&#xff0c;使得开发人员容易掌握&#xff0c;企业若能在其计算机软件中支…

PostgreSQL pg-xact(clog)目录文件缺失处理

一、 背景 前些天晚上突然收到业务反馈&#xff0c;查询DB中的一个表报错 Could not open file "pg-xact/005E": No such file or directory. 两眼一黑难道是文件损坏了...登录查看DB日志&#xff0c;还好没有其他报错&#xff0c;业务也反馈只有这一个表在从库查询报…

Cursor的chat与composer的使用体验分享

经过一段时间的试用&#xff0c;下面对 Composer 与 Chat 的使用差别进行总结&#xff1a; 一、长文本及程序文件处理方面 Composer 在处理长文本时表现较为稳定&#xff0c;可以对长文进行更改而不会出现内容丢失的情况。而 Chat 在更改长的程序文件时&#xff0c;有时会删除…

MATLAB课程:AI工具辅助编程——MATLAB+LLMs

给出一些可能有用的方法辅助大家写代码。 方法一&#xff1a;MATLAB软件LLM (不太懂配置的同学们为了省事可以主要用这个方法) 方法一特别针对本门MATLAB教学课程&#xff0c;给出一种辅助ai工具的操作指南。MATLAB中可以安装MatGPT插件&#xff0c;该插件通过调用ChatGPT的API…

2.索引:SQL 性能分析详解

SQL性能分析是数据库优化中重要的一环。通过分析SQL的执行频率、慢查询日志、PROFILE工具以及EXPLAIN命令&#xff0c;能够帮助我们识别出数据库性能的瓶颈&#xff0c;并做出有效的优化措施。以下将详细讲解这几种常见的SQL性能分析工具和方法。 一、SQL 执行频率 SQL执行频率…

使用Go语言编写一个简单的NTP服务器

NTP服务介绍 NTP服务器【Network Time Protocol&#xff08;NTP&#xff09;】是用来使计算机时间同步化的一种协议。 应用场景说明 为了确保封闭局域网内多个服务器的时间同步&#xff0c;我们计划部署一个网络时间同步服务器&#xff08;NTP服务器&#xff09;。这一角色将…

深度学习经典模型之VGGNet

1 VGGNet 1.1 模型介绍 ​ VGGNet是由牛津大学视觉几何小组&#xff08;Visual Geometry Group, VGG&#xff09;提出的一种深层卷积网络结构&#xff0c;他们以7.32%的错误率赢得了2014年ILSVRC分类任务的亚军&#xff08;冠军由GoogLeNet以6.65%的错误率夺得&#xff09;和…

Android的BroadcastReceiver

1.基本概念&#xff1a;BroadCast用于进程间或者线程间通信 本质上是用Binder方法&#xff0c;以AMS为订阅中心&#xff0c;完成注册&#xff0c;发布&#xff0c;监听的操作。 2.简单实现的例子 package com.android.car.myapplication;import android.content.BroadcastRe…