【详解】通讯录项目

目录

通讯录项目要求:

引言:

步骤如下:

用户的数据类型:

初始化循序表:

菜单:

添加联系人:

删除联系人:

修改联系人:

查找联系人:

查看通讯录:

头文件:

(1)Contact.h

(2)Seqlist.h

.c文件

(1)Contact.c

(2)Contest.c

(3)SeqList.c

结语:


通讯录项目要求:

c语言基础要求:结构体,动态内存管理,循序表

通讯录功能要求:

(1)至少能够存储100个人的通讯信息

(2)能够保存用户信息:名字,性别,年龄,电话,地址等

(3)增加联系人

(4)查找指定联系人

(5)删除指定联系人

(6)修改指定联系人

(7)显示联系人信息

引言:

随着c语言结构体和顺序表的逐渐学习深入,我们就可以完成一个通讯录的小项目,通过实现它来检查自己的学习情况和查缺补漏。👏👏👏

步骤如下:

说明:由于通讯录是由循序表的基本运算构成的,故下面的各种操作都只给出在顺序表基础上的完成的,在文章最后会给出循序表的基本运算。

基本运算的函数名如下:

void SLInit(SL* ps) 初始化

void SLDestroy(SL* ps) 销毁

void SLPrint(SL* ps) 打印

void SLCheckCapacity(SL* ps) 扩容

void SLPushBack(SL* ps, ElemType x)尾插

void SLInsert(SL* ps, int pos, ElemType x)指定插入

void SLErase(SL* ps, int pos)删除指定数据

用户的数据类型:

//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char number[TEL_MAX];char address[ADDR_MAX];
}PeoInfo;

初始化循序表:

基本运算如上面给出的。

void InitContact(contact* con)
{SLInit(con);
}

菜单:

void menu()
{printf("********************通讯录******************\n");printf("*********1.添加联系人    2.删除联系人*******\n");printf("*********3.修改联系人    4.查找联系人*******\n");printf("*********5.查看通讯录    0. 退   出  *******\n");printf("********************************************\n");
}

效果如下:

添加联系人:

peoinfo是自定义的数据结构

void AddContact(contact* con)
{PeoInfo e;printf("请输入联系人姓名\n");scanf("%s", e.name);printf("请输入联系人年龄\n");scanf("%d", &e.age);printf("请输入联系人性别\n");scanf("%s", e.sex);printf("请输入联系人电话\n");scanf("%s", e.number);printf("请输入联系人住址\n");scanf("%s", e.address);SLPushBack(con, e);
}

运行结果如下:

删除联系人:

用一个name数组来存储输入的字符串,和通讯录对比若findindex大于0说明该联系人存在删除成功,若小于0说明不存在该联系人删除失败。

查找联系人的函数如下:

int FindNAME(contact* con, char name[])
{
    for (int i = 0; i < con->size; i++)
    {
        if (strcmp(con->arr[i].name, name) == 0)
            return i;
    }
    return -1;
}

void DelContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");//char name[NAME_MAX];scanf("%s",name);int findindex = FindNAME(con, name);if (findindex >= 0){SLErase(con, findindex);printf("删除联系人成功\n");}elseprintf("删除联系人失败\n");
}

运行结果如下:

修改联系人:

先查找联系人在进行修改和输入新的联系人,和上面的删除差不多。😊😊😊

void ContactModify(contact*con)
{char name[NAME_MAX];printf("请输入要修改联系人名称\n");scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("无此联系人\n");return;}else{printf("请输入联系人姓名\n");scanf("%s", con->arr[findindex].name);printf("请输入联系人年龄\n");scanf("%d", &con->arr[findindex].age);printf("请输入联系人性别\n");scanf("%s", con->arr[findindex].sex);printf("请输入联系人电话\n");scanf("%s", con->arr[findindex].number);printf("请输入联系人住址\n");scanf("%s", con->arr[findindex].address);printf("修改联系人成功\n");}}

运行结果如下:

查找联系人:

先输入要查找联系人的姓名,后通过FindNAME函数找到联系人对应的下标,进行判断,最后在把联系人对应的信息输出。

