数据结构-- 基于顺序表的通讯录代码讲解
我们了解顺序表之后来一个比较简单的小项目来巩固一下.
每一个函数我都进行了详细的补充, 各位可以仔细阅读。我将整个项目分为了Contact.h 、Contact.c和test.c三个文件中,其中Contact.h用于函数声明和结构体创建,Contact.c用于函数的实现,test.c用于测试代码。
Contact.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>#define NAME_MAX 20
#define GENDER_MAX 10
#define TELE_MAX 20
#define ADDR_MAX 100//定义通讯录结构体
typedef struct peopleInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tele[TELE_MAX];char addr[ADDR_MAX];
}peoInfo;
//改名为通讯录
typedef peoInfo Contact;//改名便于整体替换类型
typedef peoInfo sqDataType;
//定义顺序表
struct SeqList
{sqDataType* arr;int size;int capacity;
};
//缩写改名
typedef struct SeqList SQL;/*000000000000000000000000000000000000000000000000000000000000000000000000000000000000*///顺序表初始化
void SQLInit(SQL* ps);//检查容量函数
void check_capacity(SQL* ps);//顺序表尾插函数
void TailInsert(SQL* ps, sqDataType info);//任意位置删除联系人
void SQLDelete(SQL* ps, int pos, sqDataType info);//任意位置修改顺序表元素
void SQLModify(SQL* ps, int find);
/*0000000000000000000000000000000000000000000000000000000000000000000000000000000000*/
//初始化通讯录
void ContactInit(Contact* pcon);//增加联系人
void ContactAdd(Contact* pcon);//查找联系人
int Contactsearch(SQL* ps);//修改联系人
void ContactModify(SQL* ps);//删除联系人
void ContactDel(Contact* pcon);//文件保存联系人
void KeepFile(Contact* pcon);//显示通讯录
void ContactShow(SQL* ps);//销毁通讯录
void ContactDestroy(SQL* ps);
Contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
//改名联系人信息为通讯录
typedef peoInfo Contact;//顺序表初始化
void SQLInit(SQL* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->size = 0;
}//检查容量函数
void check_capacity(SQL* ps)
{assert(ps);//三目操作符巧妙开辟空间int newcapacity = (ps->capacity == 0) ? 1 : (2 * ps->capacity);//相等的情况if (ps->size == ps->capacity){sqDataType* pa = (sqDataType*)realloc(ps->arr, sizeof(sqDataType) * newcapacity);if (pa == NULL){perror("realloc");return;}ps->arr = pa;printf("扩容成功\n");}
}//顺序表尾插函数
void TailInsert(SQL* ps, sqDataType info)
{assert(ps && &info);//判断是否需要扩容check_capacity(ps);//插入联系人信息ps->arr[ps->size] = info;ps->size++;printf("添加成功\n");
}//任意位置删除顺序表元素
void SQLDelete(SQL* ps, int pos)
{//检验指针有效性和pos的有效性assert(ps && pos >= 0 && pos < ps->size);//pos后的元素全部向前一位for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];ps->size--;}printf("删除成功\n");
}//任意位置修改顺序表元素
void SQLModify(SQL* ps, int pos)
{//创建临时结构体变量peoInfo info;//输入联系人信息printf("请输入联系人姓名:>");scanf("%s", info.name);printf("请输入联系人性别:>");scanf("%s", info.gender);printf("请输入联系人年龄:>");scanf("%s", &info.age);printf("请输入联系人电话:>");scanf("%s", info.tele);printf("请输入联系人地址:>");scanf("%s", info.addr);//修改元素信息ps->arr[pos] = info;
}/************************************************************************************************************************/
//初始化通讯录
void ContactInit(Contact* pcon)
{//其实就是初始化顺序表,因为顺序表的底层就是数组;SQLInit(pcon);//扩容check_capacity(pcon);
}//增加联系人
void ContactAdd(Contact* pcon)
{ //断言assert(pcon);//创建临时联系人结构体peoInfo info;//输入联系人信息printf("请输入联系人姓名:>");scanf("%s", info.name);printf("请输入联系人性别:>");scanf("%s", info.gender);printf("请输入联系人年龄:>");scanf("%d", &info.age);printf("请输入联系人电话:>");scanf("%s", info.tele);printf("请输入联系人地址:>");scanf("%s", info.addr);//尾插函数:插入顺序表TailInsert(pcon,info);
}//查找联系人
int Contactsearch(SQL* ps)//在顺序表中查找
{char name[NAME_MAX];printf("请输入联系人姓名:>");scanf("%s", name);//遍历顺序表,查找联系人for (int i = 0; i < ps->size; i++){if (strcmp(ps->arr[i].name, name) == 0){//找到了return i;}}//没找到return -1;
}//修改联系人信息
void ContactModify(SQL* ps)
{//想要修改联系人,前提是要先找到联系人int find = Contactsearch(ps);if (find < 0){printf("未找到该联系人\n");return;}//修改顺序表中的该元素SQLModify(ps,find);
}//删除联系人
void ContactDel(SQL* ps)
{//想要删除联系人,前提是要先找到联系人int find = Contactsearch(ps);if (find < 0){printf("未找到该联系人\n");return;}//删除顺序表的该元素SQLDelete(ps, find);
}//文件保存联系人
void KeepFile(SQL* ps)
{//打开文件FILE* pf = fopen("C:\\编程\\2024\\continue\\ContactProject_4_7\\ContactProject_4_7\\contact.txt", "w");if (pf == NULL){perror("fopen");return;}//读入文件char arr[100000];for (int i = 0; i < ps->size; i++){fprintf(pf, "%s %s %d %s %s\n", ps->arr[i].name, ps->arr[i].gender, ps->arr[i].age, ps->arr[i].tele, ps->arr[i].addr);}//关闭文件fclose(pf);pf = NULL;
}//显示通讯录
void ContactShow(SQL* ps)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < ps->size; i++){printf("%s %s %d %s %s\n", ps->arr[i].name, ps->arr[i].gender, ps->arr[i].age, ps->arr[i].tele, ps->arr[i].addr);}
}//销毁通讯录
void ContactDestroy(SQL* ps)
{if (ps->arr != NULL){free(ps->arr);ps->arr = NULL;}ps->capacity = ps->size = 0;printf("通讯录已销毁\n");
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
//改名为通讯录
typedef peoInfo Contact;void menu()
{printf("**************************------通讯录-----******************************\n");printf("************** 1、Add 2、Delete *****************\n");printf("************** 3、Search 4、Modify *****************\n");printf("************** 5、KeepFile 6、Show *****************\n");printf("************** 7、Destroy 0、Exit *****************\n");printf("*************************************************************************\n");
}int main()
{//创建结构体便量Contact con;//初始化ContactInit(&con);int input = 0;int ret = 0;do{//菜单函数menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1://增ContactAdd(&con);break;case 2://删ContactDel(&con);break;case 3://查ret = Contactsearch(&con);if (ret < 0){printf("未找到该联系人\n");}else{//显示联系人信息ContactShow(&con);}break;case 4://改ContactModify(&con);break;case 5://文件操作KeepFile(&con);break;case 6://显示通讯录ContactShow(&con);break;case 7://销毁通讯录ContactDestroy(&con);break;case 0://退出printf("退出通讯录\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);return 0;
}
相关文章:
数据结构-- 基于顺序表的通讯录代码讲解
我们了解顺序表之后来一个比较简单的小项目来巩固一下. 每一个函数我都进行了详细的补充, 各位可以仔细阅读。我将整个项目分为了Contact.h 、Contact.c和test.c三个文件中,其中Contact.h用于函数声明和结构体创建,Contact.c用于函数的实现,t…...

qt-C++笔记之QLabel加载图片
qt-C笔记之QLabel加载图片 —— 2024-04-06 夜 code review! 文章目录 qt-C笔记之QLabel加载图片0.文件结构1.方法一:把图片放在项目路径下,在 .pro 文件中使用 DISTFILES添加图片文件1.1.运行1.2.qt_test.pro1.3.main.cpp 2.方法二:不在 .pr…...

Unity中UI系统1——GUI
介绍 工作原理和主要作用 基本控件 a.文本和按钮控件 练习: b.多选框和单选框 练习: 用的是第三种方法 c.输入框和拖动框 练习: 练习二: e.图片绘制和框 练习: 复合控件 a.工具栏和选择网格 练习: b.滚动视…...

GIt 删除某个特定commit
目的 多次commit,想删掉中间的一个/一些commit 操作方法 一句话说明:利用rebase命令的d表示移除commit的功能,来移除特定的commit # 压缩这3次commit,head~3表示从最近1次commit开始,前3个commit git rebase -i head~3rebase…...
Django --静态文件
静态文件 除了由服务器生成的HTML文件外,WEB应用一般需要提供一些其它的必要文件,比如图片文件、JavaScript脚本和CSS样式表等等,用来为用户呈现出一个完整的网页。在Django中,我们将这些文件统称为“静态文件”,因为…...

蓝桥杯第十三届省赛C++B组(未完)
目录 刷题统计 修剪灌木 X进制减法 【前缀和双指针】统计子矩阵 【DP】积木画 【图DFS】扫雷 李白打酒加强版 DFS (通过64%,ACwing 3/11); DFS(AC) DP(AC) 砍竹子(X) 刷题统计 题目描述 小明决定从下周一开始努力刷题准…...
编程生活day7--明明的随机数、6翻了、吃火锅
明明的随机数 题目描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数…...

css酷炫边框
边框一 .leftClass {background: #000;/* -webkit-animation: twinkling 1s infinite ease-in-out; 1秒钟的开始结束都慢的无限次动画 */ } .leftClass::before {content: "";width: 104%;height: 102%;border-radius: 8px;background-image: linear-gradient(var(…...

使用 Docker 部署 Photopea 在线 PS 工具
1)Photopea 介绍 GitHub:https://github.com/photopea/photopea 官方手册:https://www.photopea.com/learn/ Adobe 出品的「PhotoShop」想必大家都很熟悉啦,但是「PhotoShop」现在对电脑配置要求越来越高,体积越来越大…...

回溯法(一)——全排列 全组合 子集问题
全排列问题 数字序列 [ l , r ] [l,r] [l,r]区间内元素的全排列问题 extern int ans[],l,r,num;//num:方案数 extern bool flag[]; void dfs(int cl){//cl:current left,即为当前递归轮的首元素if(cl r 1){//数组已越界,本轮递归结束for…...

【Pt】马灯贴图绘制过程 04-玻璃脏迹
目录 效果 步骤 一、透明玻璃 二、烟熏痕迹 三、粗糙 四、浮尘 效果 步骤 一、透明玻璃 1. 打开纹理集设置,着色器链接选择“新的着色器链接” 在着色器设置中可以看到此时名称为“Main shader (Copy)” 这里修改名称为“玻璃” 在…...

Rust 程序设计语言学习——枚举模式匹配
枚举(enumerations),也被称作 enums。match 允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。 1 枚举的定义 假设我们要跨省出行,有多种交通工具供选择。常用的交通工具有飞机、火车、汽车和轮…...

正则表达式(1)
文章目录 专栏导读1、match2、匹配目标3、通用匹配4、常用匹配规则表格 专栏导读 ✍ 作者简介:i阿极,CSDN 数据分析领域优质创作者,专注于分享python数据分析领域知识。 ✍ 本文录入于《python网络爬虫实战教学》,本专栏针对大学生…...
nginx + keepalived 搭建教程
1.安装依赖 yum install -y keepalived systemctl start keepalived systemctl enable keepalived 2.配置 a. keepalived.conf配置 global_defs {router_id nginx_server2 # 机器标识(backup节点为nfs_server2) }vrrp_script chk { script "/etc/keepalived/check_po…...
React事件和原生事件的执行顺序
在 React 中,事件处理分为两种类型:React 合成事件(Synthetic Event)和原生 DOM 事件(Native DOM Event)。它们的执行顺序略有不同。 React 合成事件 React 合成事件的执行顺序: React 合成事件…...
为什么在计算查询Q和键K的矩阵乘法时需要转置键矩阵K。示例说明q11,k11代表什么。线性变换矩阵 W_q 用于生成查询,W_k 用于生成键怎么获取的。
目录 为什么在计算查询Q和键K的矩阵乘法时需要转置键矩阵K。 示例说明q11,k11代表什么。...

剑指Offer题目笔记27(动态规划单序列问题)
面试题89: 问题: 输入一个数组表示某条街道上的一排房屋内财产的数量。相邻两栋房屋不能同时被盗,问小偷能偷取到的最多财物。 解决方案一(带缓存的递归): 解决方案: 由于有报警系统&…...

撸代码时,有哪些习惯一定要坚持?
我从2011年开始做单片机开发,一直保持以下撸代码的习惯。 1.做好代码版本管理 有些人,喜欢一个程序干到底,直到实现全部的产品功能,我以前做51单片机的项目就是这样。 如果功能比较多的产品,我不建议这样做࿰…...
【leetcode面试经典150题】17.罗马数字转整数(C++)
【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…...

前后端开发之——文章分类管理
原文地址:前后端开发之——文章分类管理 - Pleasure的博客 下面是正文内容: 前言 上回书说到 文章管理系统之添加文章分类。就是通过点击“新建文章分类”按钮从而在服务端数据库中增加一个文章分类。 对于文章分类这个对象,增删改查属于配…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...