实现一个通讯录

news2024/11/20 3:36:32

目录

项目要求及功能实现

通讯录的代码实现

contact.h:

contanct.c

main.c


项目要求及功能实现

1、可以存放100个人的信息

2、每个人的信息

名字

性别

年龄

电话

地址

3、增加联系人

4、删除指定联系人

5、查找指定联系人

6、修改指定联系人

7、显示联系人信息

8、排序联系人(按照年龄/名字)

main.c //测试通讯录的相关功能

contact.h //通讯录的声明

contanct.c //通讯录的实现模块

通讯录的代码实现

如果是静态版本的设计的话会有以下的问题

1、通讯录的大小是固定大小 - 100个元素

2、当通讯录退出后,重新运行,之前的信息都丢了

当前通讯录中的信息都是保存在内存中的,程序退出,内存就回收,下一次重新运行程序,内存重新分配,之前的数据就不见了。

数据能够永久的保存? -文件

所以引入了动态版本的设计

contact.h:

//
// Created by yiming Zhang on 11/28/23.
//

#ifndef ADDRESS_BOOK_CONTACT_H
#define ADDRESS_BOOK_CONTACT_H

#endif //ADDRESS_BOOK_CONTACT_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 5
#define MAX_ADDR 5

//动态使用:
#define DEFAULT_SZ 3//默认容量
#define INC_SZ 2    //每次扩充那么多

//表示一个人的信息
typedef struct PeoInfo
{
    char name[MAX_NAME];
    int age;
    char sex[MAX_SEX];
    char tele[MAX_TELE];
    char addr[MAX_ADDR];
}PeoInfo;//使用typedef进行重命名

//静态版本的设计
//typedef struct Contact
//{
//    PeoInfo data[MAX];//存放数据
//    int sz;//记录通讯录中的
//}Contact,*pContact;

//动态的版本
//1、默认能够存放3个人的信息
//2、不够的话,每次增加2个人信息
typedef struct Contact
{
    PeoInfo *data;//data指向了存放数据的空间
    int sz;//记录通讯录中的有效信息个数
    int capacity;//通讯录当前的容量
}Contact,*pContact;

//初始化通讯录
void InitContact(Contact *pc);

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

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

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

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

//修改通讯录
void ModifyContact(pContact pc);

//排序通讯录元素
void SortContact(pContact pc);

//销毁通讯录
void DestroyContact(pContact pc);

contanct.c

//
// Created by yiming Zhang on 11/28/23.
//
#include "contact.h"

//静态的版本
//void InitContact(Contact *pc)
//{
//    pc->sz = 0;
//    memset(pc->data,0,sizeof (pc->data));
//}

//动态的版本
void InitContact(Contact *pc)
{
    pc->data = (PeoInfo*)malloc(DEFAULT_SZ* sizeof(PeoInfo));
    if(pc->data == NULL)
    {
        printf("通讯录初始化失败:%s\n", strerror(errno));
        return;
    }
    pc->sz = 0;
    pc->capacity = DEFAULT_SZ;
}

//静态的版本
//void AddContact(Contact* pc)
//{
//    if(pc->sz == MAX)
//    {
//        printf("通讯录已满,无法增加\n");
//        return;
//    }
//    printf("请输入名字:>\n");
//    scanf("%s",pc->data[pc->sz].name);
//    printf("请输入年龄:>\n");
//    scanf("%d",&(pc->data[pc->sz].age));
//    printf("请输入性别:>\n");
//    scanf("%s",pc->data[pc->sz].sex);
//    printf("请输入电话:>\n");
//    scanf("%s",pc->data[pc->sz].tele);
//    printf("请输入地址:>\n");
//    scanf("%s",pc->data[pc->sz].addr);
//    pc->sz++;
//    printf("添加成功\n");
//}

