通讯录的实现(顺序表版本)

我们知道通讯录是基于顺序表的前提下,要写好通讯录我们就要深入了解好顺序表。我们先来看看什么是顺序表。(注意今天代码量有点多,坚持一下)。冲啊!兄弟们!

顺序表的简单理解

对于顺序表,我们首先要知道的是:它不仅物理存储结构上是连续的,逻辑层次上也是连续的。它的本质是数组。它是在数组上的增删查改。这其实就是一个顺序表。

typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效个数int capacity;//数组空间大小
}SL;

而这个顺序表的大小其实取决于你给这个数组开辟多少内存空间。

那我们来看看一个完整功能的顺序表是怎么实现的。我们将顺序表所需要的函数的头文件写在SeqList.h头文件中,将函数的实现写在SeqList.c中

SeqList.h的头文件所需要的函数:

#pragma once
//所需要的头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"
//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效个数int capacity;//数组空间大小
}SL;//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//尾插
void SLpushBack(SL* ps, SLDataType x);
//空间的申请
void SLcheck(SL* ps);
//头插
void SLpushFront(SL* ps, SLDataType x);
//尾删
void SLpopBack(SL* ps);
//头删
void SLpopFront(SL* ps);
//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置删除
void SLErase(SL* ps, int pos);

各种函数的实现

初始化函数的实现

一个变量需要初始化,而顺序表也不例外。

//顺序表初始化
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

顺序表销毁函数的实现

利用动态内存函数开辟的空间,如果不使用了,我们就要将他们释放掉,也就是顺序表的销毁。

//顺序表的销毁
void SLDestroy(SL* ps)
{//注意这里要判断一下数组地址是否为NULL,否则释放空指针空间会出问题if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}

尾插函数的实现

在尾插之前,我们需要判断一下,顺序表里面的那个数组的内存够不够这个数据的插入,那么我们可以将这样一个功能封装成一个函数。

//尾插
void SLpushBack(SL* ps, SLDataType x)
{assert(ps);SLcheck(ps);ps->arr[ps->size++] = x;
}
//空间申请
void SLcheck(SL* ps)
{if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc");return;}ps->arr = tmp;ps->capacity = newcapacity;}
}

头插函数的实现

尾插需要判断一下数组内存是否够不够插入,那么头插也是如此。

//头插
void SLpushFront(SL* ps, SLDataType x)
{assert(ps);SLcheck(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];//arr[1]=arr[0]}ps->arr[0] = x;ps->size++;

尾删函数的实现

实现这个函数,需要注意的是只要我们不影响其它函数的使用,即使不让开辟的内存释放也行的通

//尾删
void SLpopBack(SL* ps)
{assert(ps);ps->size--;
}

头删函数的实现

void SLpopFront(SL* ps)
{assert(ps);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1]}ps->size--;

指定位置插入函数的实现

//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLcheck(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//arr[pos+1]=arr[pos]}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];//arr[size-2]=arr[size-1]}ps->size--;
}

通讯录函数声明和定义

我们将通讯录要用到的函数声明放到Contact.h头文件中,将函数的实现放到Contact.c的源文件中。

Contact.h头文件的函数:

#pragma once
//联系人结构体
//姓名  性别  年龄  电话  地址
#define NAME_MAX 20
#define GENDER_MAX 10
#define AGE_MAX 10
#define TEL_MAX 10
#define ADDR_MAX 10
typedef struct perinfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}perinfo;typedef struct SeqList Contact;//前置声明//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDetroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDelete(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录的查找
int ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

通讯录函数的实现

通讯录初始化函数的实现

注意由于我们通讯录是基于顺序表的,所以一些函数可以调用顺序表中的函数。

//通讯录的初始化
void ContactInit(Contact* con)
{//通讯录的初始化实际上是顺序表的初始化//而顺序表的初始化已经实现了SLInit(con);
}

通讯录销毁函数的实现

这里可以调用顺序表里面的销毁函数。

//通讯录的销毁
void ContactDetroy(Contact* con)
{SLDestroy(con);
}

通讯录添加数据函数的实现

//通讯录添加数据
void ContactAdd(Contact* con)
{perinfo info;//姓名 性别 年龄 电话 地址printf("请输入要添加联系人的姓名:\n");scanf("%s", info.name);printf("请输入要添加联系人的性别:\n");scanf("%s", info.gender);printf("请输入要添加联系人的年龄:\n");scanf("%d", &info.age);printf("请输入要添加联系人的电话:\n");scanf("%s", info.tel);printf("请输入要添加联系人的地址:\n");scanf("%s", info.addr);//插入数据SLpushBack(con, info);
}

