【C/C++数据结构与算法】C语言通讯录

目录

contact.h头文件

contact.c源文件

main.c源文件


项目分析:

  • 通讯录项目需要用到的顺序表的数据结构,每个元素为一个联系人信息结构体
  • 通讯录功能有新增、删除、查找、修改、排序、打印、清空
  • 通讯录还要有读档和存档的功能,用文件的读写
  • 新增数据要考虑顺序容量问题,若满则扩
  • 删除数据要先找到数据,再从要删除数据的位置,循环将后面的数据前移覆盖
  • 查找数据用strstr比strcmp更好,这样能实现模糊查找
  • 排序用qsort函数,可以按照联系人姓名或者联系人电话号码进行排序

contact.h头文件

外部头文件包含:

#pragma once 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <Windows.h>
#include <string.h>

数据结构:

#define CAPACITY 4    //顺序表初始容量

typedef struct PeoInfo 
{
    char name[10];
    char phone[12];
}Peo;

typedef struct Contact 
{
    Peo* data;
    int size;
    int capacity;
}Con;

函数声明:

void Init(Con* con);    //初始化
void Add(Con* con);     //添加
void Del(Con* con);     //删除
void Find(Con* con);    //查找
void Mod(Con* con);     //修改
void Sort(Con* con);    //排序
void Print(Con* con);   //打印
void Destory(Con* con); //清空
void Load(Con* con);    //加载信息
void Save(Con* con);    //保存信息

contact.c源文件

void Init(Con* con) 初始化

#include "contact.h"

void Init(Con* con) 
{
    assert(con);
    con->data = (Peo*)malloc(sizeof(Peo) * CAPACITY);
    if (con->data == NULL) 
    {
        perror("init::malloc");
        exit(1);
    }
    con->size = 0;
    con->capacity = CAPACITY;
    Load(con);    //读档
}

void Add(Con* con)

void Del(Con* con) 数据增删

用临时变量结构体指针进行扩容,增加安全性

bool Empty(Con* con) 
{
    assert(con);
    return con->size == 0;
}    //判空

void Check(Con* con) 
{
    assert(con);
    if (con->size == con->capacity) 
    {
        Peo* tmp = (Peo*)realloc(con->data, sizeof(Peo) * (con->size + CAPACITY));
        if (tmp) 
        {
            con->data = tmp;
            con->capacity += CAPACITY;
        }
    }
}    //检查容量

void Add(Con* con) 
{
    assert(con);
    Check(con);
    printf("请输入姓名:");
    scanf("%s", con->data[con->size].name);
    printf("请输入号码:");
    scanf("%s", con->data[con->size].phone);
    printf("新增联系人成功:%s %s\n", con->data[con->size].name, con->data[con->size].phone);
    ++con->size;
}

void Del(Con* con) 
{
    assert(con);
    if (Empty(con)) 
    {
        printf("通讯录为空\n");
        return;
    }
    printf("请输入要删除的联系人姓名:");
    char del[20];
    scanf("%s", del);
    int i = 0;
    while (i < con->size) 
    {
        if (strcmp(del, con->data[i].name) == 0) 
        {
            int j = i;
            while (j < con->size - 1) 
            {
                strcpy(con->data[j].name, con->data[j + 1].name);
                strcpy(con->data[j].phone, con->data[j + 1].phone);
                ++j;
            }
        }
        ++i;
    }
}

void Find(Con* con) 模糊查询

void Find(Con* con) 
{
    assert(con);
    printf("请输入姓名/号码进行查询:");
    char find[20];
    scanf("%s", find);
    int count = 0;
    int i = 0;
    while (i < con->size) 
    {
        if (strstr(con->data[i].name, find) || strstr(con->data[i].phone, find)) 
        {
            printf("%10s %12s\n", con->data[i].name, con->data[i].phone);
            ++count;
        }
        ++i;
    }
    printf("共查询到 %d 条数据\n", count);
}

void Mod(Con* con) 数据修改

