静态版通讯录——“C”

各位CSDN的uu你们好呀,之前小雅兰学过了一些结构体、枚举、联合的知识,现在,小雅兰把这些知识实践一下,那么,就让我们进入通讯录的世界吧


实现一个通讯录:

  1. 可以存放100个人的信息
  2. 每个人的信息:名字 性别 年龄 电话 地址
  3. 增加联系人
  4. 删除指定联系人
  5. 查找指定联系人
  6. 修改指定联系人
  7. 显示联系人信息
  8. 排序联系人(按照年龄/名字) 

通讯录和小雅兰之前写的三子棋和扫雷一样,都是多文件的形式

三子棋——“C”_认真学习的小雅兰.的博客-CSDN博客 

扫雷——“C”_认真学习的小雅兰.的博客-CSDN博客

  • test.c —— 测试通讯录的相关功能
  • Contact.h —— 声明
  • Contact.c —— 通讯录的实现模块

 表示一个人的信息:

//表示一个人的信息
typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
	char addr[30];
}PeoInfo;

改进:

#define MAX_NAME 20
#define MAX_SEX 5
#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;

这样确保如果以后想改信息,直接在#define那里修改,就不用在结构体中进行修改啦

通讯录:

typedef struct Contact
{
	PeoInfo data[MAX];//存放数据
	int sz;//记录通讯录中有效信息的个数
}Contact;

  

 初始化通讯录:

void InitContact(Contact* pc)
{
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
    //把data数组的所有内容都改成0
}

 增加指定联系人:

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

	pc->sz++;
	printf("添加成功\n");
}

显示联系人信息:

//显示联系人信息
void ShowContact(const Contact* pc)
{
	int i = 0;
	//姓名     年龄    性别     电话    地址
	//zhangsan  13     男    123456   北京
	//打印标题
	printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-15s %-4d %-5s %-12s %-30s\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)
{
	char name[MAX_NAME] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	//删除
	//1.找到要删除的人 - 位置(下标)
	printf("输入要删除人的名字:>");
	scanf("%s", name);
	int i = 0;
	int pos = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			pos = i;
			break;
		}
	}
	if (i == pc->sz)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//2.删除-删除pos位置上的元素
	for (i = pos;i<pc->sz-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

不考虑重名的情况

 另一种写法:

typedef struct Contact
{
	PeoInfo data[MAX];//存放数据
	int sz;//记录通讯录中有效信息的个数
}Contact,*pContact;
void DelContact(pContact pc)
void SearchContact(pContact pc)

 我们发现,在很多函数的功能里面都需要用到查找一个人的名字,所以可以把这个功能封装成一个函数

int FindByName(Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			return i;
		}
	}
	if (i == pc->sz)
	{
		return -1;
	}
}
 //删除指定联系人
void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	//删除
	//1.找到要删除的人 - 位置(下标)
	printf("输入要删除人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//2.删除-删除pos位置上的元素
	int i = 0;
	for (i = pos;i<pc->sz-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}

 我们又发现,上述封装的函数,如果是这么写,写成if语句,只有i==pc->sz的情况下才返回-1,这样可能会不周全,应该这么写:

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

 然后,如果我们不想把这个查找名字函数功能的代码暴露出来,可以加static。

因为:此函数只是一个辅助功能的函数,都没有在头文件中声明

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

 查找指定联系人:

//查找指定联系人
void SearchContact(const Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人的名字:>");
	scanf("%s", name);
	//查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	//打印
	printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-15s %-4d %-5s %-12s %-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 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	//修改
	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");
}

 排序通讯录元素:

 

 

//排序通讯录元素
//按照名字来排序
int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
	ShowContact(pc);
	printf("排序成功\n");
}

当然,这个静态版本的通讯录有很多不足

  • 通讯录的大小是固定大小 —— 100个元素
  • 当通讯录退出后,重新运行,之前的信息都丢了,当前通讯录中的信息都是保存在内存中的,程序退出,内存就回收,下一次重新运行程序,内存重新分配,之前的数据就不见了。(动态内存分配)
  • 数据能够永久的保存??? —— 文件

源代码如下:

Contact.h的内容:

#pragma once
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//表示一个人的信息
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 sz;//记录通讯录中有效信息的个数
}Contact; 
//初始化通讯录
void InitContact(Contact *pc);

//增加指定联系人
void AddContact(Contact* pc);

//显示联系人信息
void ShowContact(const Contact* pc);

//删除指定联系人
void DelContact(Contact* pc);

//查找指定联系人
void SearchContact(const Contact* pc);

//修改指定联系人
void ModifyContact(Contact* pc);

//按照名字来排序
void SortContact(Contact* pc);