void ContactFind(contact* con)
{printf("请输入要查找的姓名\n");char name[NAME_MAX];scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("查无此人\n");return;}else{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%s %s %d %s %s\n",con->arr[findindex].name,con->arr[findindex].sex,con->arr[findindex].age,con->arr[findindex].number,con->arr[findindex].address);}}

运行如下:

查看通讯录:

void ShowContact(contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");for (int i = 0; i < con->size; i++){printf("%s %s %d %s %s\n",con->arr[i].name,con->arr[i].sex,con->arr[i].age,con->arr[i].number,con->arr[i].address);}
}

运行结果如下:

由于是个项目故要进行个功能的函数分装和头文件的引用,故下面我给出头文件和.c文件大家按照我给出的名字在编译器上创建即可运行。

头文件:

(1)Contact.h

声明通讯录的各种函数及结构体内容。

#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//前置声明//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char number[TEL_MAX];char address[ADDR_MAX];
}PeoInfo;
struct SeqList;
typedef struct SeqList contact;
//初始化通讯录
void InitContact(contact* con);
//添加通讯录数据
void AddContact(contact* con);
//删除通讯录数据
void DelContact(contact* con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact* con);
//销毁通讯录数据
void DestroyContact(contact* con);

(2)Seqlist.h

循序表的基本运算

#pragma once
//PeoInfo
#include "Contact.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
typedef PeoInfo ElemType;
typedef struct SeqList
{ElemType* arr;int capacity;int size;
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, ElemType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, ElemType x);
void SLPopFront(SL* ps);//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, ElemType x);
void SLErase(SL* ps, int pos);
//int SLFind(SL* ps, ElemType x);

.c文件

(1)Contact.c