void Mod(Con* con) 
{
    assert(con);
    printf("请输入需要修改信息的联系人姓名:");
    char mod[20];
    scanf("%s", mod);
    int i = 0;
    while (i < con->size) 
    {
        if (strcmp(mod, con->data[i].name) == 0) 
        {
            printf("请更新姓名:");
            scanf("%s", con->data[i].name);
            printf("请更新号码:");
            scanf("%s", con->data[i].phone);
            return;
        }
        ++i;
    }
    printf("联系人未查询到\n");
}

void Sort(Con* con) 数据排序

int cmp_name(const void* e1, const void* e2) 
{
    return strcmp((*(Peo*)e1).name, (*(Peo*)e2).name);
}

int cmp_phone(const void* e1, const void* e2) 
{
    return strcmp((*(Peo*)e1).phone, (*(Peo*)e2).phone);
}

void Sort(Con* con) 
{
    assert(con);
    printf("请选择排序方式(1.cmp_name   2.cmp_phone):");
    int choose;
    scanf("%d", &choose);
    if (choose == 1) 
    {
        qsort(con->data, con->size, sizeof(Peo), cmp_name);
        printf("已按姓名排序成功\n");
    }
    else if (choose == 2) 
    {
        qsort(con->data, con->size, sizeof(Peo), cmp_phone);
        printf("已按号码排序成功\n");
    }
    else 
    {
        printf("输入错误,排序失败\n");
    }
}

void Print(Con* con) 打印

void Destory(Con* con) 销毁、清空

void Print(Con* con) 
{
    assert(con);
    if (Empty(con)) 
    {
        printf("通讯录为空\n");
        return;
    }
    int i = 0; 
    printf("         联系人   电话号码\n");
    while (i < con->size) 
    {
        printf("%03d: %10s %12s\n", i, con->data[i].name, con->data[i].phone);
        ++i;
    }
}

void Destory(Con* con) 
{
    assert(con);
    free(con->data);
    con->data = (Peo*)malloc(sizeof(Peo) * CAPACITY);
    if (con->data == NULL) 
    {
        perror("destory::malloc");
        exit(1);
    }
    con->size = 0;
    con->capacity = CAPACITY;
}

void Load(Con* con) 读档

void Save(Con* con) 存档

void Load(Con* con) 
{
    assert(con);
    FILE* pfRead = fopen("contact.txt", "rb");
    if (pfRead == NULL) 
        return;

    Peo tmp = { 0 };
    while (fread(&tmp, sizeof(Peo), 1, pfRead)) 
    {
        Check(con);
        con->data[con->size] = tmp;
        ++con->size;
    }
    fclose(pfRead);
    pfRead = NULL;
}

void Save(Con* con) 
{
    assert(con);
    FILE* pfWrite = fopen("contact.txt", "wb");
    if (pfWrite == NULL) 
    {
        perror("pfWrite::fopen");
        exit(1);
    }
    int i = 0;
    while (i < con->size) 
    {
        fwrite(con->data + i, sizeof(Peo), 1, pfWrite);
        ++i;
    }
    fclose(pfWrite);
    pfWrite = NULL;
}

main.c源文件

#include "contact.h"

void Menu() 
{
    printf("\n------------------------\n");
    printf("-----    0. 退出   -----\n");
    printf("-----    1. 新增   -----\n");
    printf("-----    2. 删除   -----\n");
    printf("-----    3. 查找   -----\n");
    printf("-----    4. 修改   -----\n");
    printf("-----    5. 排序   -----\n");
    printf("-----    6. 打印   -----\n");
    printf("-----    7. 清空   -----\n");
    printf("------------------------\n");
    printf("请输入选项:");
}

int main() 
{
    Con con;
    Init(&con);
    int input;
    do 
    {
        Menu();
        scanf("%d", &input);
        system("cls");
        switch (input) 
        {
        case 0:
            Save(&con);
            printf("退出通讯录\n");
            return;
        case 1:
            Add(&con);
            break;
        case 2:
            Del(&con);
            break;
        case 3:
            Find(&con);
            break;
        case 4:
            Mod(&con);
            break;
        case 5:
            Sort(&con);
            break;
        case 6:
            Print(&con);
            break;
        case 7:
            Destory(&con);
            break;
        default:
            break;
        }
    } while (input);
    return 0;
}

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

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