查找联系人

//查找联系人
int ContactFindname(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 ContactDelete(Contact* con)
{//删除的数据要先存在才能删除,否则删除不了//查找char name[NAME_MAX];printf("请输入你要删除的联系人姓名:\n");scanf("%s", name);int find = ContactFindname(con, name);if (find < 0){printf("没有此联系人!\n");return;}//执行删除程序SLErase(con, find);printf("删除成功!\n");
}

展示联系人数据函数的实现

//展示通讯录数据
void ContactShow(Contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < con->size; i++){printf("%.6s    %.6s    %d   %.6s   %.6s\n", con->arr[i].name, con->arr[i].gender, con->arr[i].age, con->arr[i].tel, con->arr[i].addr);}
}

通讯录修改函数的实现

这里也可以直接调用一下以上的查找函数。

//通讯录的修改
void ContactModify(Contact* con)
{char name[NAME_MAX];printf("请输入要修改的用户姓名:\n");scanf("%s", name);int find = ContactFindname(con, name);if (find < 0){printf("要修改的联系人不存在!\n");return;}//直接修改printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入新的电话:\n");scanf("%s", con->arr[find].tel);printf("请输入新的住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功!\n");
}

通讯录查找函数的实现

//通讯录的查找
int ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找人的姓名:\n");scanf("%s", name);int find = ContactFindname(con,name);if (find < 0){printf("没有此联系人!\n");return;}printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%.6s    %.6s    %d   %.6s   %.6s\n", con->arr[find].name, con->arr[find].gender, con->arr[find].age, con->arr[find].tel, con->arr[find].addr);
}

总代码

SeqList.h文件

#pragma once
//所需要的头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"
//动态顺序表
typedef perinfo SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效个数int capacity;//数组空间大小
}SL;//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//尾插
void SLpushBack(SL* ps, SLDataType x);
//空间的申请
void SLcheck(SL* ps);
//头插
void SLpushFront(SL* ps, SLDataType x);
//尾删
void SLpopBack(SL* ps);
//头删
void SLpopFront(SL* ps);
//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置删除
void SLErase(SL* ps, int pos);

SeqList.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//各个函数的实现//顺序表初始化
void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{//注意这里要判断一下数组地址是否为NULL,否则释放空指针空间会出问题if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}
//尾插
void SLpushBack(SL* ps, SLDataType x)
{assert(ps);SLcheck(ps);ps->arr[ps->size++] = x;
}
//空间申请
void SLcheck(SL* ps)
{if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc");return;}ps->arr = tmp;ps->capacity = newcapacity;}
}
//头插
void SLpushFront(SL* ps, SLDataType x)
{assert(ps);SLcheck(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];//arr[1]=arr[0]}ps->arr[0] = x;ps->size++;
}
//尾删
void SLpopBack(SL* ps)
{assert(ps);ps->size--;
}
//头删
void SLpopFront(SL* ps)
{assert(ps);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1]}ps->size--;
}
//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLcheck(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//arr[pos+1]=arr[pos]}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];//arr[size-2]=arr[size-1]}ps->size--;
}

Contact.h文件

#pragma once
//联系人结构体
//姓名  性别  年龄  电话  地址
#define NAME_MAX 20
#define GENDER_MAX 10
#define AGE_MAX 10
#define TEL_MAX 10
#define ADDR_MAX 10
typedef struct perinfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}perinfo;typedef struct SeqList Contact;//前置声明//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDetroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDelete(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录的查找
int ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

