C语言实现简易通讯录

目录

普通版

功能需求

模块设计 

test.c模块实现 

contact.h模块实现

类型的声明

函数的声明

头文件、枚举、宏定义

contact.c 模块实现

初始化通讯录

增加联系人

显示所有联系人的信息

 查找函数 

删除指定联系人

查找指定联系人 

修改指定联系人

 进阶版通讯录(动态存储)

模块一test.c

模块二Contact.h

模块三Contact.c


普通版

功能需求

实现通讯录的增加、删除、查找、修改、显示 

模块设计 

分为三个模块

test.c      测试通讯录

contact.h     函数和类型的声明

contact.c     函数的实现

test.c模块实现 

首先我们得有我们的主函数

int main()
{test();return 0;
}

然后我们在实现test函数时,我们需要完成通讯录的显示菜单,还需要操作者可以进行选择

 具体实现如下

void menu()
{printf("***********      通讯录     *************\n");printf("******* 1 添加联系人  2 删除联系人 ******\n");printf("******* 3 查找联系人  4 修改联系人 ******\n");printf("******* 5 显示通讯录  0 退出通讯录 ******\n");printf("*****************************************\n");
}void test()
{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 EXIT :printf("退出通讯录\n");break;default: printf("输入错误,重新输入\n");break;}} while (input);}

而在此处出现的结构体Contact与枚举会在contact.h模块进行声明,还有函数InitContact声明也会在contact.h说明,具体实现会在contact.c模块进行实现

contact.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;

sz存在的意义为可以知道通讯录里有多少联系人

函数的声明

//函数声明//初始化通讯录
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);

头文件、枚举、宏定义

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
enum OPTION//枚举
{EXIT,//0ADD,DEL,SEARCH,MODIFY,SHOW
};

contact.c 模块实现

初始化通讯录

void InitContact(Contact* pc)
{assert(pc);//断言,防止pc为空指针memset(pc->data, 0, sizeof(pc->data));//进行复制,每个字节都为0pc->sz = 0;
}

增加联系人

这里注意我们需要我们需要进行判断如果通讯录已满,我们就得进行提醒

void AddContact(Contact* pc)
{assert(pc);if (pc->sz >= MAX){printf("通讯录已满,无法添加");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)
{assert(pc);int i = 0;//打印列标题printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-10s\t%-4d\t%-5s\t%-12s\t%-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 (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//找不到
}

删除指定联系人

这里的删除其实是后面的数据对前面的数据的覆盖

实现如下

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

查找指定联系人 

只需要按名字进行查找,最后进行输出就好,实现如下

void SearchContact(const Contact* pc)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法查找\n");return;}char name[MAX_NAME] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1)printf("要查找的人不存在\n");else{printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据printf("%-10s\t%-4d\t%-5s\t%-12s\t%-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)
{assert(pc);if (pc->sz == 0){printf("通讯录为空,无法修改\n");return;}char name[MAX_NAME] = { 0 };printf("请输入要修改人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (pos == -1)printf("要修改的人不存在\n");else{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");}
}

 进阶版通讯录(动态存储)

进阶版通讯录实现与普通版通讯录区别在于,普通版通讯录的存储是有限,是提前规定好的,而进阶版则是可以根据用户的实际需求进行扩容。具体实现同样分为三个模块

模块一test.c

此模块没有什么变化

#include "Contact.h"void menu()
{printf("***********      通讯录     *************\n");printf("******* 1 添加联系人  2 删除联系人 ******\n");printf("******* 3 查找联系人  4 修改联系人 ******\n");printf("******* 5 显示通讯录  0 退出通讯录 ******\n");printf("*****************************************\n");
}void test()
{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 EXIT :printf("退出通讯录\n");break;default: printf("输入错误,重新输入\n");break;}} while (input);}int main()
{test();return 0;
}

模块二Contact.h

由于变为了动态存储所以这里的结构的声明有一些变化

#include <stdlib.h>#include <string.h>
#include <assert.h>
#include <stdio.h>#define DEFAULT_SZ 3
#define INC_SZ 2
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30enum OPTION//枚举
{EXIT,//0ADD,DEL,SEARCH,MODIFY,SHOW
};//类型的声明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;//指向了存放数据的空间int sz;//记录的当前放的有效元素的个数int capacity;//通讯录当前的最大容量
}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);

模块三Contact.c

修改如下

//静态版本
//void InitContact(Contact* pc)
//{
//	assert(pc);
//	memset(pc->data, 0, sizeof(pc->data));
//	pc->sz = 0;
//}//动态的版本
void InitContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));if (pc->data == NULL){perror("InitContact");return;}pc->sz = 0;pc->capacity = DEFAULT_SZ;
}//静态版本
//
//void AddContact(Contact* pc)
//{
//	assert(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");
//}int CheckCapacity(Contact* pc)
{if (pc->sz == pc->capacity){PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ)*sizeof(PeoInfo));if (ptr == NULL){perror("CheckCapacity");return 0;}else{pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功\n");return 1;}}return 1;
}//动态的版本
void AddContact(Contact* pc)
{assert(pc);if (pc->sz == MAX)if (0 == CheckCapacity(pc)){printf("通讯录已满,无法添加\n");return;}void AddContact(Contact* pc)printf("成功增加联系人\n");
}void ShowContact(const Contact* pc)
{assert(pc);void ModifyContact(Contact* pc)}
}//释放空间
void DestroyContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}