相关文章

日志是什么?耗时2个月搞懂Linux日志

这里写目录标题 日志基本介绍日志管理服务日志轮替 日志基本介绍 日志是用来记录重大事件的工具。 日志文件是重要的系统信息文件&#xff0c;其中记录了很多重要的系统事件。包括用户的登录信息&#xff0c;系统的启动信息&#xff0c;系统的安全信息&#xff0c;邮件相关信息…

ChatGPT:数字时代革新与展望

ChatGPT&#xff1a;数字时代革新与展望 AGI 未来的愿景&#xff1a;建安全有益的 AGI OpenAI团队对AGI的展望&#xff1a; 我们希望 AGI 能够赋予人类在宇宙中最大程度地繁荣发展的能力。我们不期望未来是一个不合格的乌托邦&#xff0c;但我们希望将好的最大化&#xff0c;将…

【云计算 | Azure】微软 Azure 基础解析(九)Azure 标识、身份管理、Azure AD 的功能与用途

本系列博文还在更新中&#xff0c;收录在专栏&#xff1a;「Azure探秘&#xff1a;构建云计算世界」 专栏中。 本系列文章列表如下&#xff1a; 【Azure】微软 Azure 基础解析&#xff08;三&#xff09;云计算运营中的 CapEx 与 OpEx&#xff0c;如何区分 CapEx 与 OpEx 【A…

国产MCU-CW32F030开发学习--按键检测

国产MCU-CW32F030开发学习–按键检测 bsp_key 按键驱动程序用于扫描独立按键&#xff0c;具有软件滤波机制&#xff0c;采用 FIFO 机制保存键值。可以检测 如下事件&#xff1a; 按键按下。 按键弹起。 长按键。 长按时自动连发。 我们将按键驱动分为两个部分来介绍&#xff…

Spark大数据处理学习笔记1.5 掌握Scala内建控制结构

文章目录 一、学习目标二、条件表达式&#xff08;一&#xff09;语法格式&#xff08;二&#xff09;执行情况&#xff08;三&#xff09;案例演示任务1、根据输入值的不同进行判断任务2、编写Scala程序&#xff0c;判断奇偶性 三、块表达式&#xff08;一&#xff09;语法格式…

电弧打火机方案,点烟器单片机开发方案

市面上的打火机除了明火之外&#xff0c;还有电热丝、电弧两种类型的点烟器。电热丝在使用过程中会变细并且烧断。宇凡微推出的电弧打火机方案&#xff0c;该点烟器芯片为宇凡微单片机YF系列&#xff0c;电弧点烟器IC性价比高。 一、电弧打火机方案的原理 电弧打火机使用的是电…

【git切换分支/tag】git stash保存暂不提交的更改

目录 问题git stash使用方法git stash pop 还原修改 git stash使用、修改指定tag的代码 其他git指令 问题 情景&#xff1a;分支1上开发新功能&#xff0c;临时切换到其他分支或tag上修改bug。 1、直接切换&#xff1a;如果没有冲突&#xff0c;分支1的修改会带到要切换的分支…

拉普拉斯方程解决有介质导体球壳问题

一个内径和外径分别为和的导体球壳&#xff0c;带电荷&#xff0c;同心地包围着一个的导体球&#xff0c;使这个导体球接地&#xff0c;求空间各点的电势和这个导体球的感应电荷 我们不难发现&#xff0c;球对称性非常强&#xff0c;电势只和半径有关系 所以我们可以假设电势为…

【GitLab】-HTTP Basic: Access denied.remote:You must use a personal access token

写在前面 本文简要说明GitLab配置accessToken以及双因子认证&#xff08;Two-factor authentication&#xff09;。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.配置accessToken3.克隆项目4.双因子认证 三、参考资料写在后面 一、场景描述 在使用账号和密码的方式拉取公…

Alex-Net 与 VGG-16

