练手项目层初阶1—《详解静态版本——通讯录管理系统》

news2024/10/9 22:24:43

在这里插入图片描述

文章目录

  • 🚩前言
    • 🔊 项目需求
    • 📚 项目知识点包含
    • 🧩项目框架
    • 📝框架拆解分析
      • ✨Struct_book.h 头文件解析
      • ✨Struct_book.c文件解析
      • ✨test_book.c文件解析
    • 📺演示效果
    • 🚀完整代码

🚩前言

俗话说:“学以致用!”,前面描述了C语言的各种知识,接下来,我们就运用所学,自己写一个练手项目——《静态通讯录管理系统》

🔊 项目需求

静态版本通讯录,主要完成对联系人信息的增、删、查、改、排序、显示功能。由于
初级练手项目,主要是为了熟悉和整体运用C语言知识。因此,对联系人的数据保存暂时没写,我会在后面加入保存功能。

📚 项目知识点包含

此练手小项目,主要会运用到结构体、结构体的嵌套、结构体数组、枚举、以及各种增删查改的简单算法,还有就是用分文件编写来管理该系统。其他都是C语言中各种的结构语句。

🧩项目框架

在这里插入图片描述

📝框架拆解分析

接下来对三个文件所包含的内容进行详解——>👇👇👇👇

✨Struct_book.h 头文件解析

在这里插入图片描述

下面对代码进行解析:👇👇

//对需要用到的常量用宏定义来表示,方便以后修改
#define MAX_NUMBER 100
#define MAX_NAME 100
#define MAX_SEX 20
#define MAX_TELE 12
#define MAX_ADDR 300

//枚举所有功能,它的常量刚好可以匹配上我们输入功能的数字。
enum Eu
{
    Exit,//0,退出
    Add,//1,添加
    Del,//2,删除
    Find,//3,查找
    Mod,//4,修改
    Sort,//5,排序
    Show//6,显示
};


//信息结构体
typedef struct PersonInformation
{
    char name[MAX_NAME];
    int age;
    char sex[MAX_SEX];
    char TeleNumber[MAX_TELE];
    char addr[MAX_ADDR];
}PeoInfo;
//直接用typedef给结构体struct PersonInformation命名为PeoInfo


//通讯录结构体
typedef struct Contact
{
    PeoInfo data[MAX_NUMBER];//储存联系人数据的结构体数组,
    //每个元素都是结构体类型
    int count;//记录成员数量
}Con;


void InitCon(Con* ptr);//初始化函数
void Add_Person_Information(Con* ptr);//添加函数
void Show_Person_Information(const Con* ptr);//打印信息函数
void Delete_Person_Information(Con* ptr);//删除指定元素信息
void Find_Person_Information(Con* ptr);//查找函数
void Modify_Person_Information(Con* ptr);//修改函数
void Sort_Person_Information(Con* ptr);//排序函数