Contact.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//通讯录的初始化
void ContactInit(Contact* con)
{//通讯录的初始化实际上是顺序表的初始化//而顺序表的初始化已经实现了SLInit(con);
}
//通讯录的销毁
void ContactDetroy(Contact* con)
{SLDestroy(con);
}
//通讯录添加数据
void ContactAdd(Contact* con)
{perinfo info;//姓名 性别 年龄 电话 地址printf("请输入要添加联系人的姓名:\n");scanf("%s", info.name);printf("请输入要添加联系人的性别:\n");scanf("%s", info.gender);printf("请输入要添加联系人的年龄:\n");scanf("%d", &info.age);printf("请输入要添加联系人的电话:\n");scanf("%s", info.tel);printf("请输入要添加联系人的地址:\n");scanf("%s", info.addr);//插入数据SLpushBack(con, info);
}
//查找联系人
int ContactFindname(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 ContactDelete(Contact* con)
{//删除的数据要先存在才能删除,否则删除不了//查找char name[NAME_MAX];printf("请输入你要删除的联系人姓名:\n");scanf("%s", name);int find = ContactFindname(con, name);if (find < 0){printf("没有此联系人!\n");return;}//执行删除程序SLErase(con, find);printf("删除成功!\n");
}
//展示通讯录数据
void ContactShow(Contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < con->size; i++){printf("%.6s    %.6s    %d   %.6s   %.6s\n", con->arr[i].name, con->arr[i].gender, con->arr[i].age, con->arr[i].tel, con->arr[i].addr);}
}
//通讯录的修改
void ContactModify(Contact* con)
{char name[NAME_MAX];printf("请输入要修改的用户姓名:\n");scanf("%s", name);int find = ContactFindname(con, name);if (find < 0){printf("要修改的联系人不存在!\n");return;}//直接修改printf("请输入新的姓名:\n");scanf("%s", con->arr[find].name);printf("请输入新的性别:\n");scanf("%s", con->arr[find].gender);printf("请输入新的年龄:\n");scanf("%d", &con->arr[find].age);printf("请输入新的电话:\n");scanf("%s", con->arr[find].tel);printf("请输入新的住址:\n");scanf("%s", con->arr[find].addr);printf("修改成功!\n");
}
//通讯录的查找
int ContactFind(Contact* con)
{char name[NAME_MAX];printf("请输入要查找人的姓名:\n");scanf("%s", name);int find = ContactFindname(con,name);if (find < 0){printf("没有此联系人!\n");return;}printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%.6s    %.6s    %d   %.6s   %.6s\n", con->arr[find].name, con->arr[find].gender, con->arr[find].age, con->arr[find].tel, con->arr[find].addr);
}

test_1.c文件

将通讯录各个函数封装一下,制成一个菜单。

#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");
}
int main()
{int input;Contact con;ContactInit(&con);do{menu();printf("请选择你的操作:\n");scanf("%d", &input);switch (input){case 1:ContactAdd(&con);break;case 2:ContactDelete(&con);break;case 3:ContactFind(&con);break;case 4:ContactModify(&con);break;case 5:ContactShow(&con);break;case 0:printf("退出通讯录....\n");break;default:printf("选项不合法,重新选择\n");break;}} while (input);ContactDetroy(&con);return 0;
}

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

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

相关文章

用AI的视角看世界

前言 2024年将是Ai人工智能在各个行业垂直领域发展的元年。 随着2022年11月openai 的大语言模型chatgpt3.5的诞生&#xff0c;已经预示着互联网时代&#xff0c;移动互联网时代即将迎来新的变革&#xff0c;也预示着web3.0和元宇宙更近了一步。 回顾历史&#xff0c;互联网的…

使用hexo+gitee从零搭建个人博客

一、环境准备 1.Node.js&#xff1a;下载 | Node.js 中文网 (nodejs.cn) &#xff0c;Hexo 是基于Node.js 的博客框架 教程&#xff1a;https://blog.csdn.net/weixin_52799373/article/details/123840137 node -v npm -v 安装 Node.js 淘宝镜像加速器 &#xff08;cnpm&am…

大模型应用工具 LangChain 入门书籍: LangChain 简明讲义

书籍信息 书名&#xff1a;《LangChain 简明讲义&#xff1a;从 0 到 1 构建 LLM 应用程序》出版社&#xff1a;电子工业出版社书籍链接&#xff1a;https://item.jd.com/14105705.html书籍配套代码&#xff1a;https://github.com/kebijuelun/langchain_book 书籍背景 计算机…

力扣LeetCode138. 复制带随机指针的链表 两种解法(C语言实现)

目录 题目链接 题目分析 题目定位&#xff1a; 解题思路 解题思路1&#xff08;粗暴但是复杂度高&#xff09; 解题思路2&#xff08;巧妙并且复杂度低&#xff09; 题目链接 138. 复制带随机指针的链表https://leetcode-cn.com/problems/copy-list-with-random-pointer/ …

实战项目——智慧社区(四)之 系统管理

1、用户管理 提供查询和搜索用户、根据id查询用户信息、添加用户、修改用户、删除用户的功能 界面 添加用户 修改用户信息 2、角色管理 提供查询和搜索角色、根据id查询角色信息、添加角色、修改角色、删除角色的功能 界面 添加角色 修改角色 3、菜单管理 提供查询和搜索菜…

机器学习在安全领域的应用:从大数据中识别潜在安全威胁

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

蓝桥杯第2152题——红绿灯

问题描述 爱丽丝要开车去上班, 上班的路上有许多红绿灯, 这让爱丽丝很难过。为 了上班不迟到, 她给自己的车安装了氮气喷射装置。现在她想知道自己上班最 短需要多少时间。 爱丽丝的车最高速度是 米每秒, 并且经过改装后, 可以瞬间加速到小于 等于最高速的任意速度, 也可以瞵…