若有需要完整版的宝子或者在使用时出现了一些问题,都可以评论区评论或私信博主!!!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于scrcpy的Android群控项目重构,获取Android屏幕元素信息并编写自动化事件

系列文章目录 基于scrcpy的远程调试方案 基于scrcpy的Android群控项目重构 基于scrcpy的Android群控项目重构 进阶版 基于scrcpy的Android群控项目重构&#xff0c;获取Android屏幕元素信息并编写自动化事件&#xff08;视频&#xff09; 基于scrcpy的Android群控项目重构…

面向个人的免费组态软件:摩尔信使MThings

产品官网 现代工业自动化各行各业中均广泛应用工控上位机软件&#xff0c;但同时也面临着一系列挑战和复杂性。 多样化设备组网&#xff1a;工控系统包含不同厂家的各类硬件和设备&#xff0c;如传感器、执行器、PLC等。工控上位机软件需要与不同类型的设备进行集成和通信&am…

C++常用库函数 2.字符分类函数

函数名&#xff1a;isalnum 函数原型&#xff1a;int isalnum(int c)&#xff1b; 所需头文件&#xff1a;<cctype> 功能&#xff1a;测试 c 是否字母或数字。 返回值&#xff1a;如果 c 在 A&#xff5e;Z、a&#xff5e;z 或0&#xff5e;9的范围内&#xff0c;则返回…

[Linux] 最基础简单的线程池 及其 单例模式的实现

本篇文章主要用到线程相关内容, 下面是博主关于线程相关内容的文章: [Linux] 线程同步分析&#xff1a;什么是条件变量&#xff1f;生产者消费者模型是什么&#xff1f;POSIX信号量怎么用&#xff1f;阻塞队列和环形队列模拟生产者消费者模型 [Linux] 线程互斥分析: 多线程的问…

使用claude 2的文档分析功能

复制一段较长的文本内容&#xff0c;比如json文件。 https://zh.annas-archive.org/db/aarecord/md5:ba19176859126615bba9f35110f7492e.json 打开claude 2网页。 在输入框中粘贴内容&#xff0c;会自动生成一个past.txt图标。 输入要问的问题&#xff0c;按回车。 结果如下&a…

外网SSH远程连接linux服务器「cpolar内网穿透」

文章目录 1. Linux CentOS安装cpolar2. 创建TCP隧道3. 随机地址公网远程连接4. 固定TCP地址5. 使用固定公网TCP地址SSH远程 本次教程我们来实现如何在外公网环境下&#xff0c;SSH远程连接家里/公司的Linux CentOS服务器&#xff0c;无需公网IP&#xff0c;也不需要设置路由器。…

分层解耦-IOCDI-DI详解

目录 Bean注入 小结 依赖注入的注解 Resource和Autowired区别 Bean注入 Autowired注解&#xff0c;默认是按照类型进行依赖注入&#xff0c;如果存在多个相同类型的bean就会报错 解决方案 Primary&#xff08;设置bean的优先级&#xff09; Qualifier&#xff08;通过bean…

搭建Serv-U FTP服务器共享文件并外网远程访问「无公网IP」

文章目录 1. 前言2. 本地FTP搭建2.1 Serv-U下载和安装2.2 Serv-U共享网页测试2.3 Cpolar下载和安装 3. 本地FTP发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 科技日益发展的今天&#xff0c;移动电子设备似乎成了我们生活的主角&#xff0c;智能…

mp4视频太大怎么压缩?简单视频压缩方法分享

视频压缩是一种常见的操作&#xff0c;它可以起到很多有用的效果。通过压缩视频&#xff0c;我们可以减小视频文件的大小&#xff0c;从而节省存储空间和传输带宽。此外&#xff0c;压缩后的视频可以更快地加载和播放&#xff0c;提高观看体验&#xff0c;特别是对于网络传输较…

中国地图数据可视化制作,python的pyecharts模块读取excel中国着色地图可视化

数据格式如下&#xff1a; import pandas as pd from pyecharts import options as opts from pyecharts.charts import Map from pyecharts.globals import ChartType# 读取Excel数据 data pd.read_excel(C:\\Users\\Administrator\\Desktop\\国内数据.xlsx)# 创建地图实例 m…

性能测试 jmeter 的 beanshell 脚本的 2 个常用例子

目录 前言&#xff1a; Bean Shell 内置变量大全 例子 1 例子 2 技巧 前言&#xff1a; JMeter是一个功能强大的性能测试工具&#xff0c;而Beanshell是JMeter中用于编写脚本的一种语言。 在利用 jmeter 进行接口测试或者性能测试的时候&#xff0c;我们需要处理一些复杂…

Halcon——C#中在HWindow上显示字符串遇见的问题及解决方案

Halcon——C#中在HWindow上显示字符串遇见的问题及解决方案 前言一、HWindow上显示字符串的两种方式1. DispText函数2. WriteString函数 二、DispText函数与WriteString函数的区别三、遇见的问题及解决方案“HALCON error #5123: Wrong window type in operator disp_text”“H…