上述代码中,主要的是:
//信息结构体
typedef struct PersonInformation
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char TeleNumber[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;

掌握结构体创建知识点就可以写出来了。

//通讯录结构体
typedef struct Contact
{
PeoInfo data[MAX_NUMBER];
int count;
}Con;

存储数据主要是结构体数组起的作用,因为用的是数组,存储大小是固定好的,通过宏定义来改变固定值,缺点就是定义小了不够存储,定义大了浪费空间。所以叫静态的通讯录。

✨Struct_book.c文件解析

在这里插入图片描述

下面是选取代码块详解:

void Delete_Person_Information(Con* ptr)
{
  
    assert(ptr);
    if (ptr->count == 0)
    {
        printf("通讯录为空,无信息可删除!\n");
        return;
    }
    printf("请输入要删除的联系人的姓名:\n");
    char name[MAX_NAME];
    scanf("%s", name);

    //查找
   int ret=Find_Information(ptr,name);
   
    //删除
   if (ret == -1)
   {
       printf("没找到,无法删除!\n");
       return;
    }
   for (int i = ret; i < ptr->count - 1; i++)//人数减去1,防止越界
   {
       ptr->data[i] = ptr->data[i + 1];//若删除最后一个也不影响,
       //因为最后人数会减去1
   }
   //人数减去1
   ptr->count--;
   printf("删除成功!\n");
  
   Show_Person_Information(ptr);
}

选取的是删除模块,在此模块需要注意的是循环条件和人数,没删除一个count得自减。

✨test_book.c文件解析

在这里插入图片描述

代码展示:

void menu()
{
    printf("\t\t\t\t**************************\n");
    printf("\t\t\t\t*****  Address Book  *****\n");
    printf("\t\t\t\t**************************\n");
    printf("\t\t\t\t********* 0、Exit ********\n");
    printf("\t\t\t\t********* 1、Add  ********\n");
    printf("\t\t\t\t********* 2、Del  ********\n");
    printf("\t\t\t\t********* 3、Find ********\n");
    printf("\t\t\t\t********* 4、Mod  ********\n");
    printf("\t\t\t\t********* 5、Sort ********\n");
    printf("\t\t\t\t********* 6、Show ********\n");
    printf("\t\t\t\t**************************\n");
}

static void test()
{
    Con con;//创建通讯录结构体变量

    InitCon(&con);//初始化通讯录结构体
   
    int input = 0;
    //menu();
    while(1)
    {
        menu();
        printf("请输入对应的功能——>:\n");
        scanf("%d", &input);
        switch (input)
        {
        case Add:
            Add_Person_Information(&con);
            break;
        case Del:
            Delete_Person_Information(&con);
            break;
        case Find:
            Find_Person_Information(&con);
            break;
        case Mod:
            Modify_Person_Information(&con);
            break;
        case Sort:
            Sort_Person_Information(&con);
            break;
        case Show:
            Show_Person_Information(&con);
            break;
        case Exit:
            printf("退出通讯录,欢迎下次使用!\n");
            exit(1);
        default:
            printf("输入有误,请重新输入:\n");
            break;
        }
        _getch();
        system("cls");//清屏
    }
}

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

📺演示效果

在这里插入图片描述

在这里插入图片描述

🚀完整代码

Struct_book.h

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


#define MAX_NUMBER 100
#define MAX_NAME 100
#define MAX_SEX 20
#define MAX_TELE 12
#define MAX_ADDR 300
//枚举所有功能
enum Eu
{
    Exit,
    Add,
    Del,
    Find,
    Mod,
    Sort,
    Show
};


//信息结构体
typedef struct PersonInformation
{
    char name[MAX_NAME];
    int age;
    char sex[MAX_SEX];
    char TeleNumber[MAX_TELE];
    char addr[MAX_ADDR];
}PeoInfo;


//通讯录结构体
typedef struct Contact
{
    PeoInfo data[MAX_NUMBER];
    int count;
}Con;


void InitCon(Con* ptr);//初始化函数
void Add_Person_Information(Con* ptr);//添加函数
void Show_Person_Information(const Con* ptr);//打印信息函数
void Delete_Person_Information(Con* ptr);//删除指定元素信息
void Find_Person_Information(Con* ptr);//查找函数
void Modify_Person_Information(Con* ptr);//修改函数
void Sort_Person_Information(Con* ptr);//排序函数


Struct_book.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Struct_Book.h"

void InitCon(Con* ptr)
{
    assert(ptr);
    ptr->count = 0;
    memset(ptr->data, 0, sizeof(ptr->data));
}


void Add_Person_Information(Con* ptr)
{
   
    assert(ptr);
    if (ptr->count == MAX_NUMBER)
    {
        printf("通讯录已满,无法添加!\n");
        return;
    }
    printf("请输入姓名:\n");
    scanf("%s", ptr->data[ptr->count].name);
    printf("请输入年龄:\n");
    scanf("%d", &(ptr->data[ptr->count].age));
    printf("请输入性别:\n");
    scanf("%s", ptr->data[ptr->count].sex);
    printf("请输入电话:\n");
    scanf("%s", ptr->data[ptr->count].TeleNumber);
    printf("请输入地址:\n");
    scanf("%s", ptr->data[ptr->count].addr);

    ptr->count++;
    printf("添加成功\n");
    Sleep(1000);
    system("cls");
}


void Show_Person_Information(const Con* ptr)
{
   
    assert(ptr);
    if (ptr->count == 0)
    {
        printf("通讯录为空,无法显示!\n");
        return;
    }
   
    printf("\n通讯录总人数:%d\n", ptr->count);
    printf("---------------------------------------------------------------------------------------------\n");

    printf("|%-12s\t\t%-2s\t%-2s\t\t%-12s\t\t%-20s|\n", "姓名", "年龄", "性别", "电话", "地址");
    for (int i = 0; i < ptr->count; i++)
    {
        printf("|%-12s\t\t%-2d\t%-2s\t\t%-12s\t\t%-20s|\n", ptr->data[i].name
            , ptr->data[i].age
            , ptr->data[i].sex
            , ptr->data[i].TeleNumber
            , ptr->data[i].addr);
    }
    printf("---------------------------------------------------------------------------------------------\n");

}

static int Find_Information(Con* pc, char* name1)
{
    assert(pc);
    for (int i = 0; i < pc->count; i++)
    {
        if (strcmp(pc->data[i].name, name1) == 0)//说明两个相同
        {
            return i;//返回当前位置
        }
    }
    //遍历完都没找到
    return -1;
}

void Delete_Person_Information(Con* ptr)
{
  
    assert(ptr);
    if (ptr->count == 0)
    {
        printf("通讯录为空,无信息可删除!\n");
        return;
    }
    printf("请输入要删除的联系人的姓名:\n");
    char name[MAX_NAME];
    scanf("%s", name);

    //查找
   int ret=Find_Information(ptr,name);
   
    //删除
   if (ret == -1)
   {
       printf("没找到,无法删除!\n");
       return;
    }
   for (int i = ret; i < ptr->count - 1; i++)//人数减去1,防止越界
   {
       ptr->data[i] = ptr->data[i + 1];//若删除最后一个也不影响,因为最后人数会减去1
   }
   //人数减去1
   ptr->count--;
   printf("删除成功!\n");
  
   Show_Person_Information(ptr);
}



void Find_Person_Information(Con* ptr)
{
  
    assert(ptr);
    if (ptr->count == 0)
    {
        printf("通讯录为空,无法查找!\n");
        return;
    }
    char name2[MAX_NAME];
    printf("请输入要查找的联系人的姓名:\n");
    scanf("%s", name2);
    int ret = Find_Information(ptr, name2);
    if (ret == -1)
    {
        printf("没找到!\n");
        return;
    }
   
    printf("此联系人信息如下:\n");
    printf("---------------------------------------------------------------------------------------------\n");

    printf("|%-12s\t\t%-2s\t%-2s\t\t%-12s\t\t%-20s|\n", "姓名", "年龄", "性别", "电话", "地址");
    printf("|%-12s\t\t%-2d\t%-2s\t\t%-12s\t\t%-20s|\n", ptr->data[ret].name
        , ptr->data[ret].age
        , ptr->data[ret].sex
        , ptr->data[ret].TeleNumber
        , ptr->data[ret].addr);
    printf("---------------------------------------------------------------------------------------------\n");

}



void Modify_Person_Information(Con* ptr)
{
  
    assert(ptr);
    if (ptr->count==0)
    {
        printf("通讯录为空,无法修改!\n");
        return;
    }
    printf("请输入要修改信息的联系人的姓名:\n");
    char name3[MAX_NAME];
    scanf("%s", name3);
    int ret = Find_Information(ptr, name3);
    if (ret == -1)
    {
        printf("没找到,无法修改!\n");
        return;
    }
    printf("修改进行中………\n");
    printf("请输入新的姓名:\n");
    scanf("%s", ptr->data[ret].name);
    printf("请输入新的年龄:\n");
    scanf("%d", &(ptr->data[ret].age));
    printf("请输入新的性别:\n");
    scanf("%s", ptr->data[ret].sex);
    printf("请输入新的电话:\n");
    scanf("%s", ptr->data[ret].TeleNumber);
    printf("请输入新的地址:\n");
    scanf("%s", ptr->data[ret].addr);
    printf("修改成功!\n");
   
    Show_Person_Information(ptr);
}


int compar_by_name(const void* e1, const void* e2)
{
    return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

int compar_by_age(const void* e1, const void* e2)
{
    return (((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age);
}


void Sort_Person_Information(Con* ptr)
{ 
 
    int num = 0;
    assert(ptr);
    if (ptr->count == 0)
    {
        printf("通讯录为空,无法排序!\n");
        return;
    }
    printf("\n请选择排序方式:1.姓名首字母、2.年龄排序\n");
    scanf("%d", &num);
    if (num == 1)
    {
        //void qsort (void* base, size_t num, size_t size,int (*compar)(const void*, const void*));
        qsort(ptr,ptr->count,sizeof(PeoInfo),compar_by_name);
        printf("排序成功!\n");
    }
    if (num == 2)
    {
        qsort(ptr, ptr->count, sizeof(PeoInfo), compar_by_age);
        printf("排序成功!\n");
    }
}

test_book.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Struct_Book.h"


void menu()
{
    printf("\t\t\t\t**************************\n");
    printf("\t\t\t\t*****  Address Book  *****\n");
    printf("\t\t\t\t**************************\n");
    printf("\t\t\t\t********* 0、Exit ********\n");
    printf("\t\t\t\t********* 1、Add  ********\n");
    printf("\t\t\t\t********* 2、Del  ********\n");
    printf("\t\t\t\t********* 3、Find ********\n");
    printf("\t\t\t\t********* 4、Mod  ********\n");
    printf("\t\t\t\t********* 5、Sort ********\n");
    printf("\t\t\t\t********* 6、Show ********\n");
    printf("\t\t\t\t**************************\n");
}

static void test()
{
    Con con;//创建通讯录结构体变量

    InitCon(&con);//初始化通讯录结构体
   
    int input = 0;
    //menu();
    while(1)
    {
        menu();
        printf("请输入对应的功能——>:\n");
        scanf("%d", &input);
        switch (input)
        {
        case Add:
            Add_Person_Information(&con);
            break;
        case Del:
            Delete_Person_Information(&con);
            break;
        case Find:
            Find_Person_Information(&con);
            break;
        case Mod:
            Modify_Person_Information(&con);
            break;
        case Sort:
            Sort_Person_Information(&con);
            break;
        case Show:
            Show_Person_Information(&con);
            break;
        case Exit:
            printf("退出通讯录,欢迎下次使用!\n");
            exit(1);
        default:
            printf("输入有误,请重新输入:\n");
            break;
        }
        _getch();
        system("cls");//清屏
    }
}

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

在这里插入图片描述

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

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

相关文章

Linux下Qt生成程序崩溃文件

文章目录 1.背景2.Qt编译生成程序2.1.profile模式的本质 3.执行程序&#xff0c;得到core文件4.代码定位4.1.直接使用gdb4.2.使用QtCreator 5.总结6.题外话6.1.profile模式和debug模式的区别 1.背景 在使用Qt时&#xff0c;假如在windows&#xff0c;当软件崩溃时&#xff0c;…

Linux 服务器间SSH免密码登录与拷贝文件(SCP)

适用背景 工作中频繁登录服务器和拷贝文件&#xff0c;都会提示输入密码在持续集成的场景下&#xff0c;自动部署应用时是没有人工干预的 解决方案 下面以实现A服务器到B服务器的免密码登录和拷贝文件为例&#xff0c;介绍相关的配置。&#xff08;即A访问B不需要输密码&…

不能在主机和虚拟机之间拷贝文本(虚拟机ubuntu16.04)

问题 ubuntu16.04不能在主机和虚拟机之间拷贝文本。 原因 vmware tools没安装好。 解决办法 重新安装vmware tools&#xff0c;步骤入下&#xff1a; 让虚拟机加载C:\Program Files (x86)\VMware\VMware Workstation\linux.iso光盘文件&#xff0c;设置如下&#xff1a; …

DHT11温湿度传感器使用视频教程分享

下载地址&#xff1a; 温湿度计(STCDHT11): https://url83.ctfile.com/d/45573183-60623983-9b7f6c?p7526 (访问密码: 7526)

使用 CloudDM 操作 PostgrgSQL 数据库

CloudDM 简介 CloudDM 是 ClouGence 公司推出的一款一站式数据库管理工具&#xff0c;使用它可以方便地访问和管理 MySQL、Oracle、PostgreSQL、阿里云 RDS、Greenplum、TiDB、Redis、StarRocks、Doris、SelectDB、SQL SERVER、ClickHouse、OceanBase 、PolarDB-X 、IBM Db2 等…

JVM之常用监控工具

JVM之常用监控工具 jps jinfo 获取配置信息 基本语法 jinfo [options] <pid>常用选项 -sysprops&#xff1a;显示JVM进程的系统属性。-flags&#xff1a;显示用于启动JVM的命令行标志和VM选项。-flag <name>&#xff1a;显示指定JVM标志的当前值。-flag [|-]&…

vue想要突破全局样式限制又不影响别的页面样式怎么办

<!-- 用scope盖不住全局&#xff0c;随意来个class匹配私定&#xff0c;搜索关键词&#xff1a;不要随便改&#xff0c;乱打class名 --> <style> .lkajsdfjkalsfhkljashkflhaskl .el-input.el-input--default.el-input--suffix { width: 160px !important; } …

亮数据Bright Data,引领高效数据采集新体验

随着互联网和大数据的日益普及&#xff0c;我们对于高速、安全和无限畅通的网络体验追求越发迫切&#xff0c;随之而来的网络安全和隐私保护变得越来越重要。IP代理作为一种实用的代理工具&#xff0c;可以高效地帮我们实现网络数据采集&#xff0c;有效解决网络安全问题&#…

【Java集合进阶】list常见的方法和五种遍历方式数据结构

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

《QT实用小工具·十》本地存储空间大小控件

1、概述 源码放在文章末尾 本地存储空间大小控件&#xff0c;反应电脑存储情况&#xff1a; 可自动加载本地存储设备的总容量/已用容量。进度条显示已用容量。支持所有操作系统。增加U盘或者SD卡到达信号。 下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #if…

jsp中使用cookie+session实现自动登录功能

1、需求分析 在实际运用中的用户登陆网站中&#xff0c;多提供有记住密码和自动登陆等功能&#xff0c;方便同一用户短时间内不用再输入用户名和密码等繁琐信息可以快捷登陆。本案例将模拟用户自动登陆功能。 1.2、设计思路&#xff08;实现原理&#xff09; 创建login.html页面…

Golang学习系列1-pprof性能调优

1. pprof 简述 一位亦师亦友的话让我记忆犹新&#xff0c;他说“学习一个新事务&#xff0c;应该从三个方面入手what,why,how;且三者的重要程度应该是递减”。所以在本文的第一部分先叙述下pprof的what & why。 1.1 What&#xff1f; pprof是golang自身提供的一种性能分…

Python 代码混淆工具概述

在保护Python代码安全方面&#xff0c;有多种混淆工具可供选择&#xff0c;包括 Cython, Nuitka, Pyminifier 和 IPA guard。本文将介绍这些工具的特点和适用情况&#xff0c;以及在实际应用中的注意事项。 &#x1f4dd; 摘要 本文探讨了几种常见的 Python 代码混淆工具&am…

Acwing.1388 游戏(区间DP对抗思想)

题目 玩家一和玩家二共同玩一个小游戏。 给定一个包含 N个正整数的序列。 由玩家一开始&#xff0c;双方交替行动。 每次行动可以在数列的两端之中任选一个数字将其取走&#xff0c;并给自己增加相应数字的分数。&#xff08;双初始分都是 0分&#xff09; 当所有数字都被…

7种2024年算法优化BP,实现回归,单/多变量输入,单/多步预测功能,机器学习预测全家桶再更新!...

截止到本期MATLAB机器学习预测全家桶&#xff0c;一共发了19篇关于机器学习预测代码的文章。算上这一篇&#xff0c;一共20篇&#xff01;参考文章如下&#xff1a; 1.五花八门的机器学习预测&#xff1f;一篇搞定不行吗&#xff1f; 2.机器学习预测全家桶&#xff0c;多步预测…

《C++程序设计》阅读笔记【2-程序结构】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;《C程序设计》阅读笔记 本文对应的PDF源文件请关注微信公众号程序员刘同学&#xff0c;回复C程序设计获取下载链接。 1 程序结构1.1 外部存储类型1.2 静态存储类型1.2.1 静态全局变量1.2.…

【重学C语言】四、运算符和表达式

【重学C语言】四、运算符和表达式 概念左值与右值运算符一元运算符二元运算符三元运算符 优先级结合性 基本运算符赋值运算符算术运算符复合赋值运算符位运算符应用条件和逻辑运算符条件运算符逻辑运算符逻辑短路逻辑与&#xff08;&&&#xff09;的短路行为逻辑或&…

数学结论在dsa中的应用

1. LC 3102 最小化曼哈顿距离 VP周赛391 T4。这是个结论题目。 首先曼哈顿距离是需要两个数对而不是两个数去进行比较的&#xff0c;两个数之间你很轻易就知道差的绝对值最大是多少了&#xff0c;只要挑最大和最小两个数一减就可以了。 但是两个数对之间各项差的绝对值之和最…

了解以太坊虚拟机(EVM)

了解以太坊虚拟机&#xff08;EVM&#xff09; 以太坊虚拟机&#xff08;Ethereum Virtual Machine&#xff0c;简称EVM&#xff09;是以太坊网络的核心组件之一&#xff0c;它承担着智能合约执行的重要任务 特点 智能合约执行环境&#xff1a;EVM提供了一个安全的环境&#xf…

【C++STL详解 —— vector的介绍及使用】

【CSTL详解 —— vector的介绍及使用】 vector的介绍vector的使用vector的构造vector iterator 的使用begin和endrbegin和rend vector 空间增长问题size和capacityreserve和resizeempty vector 增删查改push_back和pop_backinsert和erasefindswap元素访问 vector 迭代器失效问题…