Contact.c的内容:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
//初始化通讯录
void InitContact(Contact* pc)
{
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
}
//增加指定联系人
void AddContact(Contact* pc)
{
	if (pc->sz == MAX)
	{
		printf("通讯录已满,无法增加\n");
		return;
	}
	printf("请输入姓名:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("添加成功\n");
}
//显示联系人信息
void ShowContact(const Contact* pc)
{
	int i = 0;
	//姓名     年龄    性别     电话    地址
	//zhangsan  13     男    123456   北京
	//打印标题
	printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-15s %-4d %-5s %-12s %-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(const Contact* pc, char name[])
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			return i;
		}
	}
	return -1;
}
//删除指定联系人
void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除\n");
		return;
	}
	//删除
	//1.找到要删除的人 - 位置(下标)
	printf("输入要删除人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//2.删除-删除pos位置上的元素
	int i = 0;
	for (i = pos;i<pc->sz-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功\n");
}
//查找指定联系人
void SearchContact(const Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的人的名字:>");
	scanf("%s", name);
	//查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	//打印
	printf("%-15s %-4s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-15s %-4d %-5s %-12s %-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 };
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return;
	}
	//修改
	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");
}
//排序通讯录元素
//按照名字来排序
int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void SortContact(Contact* pc)
{
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_by_name);
	ShowContact(pc);
	printf("排序成功\n");
}

test.c的内容:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Contact.h"
void menu()
{
	printf("#############################################\n");
	printf("#############        1.add       ############\n");
	printf("#############        2.del       ############\n");
	printf("#############        3.search    ############\n");
	printf("#############        4.modify    ############\n");
	printf("#############        5.show      ############\n");
	printf("#############        6.sort      ############\n"); 
	printf("#############        0.exit      ############\n");
	printf("#############################################\n");
}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};
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;
}


 好啦,小雅兰今天的内容就到这里啦,嘿嘿,后续会更新动态版通讯录的,敬请期待噢!!!

 

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

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

相关文章

FPGA打砖块游戏设计(有上板照片)VHDL

这是一款经典打砖块游戏,我们的努力让它更精致更好玩,我们将它取名为打砖块游戏(Flyball),以下是该系统的一些基本功能:  画面简约而经典,色彩绚丽而活泼,动画流畅  玩家顺序挑战3个不同难度的级别,趣味十足  计分功能,卡通字母数字  4条生命值,由生命条显示…

智能扑克牌识别软件(Python+YOLOv5深度学习模型+清新界面)

摘要&#xff1a;智能扑克牌识别软件利用视觉方法检测和识别日常扑克牌具体花色与数字&#xff0c;快速识别牌型并标注结果&#xff0c;帮助计算机完成扑克牌对战的前期识别步骤。本文详细介绍基于深度学习的智能扑克牌识别软件&#xff0c;在介绍算法原理的同时&#xff0c;给…

[数据结构]排序算法

目录 常用排序算法的实现&#xff1a;&#xff1a; 1.排序的概念及其运用 2.插入排序 3.希尔排序 4.选择排序 5.冒泡排序 6.堆排序 7.快速排序 8.归并排序 9.排序算法复杂度及稳定性分析 10.排序选择题练习 常用排序算法的实现&#xff1a;&#xff1a; 1.排序的概念及其运用…

【C语言蓝桥杯每日一题】——排序

【C语言蓝桥杯每日一题】—— 排序&#x1f60e;前言&#x1f64c;排序&#x1f64c;总结撒花&#x1f49e;&#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&#xff1a;全神贯注的上吧&#xff01;&#xff01;&#xff01; &#x1f60a;作者简介&am…

【千题案例】TypeScript获取两点之间的距离 | 中点 | 补点 | 向量 | 角度

我们在编写一些瞄准、绘制、擦除等功能函数时&#xff0c;经常会遇到计算两点之间的一些参数&#xff0c;那本篇文章就来讲一下两点之间的一系列参数计算。 目录 1️⃣ 两点之间的距离 ①实现原理 ②代码实现及结果 2️⃣两点之间的中点 ①实现原理 ②代码实现及结果 3…

当下的网络安全行业前景到底怎么样?还能否入行?

前言网络安全现在是朝阳行业&#xff0c;缺口是很大。不过网络安全行业就是需要技术很多的人达不到企业要求才导致人才缺口大常听到很多人不知道学习网络安全能做什么&#xff0c;发展前景好吗&#xff1f;今天我就在这里给大家介绍一下。网络安全作为目前比较火的朝阳行业&…

给程序加个进度条吧,1行Python代码,快速添加~

大家好&#xff0c;这里是程序员晚枫。 你在写代码的过程中&#xff0c;有没有遇到过以下问题&#xff1f; 已经写好的程序&#xff0c;想看看程序执行的进度&#xff1f; 在写代码批量处理文件的时候&#xff0c;如何显示现在处理到第几个文件了&#xff1f; &#x1f446…

真要被00后职场整顿了?老员工纷纷表示真的干不过.......

最近聊到软件测试的行业内卷&#xff0c;越来越多的转行和大学生进入测试行业。想要获得更好的待遇和机会&#xff0c;不断提升自己的技能栈成了测试老人迫在眉睫的问题。 不论是面试哪个级别的测试工程师&#xff0c;面试官都会问一句“会编程吗&#xff1f;有没有自动化测试…