//动态的版本
void CheckCapacity(Contact * pc)
{
    if(pc->sz == pc->capacity)//判断是不是容量满了
    {
        PeoInfo *ptr = (PeoInfo*)realloc(pc->data,(pc->capacity + INC_SZ)* sizeof(PeoInfo));
        if(ptr == NULL)
        {
            printf("CheckCapacity:%s\n", strerror(errno));
            return;
        } else
        {
            pc->data = ptr;
            pc->capacity += INC_SZ;
            printf("扩容成功,当前容量:%d\n",pc->capacity);
        }

    }
}
void AddContact(Contact* pc)
{
    CheckCapacity(pc);
    printf("请输入名字:>\n");
    scanf("%s",pc->data[pc->sz].name);
    printf("请输入年龄:>\n");
    scanf("%d",&(pc->data[pc->sz].age));
    printf("请输入性别:>\n");
    scanf("%s",pc->data[pc->sz].sex);
    printf("请输入电话:>\n");
    scanf("%s",pc->data[pc->sz].tele);
    printf("请输入地址:>\n");
    scanf("%s",pc->data[pc->sz].addr);
    pc->sz++;
    printf("添加成功\n");
}
void ShowContact(const Contact *pc)
{
    int i;
    //姓名    //年龄    //性别    //电话    //地址
    //zhangsan 20      男        123456    北京

    //打印标题
    printf("%-11s %-4s %-5s %-12s %-30s\n","姓名","年龄","性别","电话","地址");
    //打印数据
    for (i = 0;i < pc->sz;i ++)
    {
        printf("%-10s %-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(pContact pc,char *name)
{
    int i;
    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;
    }
    int i;
    //2.删除 - 删除pos位置上的数据
    for (i = pos;i<pc->sz-1;i++)
    {
        pc->data[i] = pc->data[i+1];
    }
    pc->sz--;
    printf("删除成功\n");
}

void SearchContact(const pContact pc)
{
    char name[MAX_NAME] = {0};
    printf("请输入要查找人的名字:>");
    scanf("%s",name);
    int pos = FindByname(pc,name);
    if (pos == -1)
    {
        printf("要查找的人不存在\n");
        return;
    } else
    {
        //打印
        //打印标题
        printf("%-11s %-4s %-5s %-12s %-30s\n","姓名","年龄","性别","电话","地址");
        //打印数据
        printf("%-10s %-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(pContact pc)
{
    char name[MAX_NAME] = {0};
    printf("请输入要修改人的名字:>");
    scanf("%s",name);
    int pos = FindByname(pc,name);
    if (pos == -1)
    {
        printf("要修改的人不存在\n");
        return;
    }
    //修改
    printf("请输入名字:>\n");
    scanf("%s",pc->data[pos].name);
    printf("请输入年龄:>\n");
    scanf("%d",&(pc->data[pos].age));
    printf("请输入性别:>\n");
    scanf("%s",pc->data[pos].sex);
    printf("请输入电话:>\n");
    scanf("%s",pc->data[pos].tele);
    printf("请输入地址:>\n");
    scanf("%s",pc->data[pos].addr);
    printf("修改成功\n");
}

//按名字来排序
static int cmp_by_name(const void* e1,const void* e2)
{
    return strcmp(((PeoInfo*)e1)->name,((PeoInfo*)e2)->name);
}
void SortContact(pContact pc)
{
    qsort(pc->data,pc->sz, sizeof(PeoInfo),cmp_by_name);
    printf("排序成功\n");
}

void DestroyContact(pContact pc)
{
    free(pc->data);
    pc->data = NULL;
    pc->capacity = 0;
    pc->sz = 0;
    printf("释放内存\n");
}

main.c

#include "contact.h"

void menu()
{
    printf("****************************\n");
    printf("****** 1.add     2.del   ***\n");
    printf("****** 3.search  4.modify***\n");
    printf("****** 5.show   6.sort   ***\n");
    printf("****** 0.exit            ***\n");
    printf("****************************\n");
}
enum    Option
{
    EXIT,
    ADD,
    DEL,
    SEARCH,
    MODIFY,
    SHOW,
    SORT

};

int main()
{
    int input;
    Contact con;//通讯录
    //初始化通讯录
    InitContact(&con);
    do
    {
        menu();
        printf("请输入:>\n");
        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:
                DestroyContact(&con);
                printf("退出通讯录\n");
                break;
            default:
                printf("输入错误\n");
                break;
        }
    }
    while (input);
    return 0;
}

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

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

相关文章

运维笔记111

运维笔记 Navicat中查询指定字段名所在的表名tomcat设置JVM的初始堆内存修改catalina.sh文件修改完保存并关闭tomcat启动tomcat 查询数据库连接数查询是否存在死锁 Navicat中查询指定字段名所在的表名 SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME‘替换成你要…

Redis-Redis 高级数据结构 HyperLogLog与事务

Redis 高级数据结构 HyperLogLog HyperLogLog(Hyper [ˈhaɪpə(r)] ) 并不是一种新的数据结构 ( 实际类型为字符串类 型) &#xff0c;而是一种基数算法 , 通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是 IP 、 Email 、 ID 等。 如…

【brew】Mac上安装vue3

先安装node。 这里我从其他博客找的方案&#xff0c;原始脚本下载太慢了。 cnpm的安装&#xff1a; 让npm更快一点。 npm install -g cnpm --registryhttps://registry.npm.taobao.org安装vue脚手架 2.0版本&#xff1a;sudo npm install -g vue-cli 3.0版本&#xff1a; sud…

对话式数据需求激增,景联文科技提供高质量多轮对话数据定制采集标注服务

大模型的快速发展使得数据服务需求激增&#xff0c;产品整体处于供不应求状态。对话式数据集成为当下需求热点&#xff0c;人们对于更复杂、更真实的多轮对话数据需求不断增加&#xff0c;定制化服务占据市场需求主流。 通过对多轮对话数据的训练&#xff0c;模型可以更好地理解…

解析Top-K问题及堆排序算法

Top-K问题是在海量数据中找到最大或最小的K个元素&#xff0c;它在实际应用中非常常见&#xff0c;例如专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。在面对大规模数据时&#xff0c;直接对数据进行排序可能效率低下&#xff0c;因为排序的时间复杂度通常为O(n lo…

Notepad++批量添加引号

工作中经常会遇到这样情景&#xff1a;业务给到一批订单号&#xff0c;需要查询这批订单的某些字段信息。在where条件中需要传入这些订单号的数组&#xff0c;并且订单号用引号引起&#xff0c;用引号隔开。 字符串之间长度相同 可以按住CtrlAlt和鼠标左键选中区域&#xff0…

IDEA如何配置Git 遇到问题的解决

新建项目 点击 会变红 会生成.git隐藏文件 配置远程仓库路径&#xff1a;点击Manage Remotes&#xff1a;将远程仓库的链接放到这里&#xff1a; 得到如下样式&#xff1a; 此时提交到本地仓库 点击add&#xff0c;添加到暂存文件&#xff1a; 此时文件变绿&#xf…

力扣日记11.28-【二叉树篇】二叉树的最小深度

力扣日记&#xff1a;【二叉树篇】二叉树的最小深度 日期&#xff1a;2023.11.28 参考&#xff1a;代码随想录、力扣 111. 二叉树的最小深度 题目描述 难度&#xff1a;简单 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点…

Gitee-PicGo-Typora

Gitee-PicGo-Typora 问题引出 问题1&#xff1a;根据相关法律法规和政策&#xff0c;您的部分文件因存在敏感信息而无法显示 就在昨晚&#xff0c; 我在记笔记的时候&#xff0c;发现之前配置的七牛云图床出了问题&#xff1a; 1、根据相关法律法规和政策&#xff0c;您的部…

联邦学习(Federated Learning)

联邦学习&#xff08;Federated Learning&#xff09;是一种保护用户隐私的分布式机器学习方法&#xff0c;在联邦学习中&#xff0c;模型的训练是在分布式的客户端设备上进行的&#xff0c;而模型的更新则是在中央服务器上进行的。联邦学习的目标是通过共享模型而不是原始数据…

C# 使用 Fody 监控方法执行时间

写在前面 在做性能调优的时候&#xff0c;经常需要跟踪具体方法的执行时间&#xff1b;通过插入Stopwatch的方案对代码的侵入性太高了&#xff0c;所以引入了 MethodTimer.Fody 类库&#xff0c;采用编译时注入的方式给方法动态加上Stopwatch 跟踪代码&#xff0c;只需要在目标…

探索低代码之路——JNPF

目录 一、低代码行业现状 二、产品分析 1.可视化应用开发 2.流程管理 3.整个平台源码合作 三、架构和技术 技术栈 四、规划和展望 低代码平台&#xff08;Low-code Development Platform&#xff09;是一种让开发者通过拖拽和配置&#xff0c;而非传统的手动编写大量代…

geoserver根据数据字段动态设置样式

一、数据展示&#xff1a; 二、样式设置 <?xml version"1.0" encoding"UTF-8"?> <StyledLayerDescriptor version"1.0.0" xsi:schemaLocation"http://www.opengis.net/sld StyledLayerDescriptor.xsd" xmlns"http://…

从0开始学习JavaScript--JavaScript 模板字符串的全面应用

JavaScript 模板字符串是 ES6 引入的一项强大特性&#xff0c;它提供了一种更优雅、更灵活的字符串拼接方式。在本文中&#xff0c;将深入探讨模板字符串的基本语法、高级用法以及在实际项目中的广泛应用&#xff0c;通过丰富的示例代码带你领略模板字符串的魅力。 模板字符串…

Efficient RGB-T Tracking via Cross-Modality Distillation

摘要 目前大多数RGB-T跟踪器采用双流结构来提取单个RGB和热红外特征&#xff0c;并采用复杂的融合策略来实现多模态特征融合&#xff0c;这需要大量的参数&#xff0c;阻碍了它们的实际应用。另一方面&#xff0c;一个紧凑的RGB-T跟踪器可能具有计算效率&#xff0c;但由于特征…

01数仓平台 Hadoop介绍与安装

Hadoop概述 Hadoop 是数仓平台的核心组件。 在 Hadoop1.x 时代&#xff0c;Hadoop 中的 MapReduce 同时处理业务逻辑运算和资源调度&#xff0c;耦合性较大。在 Hadoop2.x 时代&#xff0c;增加了 Yarn。Yarn 只负责资源的调度&#xff0c;MapReduce 只负责运算。Hadoop3.x 在…

开源好用EasyImages简单图床源码

开源好用EasyImages简单图床源码分享&#xff0c;虽然它是开源程序&#xff0c;但功能一点也不弱&#xff0c;不仅支持多文件上传、文字/图片水印、支持API和鉴黄、还能自定义代码&#xff0c;最重要的是它不强制使用数据库运行&#xff0c;这就给我们的部署和维护带来极大方便…

GDPU 数据结构 天码行空12

文章目录 数据结构实验十二 图的遍历及应用一、【实验目的】二、【实验内容】三、实验源代码&#x1f37b; CPP&#x1f37b; C 数据结构实验十二 图的遍历及应用 一、【实验目的】 1、 理解图的存储结构与基本操作&#xff1b; 2、熟悉图的深度度优先遍历和广度优先遍历算法…

RabbitMQ快速学习之WorkQueues模型、三种交换机、消息转换器(基于SpringBoot)

文章目录 前言一、WorkQueues模型消息发送消息接收能者多劳 二、交换机类型1.Fanout交换机消息发送消息接收 2.Direct交换机消息接收消息发送 3.Topic交换机消息发送消息接收 三、编程式声明队列和交换机fanout示例direct示例基于注解 四、消息转换器总结 前言 WorkQueues模型…

借助 DPM 代码扫描的力量解锁医疗设备的可追溯性

在当今的医疗保健系统中&#xff0c;医疗设备的可追溯性变得比以往任何时候都更加重要。为了增强现代医疗保健领域的可追溯性和安全性&#xff0c;UDI 条形码充当唯一设备标识的标准&#xff0c;为医疗设备提供唯一标识符。 DataMatrix 代码&#xff08;或直接零件标记代码&am…