通讯录的函数具体实现。

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
#include "Seqlist.h"
void InitContact(contact* con)
{SLInit(con);
}
void AddContact(contact* con)
{PeoInfo e;printf("请输入联系人姓名\n");scanf("%s", e.name);printf("请输入联系人年龄\n");scanf("%d", &e.age);printf("请输入联系人性别\n");scanf("%s", e.sex);printf("请输入联系人电话\n");scanf("%s", e.number);printf("请输入联系人住址\n");scanf("%s", e.address);SLPushBack(con, e);
}
int FindNAME(contact* con, char name[])
{for (int i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name) == 0)return i;}return -1;
}
void DelContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");//char name[NAME_MAX];scanf("%s",name);int findindex = FindNAME(con, name);if (findindex >= 0){SLErase(con, findindex);printf("删除联系人成功\n");}elseprintf("删除联系人失败\n");
}
void ShowContact(contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");for (int i = 0; i < con->size; i++){printf("%s %s %d %s %s\n",con->arr[i].name,con->arr[i].sex,con->arr[i].age,con->arr[i].number,con->arr[i].address);}
}
void ContactModify(contact*con)
{char name[NAME_MAX];printf("请输入要修改联系人名称\n");scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("无此联系人\n");return;}else{printf("请输入联系人姓名\n");scanf("%s", con->arr[findindex].name);printf("请输入联系人年龄\n");scanf("%d", &con->arr[findindex].age);printf("请输入联系人性别\n");scanf("%s", con->arr[findindex].sex);printf("请输入联系人电话\n");scanf("%s", con->arr[findindex].number);printf("请输入联系人住址\n");scanf("%s", con->arr[findindex].address);printf("修改联系人成功\n");}}
void ContactFind(contact* con)
{printf("请输入要查找的姓名\n");char name[NAME_MAX];scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("查无此人\n");return;}else{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%s %s %d %s %s\n",con->arr[findindex].name,con->arr[findindex].sex,con->arr[findindex].age,con->arr[findindex].number,con->arr[findindex].address);}}
void ContactDesTroy(contact* con)
{SLDestroy(con);
}

(2)Contest.c

主函数,将Contact.c里面的函数调用,用一个swich来进行多功能的通讯录,通过do,while的特性先运行一次再判断要不要继续,符合我们日常玩游戏的逻辑,最后不要忘了一定要销毁我们开辟的空间哦。💖💖💖

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void menu()
{printf("********************通讯录******************\n");printf("*********1.添加联系人    2.删除联系人*******\n");printf("*********3.修改联系人    4.查找联系人*******\n");printf("*********5.查看通讯录    0. 退   出  *******\n");printf("********************************************\n");
}
int main()
{contact con;int op=-1;InitContact(&con);do{menu();printf("请选择\n");scanf("%d", &op);switch (op){case 1://添加联系人AddContact(&con);break;case 2:DelContact(&con);break;//删除联系人case 3:ContactModify(&con);break;//修改联系人case 4:ContactFind(&con);break;//查找联系人case 5:ShowContact(&con);break;//查看通讯录case 0:printf("退出程序.....\n");return 0;//退   出default:printf("输入错误,请重新输入\n");break;//}} while (op!=0);ContactDesTroy(&con);return 0;}

(3)SeqList.c

循序表基本运算的实现。

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void SLInit(SL* ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}
void SLDestroy(SL* ps)
{free(ps->arr);ps->capacity = ps->size = 0;ps = NULL;
}
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
void SLCheckCapacity(SL* ps)
{if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;ElemType* tmp = (ElemType*)realloc(ps->arr, sizeof(ElemType) * newcapacity);if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}
void SLPushBack(SL* ps, ElemType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}
void SLInsert(SL* ps, int pos, ElemType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

易错点:

(1)头文件里面不能再包含头文件,及头文件不能嵌套。

(2)对应使用c语言的库函数一定要将对应的头文件带上(如realloc要加上#include <stdlib.h>),不带的话运行就会出错,代码一多还很难找到,编译器的提示也不是很准确,故建议大家一用到上面库函数一定要把头文件马上写上不要等到最后再来(会忘掉)。

(3)前置声明,因为头文件的引用不能嵌套,故要想引用别的头文件的内容可以进行前置声明例如:

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

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

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

相关文章

《WebKit 技术内幕》之七(1): 渲染基础

《WebKit 技术内幕》之七&#xff08;1&#xff09;&#xff1a; 渲染基础 WebKit的布局计算使用 RenderObject 树并保存计算结果到 RenderObject 树。 RenderObject 树同其他树&#xff08;如 RenderLayer 树等&#xff09;&#xff0c;构成了 WebKit 渲染的为要基础设施。 1…

【RT-DETR有效改进】Google | EfficientNetV1一种超轻量又高效的网络 (附代码 + 添加教程)

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持Re…

python算法与数据结构---排序和归并排序

学习目标 掌握归并排序的基本原理使用python语言解答归并排序题目 归并排序 原理及过程 将两个有序的数组合并成一个有序数组称为从上往下分解&#xff1a;把当前区间一分为二&#xff0c;直至分解为若干个长度为1的子数组从上往下的合并&#xff1a;两个有序的子区域两两向…

Pytest 测试框架与Allure 测试报告——Allure2测试报告-L1

目录&#xff1a; allure2安装 Allure2介绍Allure2报告展示Allure2报告展示-首页概览Allure2报告展示-用例详情页Allure2安装Allure2下载与安装Allure环境验证插件安装-Python插件安装-Java验证插件安装-Javaallure2运行方式 生成测试报告流程使用Allure2运行方式-Python使用A…

大模型关键技术:上下文学习、思维链、RLHF、参数微调、并行训练、旋转位置编码、模型加速、大模型注意力机制优化、永久记忆、LangChain、知识图谱、多模态

大模型关键技术 大模型综述上下文学习思维链 CoT奖励建模参数微调并行训练模型加速永久记忆&#xff1a;大模型遗忘LangChain知识图谱多模态大模型系统优化AI 绘图幻觉问题从 GPT1 - GPT4 拆解GPTs 对比主流大模型技术点旋转位置编码层归一化激活函数注意力机制优化 大模型综述…

四种方法将 Docker Registry 迁移至 Harbor

Registry Docker Distribution Docker Distribution 是第一个是实现了打包、发布、存储和镜像分发的工具&#xff0c;起到 docker registry 的作用。&#xff08;目前 Distribution 已经捐赠给了 CNCF&#xff09;。其中 Docker Distribution 中的 spec 规范后来也就成为了 O…

Semaphone应用源码分析

Semaphone应用&源码分析 3.1 Semaphore介绍 sync&#xff0c;ReentrantLock是互斥锁&#xff0c;保证一个资源同一时间只允许被一个线程访问 Semaphore&#xff08;信号量&#xff09;保证1个或多个资源可以被指定数量的线程同时访问 底层实现是基于AQS去做的。 Semap…

开源进程/任务管理服务Meproc使用之HTTP API

本文讲述如何使用开源进程/任务管理服务Meproc的HTTP API管理整个服务。 Meproc所提供的全部 API 的 URL 都是相同的。 http://ip:port/proc例如 http://127.0.0.1:8606/proc在下面的小节中&#xff0c;我们使用curl命令向您展示 API 的方法、参数和请求正文。 启动任务 …

git 常规操作及设置

git 常规操作及设置 Git是一个分布式版本控制系统&#xff0c;可以用来跟踪文件的修改历史并与其他人进行协作开发。下面是一些常见的Git操作及设置&#xff1a; 初始化仓库&#xff1a;使用命令git init在当前目录创建一个新的Git仓库。 克隆仓库&#xff1a;使用命令git clo…

TCP/IP协议及配置、IP地址、子网掩码、网关地址、DNS与DHCP介绍

一、什么是服务器 能够为其他计算机提供服务的更高级的电脑 尺寸:Unit 1u1.75英寸44.45mm4.445cm IDC&#xff08;机房&#xff09; C/S结构 Client/Server客户端和服务端 二、TCP/IP协议 计算机与计算机之间通信的协议 三要素&#xff1a; IP地址 子网掩码 IP路由 I…

基于一次应用卡死问题所做的前端性能评估与优化尝试

问题背景 在上个月&#xff0c;由于客户反馈客户端卡死现象但我们远程却难以复现此现象&#xff0c;于是我们组织了一次现场上门故障排查&#xff0c;并希望基于此次观察与优化&#xff0c;为客户端开发提供一些整体的优化升级。当然&#xff0c;在尝试过程中&#xff0c;也发…

大模型实战营Day6 作业

基础作业 使用 OpenCompass 评测 InternLM2-Chat-7B 模型在 C-Eval 数据集上的性能 环境配置 conda create --name opencompass --clone/root/share/conda_envs/internlm-base source activate opencompass git clone https://github.com/open-compass/opencompass cd openco…

eMMC之分区管理、总线协议和工作模式

一、eMMC 简介 eMMC 是 embedded MultiMediaCard 的简称。MultiMediaCard&#xff0c;即MMC&#xff0c; 是一种闪存卡&#xff08;Flash Memory Card&#xff09;标准&#xff0c;它定义了 MMC 的架构以及访问 Flash Memory 的接口和协议。而eMMC 则是对 MMC 的一个拓展&…

【Docker】使用Docker安装Nginx及部署前后端分离项目应用

一、Nginx介绍 Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。它是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的&#xff0c;公开版本1.19.6发布于2020年12月15日。其将源代码以类BSD许可证的形式发布&#xff0c;因它…

内网环境横向移动——利用windows服务

利用windows服务进行横向渗透主要是通过sc命令&#xff0c;但是注意这里跟之前windows远程命令相比多了一个条件&#xff0c;即当前主机需要为administrator权限。 sc命令 sc命令是XP系统中功能强大的DOS命令,SC命令能与“服务控制器”和已安装设备进行通讯。SC是用于与服务控…

SDCMS靶场通过

考察核心&#xff1a;MIME类型检测文件内容敏感语句检测 这个挺搞的&#xff0c;一开始一直以为检查文件后缀名的&#xff0c;每次上传都失败&#xff0c;上传的多了才发现某些后缀名改成php也可通过&#xff0c;png图片文件只把后缀名改成php也可以通过&#xff0c;之前不成功…

uniapp组件库Popup 弹出层 的使用方法

目录 #平台差异说明 #基本使用 #设置弹出层的方向 #设置弹出层的圆角 #控制弹窗的宽度 | 高度 #内容局部滚动 #API #Props #Event 弹出层容器&#xff0c;用于展示弹窗、信息提示等内容&#xff0c;支持上、下、左、右和中部弹出。组件只提供容器&#xff0c;内部内容…

CSS:backdrop-filter实现毛玻璃的效果

实现效果 实现代码 /* 关键属性 */ background-color: rgba(255, 255, 255, 0.4); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);完整代码 <style>/* 遮罩层 */.mo-mask {position: fixed;top: 0;bottom: 0;left: 0;right: 0;width: 100%;height…

【排序算法】五、冒泡排序(C/C++)

「前言」文章内容是排序算法之冒泡排序的讲解。&#xff08;所有文章已经分类好&#xff0c;放心食用&#xff09; 「归属专栏」排序算法 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 冒泡排序1.1 原理1.2 代码实现&#xff08;C/C&#xff09;1.3 特性总结 冒泡排序 1.1…

WorkPlus AI助理私有化部署,助力企业降本增效

在当今数字化时代&#xff0c;提供卓越的客户服务成为了企业成功的重要因素。而AI智能客服技术的兴起&#xff0c;则成为了实现高效、快捷客户服务的利器。作为一款领先的AI助理解决方案&#xff0c;WorkPlus AI助理能够私有化部署&#xff0c;为企业打造私有知识库&#xff0c…