dfs和bfs能解决的问题

一.理解暴力穷举之dfs和bfs暴力穷举暴力穷举是在解决问题中最常用的手段&#xff0c;而dfs和bfs算法则是这个手段的两个非常重要的工具。其实&#xff0c;最简单的穷举法是直接遍历&#xff0c;如数列求和&#xff0c;遍历一个数组即可求得所问答案&#xff0c;这与我在前两篇博…

【lwIP(第二章)】以太网DMA

目录一、以太网DMA描述符简介二、以太网DMA描述符结构三、如何追踪描述符总结一、以太网DMA描述符简介 发送&#xff1a;不需要CPU的参与下&#xff0c;把描述符指向的缓冲区数据传输到Tx FIFO当中 接收&#xff1a;不需要CPU的参与下&#xff0c;将Rx FIFO中的数据传输到描述符…

3 天交付新需求?极狐GitLab APP 「极限编程 XP」实践

近日&#xff0c;中移物联网有限公司、北京青云科技股份有限公司联合举办的 “2023 云原生重庆站技术分享会” 如期召开。会上&#xff0c;极狐(GitLab) 高级解决方案架构师刘剑桥带来《云原生极限编程 101》主题分享。本文整理自演讲内容&#xff0c;你可以阅读到&#xff1a;…

java调用chatgpt接口,实现专属于自己的人工智能助手

文章目录前言导包基本说明请求参数响应参数创建请求和响应的VO类代码编写使用最后说明前言 今天突然突发奇想&#xff0c;就想要用java来调用chatget的接口&#xff0c;实现自己的聊天机器人&#xff0c;但是网上找文章&#xff0c;属实是少的可怜(可能是不让发吧)。找到了一些…

【数据结构与算法】什么是双向链表?并用代码手动实现一个双向链表

文章目录一、什么是双向链表二、双向链表的简单实现一、什么是双向链表 我们来看一下这个例子&#xff1a; 在一个教室里&#xff0c;所有的课桌排成一列&#xff0c;如图 相信在你们的读书生涯中&#xff0c;老师肯定有要求你们记住自己的前后桌是谁。所以该例子中&#x…

J 砍竹子

砍竹子 【问题描述】 这天&#xff0c;小明在砍竹子&#xff0c;他面前有 n 棵竹子排成一排&#xff0c;一开始第 i 棵竹子的高度为 hi . 他觉得一棵一棵砍太慢了&#xff0c;决定使用魔法来砍竹子。魔法可以对连续的一段相同高度的竹子使用&#xff0c;假设这一段竹子的高度…

菜鸟刷题Day5

⭐作者&#xff1a;别动我的饭 ⭐专栏&#xff1a;菜鸟刷题 ⭐标语&#xff1a;悟已往之不谏&#xff0c;知来者之可追 一.一维数组的动态和&#xff1a;1480. 一维数组的动态和 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个数组 nums 。数组「动态和」的计算公式…

为了之后找工作不被虐,每天刷3道《剑指offer》Day-1

本文已收录于专栏&#x1f33b;《刷题笔记》文章目录前言&#x1f496; 1、二维数组中的查找题目描述思路&#x1f496; 2、替换空格题目描述思路&#x1f496; 3、从尾到头打印链表题目描述思路一&#xff08;反转函数&#xff09;思路二&#xff08;递归&#xff09;思路二&a…

Celery使用:优秀的python异步任务框架

目录Celery 简介介绍安装基本使用Flask使用Celery异步任务定时任务Celery使用Flask上下文进阶使用参考停止Worker后台运行Celery 简介 介绍 Celery 是一个简单、灵活且可靠的&#xff0c;处理大量消息的分布式系统&#xff0c;并且提供维护这样一个系统的必需工具。 它是一个…

文心一言 vs GPT-4 —— 全面横向比较

文心一言 vs GPT-4 —— 全面横向比较 3月15日凌晨&#xff0c;OpenAI发布“迄今为止功能最强大的模型”——GPT-4。我第一时间为大家奉上了体验报告《OpenAI 发布GPT-4——全网抢先体验》。 时隔一日&#xff0c;3月16日下午百度发布大语言模型——文心一言。发布会上&#…

4万字企业数字化转型大数据湖项目建设和运营综合解决方案WORD

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用&#xff0c;如有侵权请联系删除。部分资料内容&#xff1a; 3.1.4沙盒管理 利用Docker, 基于kubernetes主打的容器技术与微服务应用基础平台&#xff0c;HDFS和YARN均可依此建模&#xff0c;为上层应用提供微服…

不愧是2023年就业最难的一年,还好有车企顶着~

就业龙卷风已经来临&#xff0c;以前都说找不到好的工作就去送外卖&#xff0c;但如今外卖骑手行业都已经接近饱和状态了&#xff0c;而且骑手们的学历也不低&#xff0c;本科学历都快达到了30%了&#xff0c;今年可以说是最难找到工作的一年。 像Android 开发行业原本就属于在…
最新文章