Alex-Net 由加拿大多伦多大学的 Alex Krizhevsky、Ilya Sutskever(G. E. Hinton 的两位博士生)和 Geoffrey E. Hinton 提出&#xff0c;网络名“Alex-Net”即 取自第一作者名。 下图所示是 Alex-Net 的网络结构&#xff0c;共含五层卷积层和三层全连接层。其中&#xff0c;Ale…

【Vue3 生态】Vue Router 路由知识概览

前言 在 Web 前端开发中&#xff0c;路由是非常重要的一环&#xff0c;但是路由到底是什么呢&#xff1f; 从路由的用途上讲 路由是指随着浏览器地址栏的变化&#xff0c;展示给用户不同的页面。 从路由的实现原理上讲 路由是URL到函数的映射。它将 URL 和应用程序的不同部分…

01 React入门、虚拟DOM

总结 一、React 入门 1.1 特点 高性能、声明式、组件化、单向响应的数据流、JSX扩展、灵活 1.2 React初体验 <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewpo…

软件 安全,处理威胁STRIDE模型

微软威胁分析工具&#xff1a; https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling?azure-portaltrue STRIDE 是微软定义的6中威胁 身份假冒&#xff08;Spoofing&#xff09; 身份假冒&#xff0c;即伪装成某对象或某人。例如&#xff0c;我们通过伪…

1-简单回归问题

一.梯度下降&#xff08;gradient descent&#xff09; 1.预测函数 这里有一组样本点&#xff0c;横纵坐标分别代表一组有因果关系的变量 我们的任务是设计一个算法&#xff0c;让机器能够拟合这些数据&#xff0c;帮助我们算出参数w 我们可以先随机选一条过原点的直线&#xf…

无人机电池能不能上高铁以及什么型号的电池可以上高铁

无人机电池能不能上高铁以及什么型号的电池可以上高铁 高铁关于电池的限制电池参数介绍可上高铁的无人机锂电池6S电池3S电池 高铁关于电池的限制 2022年7月1日起施行的《铁路旅客禁止、限制携带和托运物品目录》规定,充电宝、锂电池单块额定能量不超过100Wh 电池参数介绍 明…

HarmonyOS学习路之开发篇—Java UI框架(DependentLayout)

DependentLayout DependentLayout是Java UI框架里的一种常见布局。与DirectionalLayout相比&#xff0c;拥有更多的排布方式&#xff0c;每个组件可以指定相对于其他同级元素的位置&#xff0c;或者指定相对于父组件的位置。 支持的XML属性DependentLayout的共有XML属性继承自…

SpringBoot不在使用@Validated 做参数校验但是不想在Controller层怎么办?

目录 场景再现&#xff1a; 怎么做&#xff1f; 遇到了什么问题&#xff1f; 怎么实现&#xff1f; 场景再现&#xff1a; 某API接口接受加密的json字符串&#xff0c;接受字符串之后先进行解密处理&#xff0c;解密完成之后还要进行参数校验处理&#xff0c;如果参数不合规…

使用 TensorFlow.js 将机器学习引入您的 Web 应用程序

如何使用 TensorFlow.js 在您的 Web 应用程序中实施机器学习 原文作者: Abhay Singh Rathore 机器学习 (ML) 不再是一个崇高、遥不可及的概念。借助 TensorFlow.js 等库&#xff0c;开发人员现在可以将 ML 整合到他们的 Web 应用程序中。例如&#xff0c;您可以创建一个系统&am…

Springcloud之Feign、Hystrix、Ribbon如何设置超时时间

一&#xff0c;概述 我们在微服务调用服务的时候&#xff0c;会使用hystrix、feign和ribbon&#xff0c;比如有一个实例发生了故障而该情况还没有被服务治理机制及时的发现和摘除&#xff0c;这时候客户端访问该节点的时候自然会失败。 所以&#xff0c;为了构建更为健壮的应…

美味度配方

8 种配料每种配料可以放 1 到 5 克&#xff0c;美味度为配料质量之和&#xff0c;给定一个美味度 n&#xff0c;求解 8 种配料的所有搭配方案及方案数量 。 (本笔记适合学了 Python 循环&#xff0c;正在熟炼的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a…