Sonar下启动发生错误,elasticsearch启动错误

Download | SonarQube | Sonar (sonarsource.com) 1.首先我的sonar版本为 10.4.1 &#xff0c;java版本为17 2.sonar启动需要数据库,我先安装了mysql, 但是目前sonar从7.9开始不支持mysql&#xff0c;且java版本要最少11,推荐使用java17 3.安装postsql,创建sonar数据库 4.启…

ArcGIS Desktop使用入门(三)图层右键工具——可见比例范围

系列文章目录 ArcGIS Desktop使用入门&#xff08;一&#xff09;软件初认识 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——标准工具 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——编辑器 ArcGIS Desktop使用入门&#xff08;二&#x…

如何下载和安装Google Chrome扩展插件:一步步指南

Google Chrome 插件为我们提供了这样的便利&#xff0c;但有时找到一个有用的插件后&#xff0c;我们可能需要将其下载到本地以便离线使用或备份。 一、为什么可以从Google Chrome商店直接下载插件&#xff1f; Google Chrome 扩展插件主要通过Chrome Web Store分发&#xff…

流氓软件清理绝杀全家桶

下载地址&#xff1a;流氓软件清理绝杀全家桶.zip 网上仍有不少软件中携带流氓软件&#xff0c;甚至某些所谓的大厂出品的工具中也会有一些捆绑&#xff01; 对于玩机经验不太丰富的小白来说&#xff0c;也许一不小心&#xff0c;桌面就会被某些流氓软件搞得乌烟瘴气&#xf…

实验笔记之——RGBD GS-ICP SLAM配置与测试

《RGBD GS-ICP SLAM》是最新开源的一个3DGS-SLAM工作&#xff0c;通过利用GICP来实现当前帧gaussian与已mapping的gaussian进行匹配进行位姿的估算&#xff0c;并通过关键帧的选择策略来进一步提升performance~ Use G-ICP to align the current frame with the 3D GS map whic…

基于人脸识别的发型推荐系统代码实现

1.摘要 本文介绍了一个基于人脸识别技术的发型推荐系统的实现与分析。该系统利用Python编程语言和相关库&#xff0c;结合Face人脸识别API&#xff0c;实现了用户上传照片后的性别识别、脸型分析和发型推荐功能。首先&#xff0c;用户通过Tkinter GUI界面选择上传照片&#xff…

gpt在线网页版最全收录

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…

Linux网络基础 (二) ——(IP、MAC、端口号、TCPUDP协议、网络字节序)

文章目录 IP 地址基本概念源IP地址 & 目的IP地址 MAC 地址基本概念源MAC地址 & 目的MAC地址 端口号基本概念源端口号 & 目的端口号 TCP & UDP 协议基本概念TCP 与 UDP 的抉择 网络字节序大端、小端字节序 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alask…

1.9 数据结构之 并查集

编程总结 在刷题之前需要反复练习的编程技巧&#xff0c;尤其是手写各类数据结构实现&#xff0c;它们好比就是全真教的上乘武功 本栏目为学习笔记参考&#xff1a;https://leetcode.cn/leetbook/read/disjoint-set/oviefi/ 1.0 概述 并查集&#xff08;Union Find&#xff09…

# Nacos 服务发现-快速入门-测试多实例 Ribbon 负载均衡

Nacos 服务发现-快速入门-测试多实例 Ribbon 负载均衡 1、修改 服务生产模块 quickstart_provider 子工程中的 配置文件 application.yaml port: ${port:56010} # 启动端口 # 修改为动态传参&#xff0c;如果未传参数&#xff0c;默认端口为 56010 2、在 idea 中&#xff0c;…

内网渗透-Linux内网渗透

系列文章目录 文章目录 系列文章目录一、Linux内网渗透二、提权 2.1 利用内核漏洞进行提权2.2 利用文件权限配置不当进行提权2.3 利用SUID程序进行提权 三、隧道 3.1 SSH3.2 nc/ncat3.3 portmap3.4 portfw 四、反弹shell 4.1 bash4.2 netcat4.3 php4.4 perl4.5 python4.6 ruby4…

Prime (2021): 2

前言 这个靶机有亿点难,收获很多。打靶的时候&#xff0c;前面很顺&#xff0c;到创建ssh公钥之后就一点不会了。 1 01 arp扫描&#xff0c;发现有一个130&#xff0c;再查看端口 有22&#xff0c;80&#xff0c;129&#xff0c;445&#xff0c;10123 dirb扫描目录 这…