【编译原理】用Python实现LR(0)语法分析

实验内容

对于给定的如下文法,编写调试一个上下文无关文法的LR(0)分析程序。

文法G’为:
S → E S\to E SE
E → a A E\to aA EaA
E → b B E \to bB EbB
A → c A A\to cA AcA
A → d A\to d Ad
B → c B B\to cB BcB
B → d B\to d Bd


实验环境

  • IDE:PyCharm 2023.2.1 (Community Edition)
  • Python:3.8.5
  • 库:tkinter

测试结果截图以及说明

文法:

在这里插入图片描述

读取功能后功能选择:

在这里插入图片描述

状态集:

在这里插入图片描述

状态表:

在这里插入图片描述

分析字符串,输入后得到结果:

在这里插入图片描述

退出程序:

在这里插入图片描述


代码部分

代码结构如下

project_floder
│  LICENSE.md
│  main.py
│  README.md
│  read_grammar.py
│
├─.idea
│  │  .gitignore
│  │  deployment.xml
│  │  LR(0).iml
│  │  misc.xml
│  │  modules.xml
│  │  vcs.xml
│  │  workspace.xml
│  │
│  └─inspectionProfiles
│          profiles_settings.xml
│
├─src
│      grammar_1.txt
│      grammar_2.txt
│
└─__pycache__

代码仓库(Github)

在这里插入图片描述
https://github.com/hiddenSharp429/LR-0-_analysis

read_grammar.py

"""
@coding : utf-8
@File   : read_grammar.py
@Author : hiddensharp
@Date   : 2023/12/10
@Desc   : 返回一个能够给lr0分析器分析的字典并自动变成增广文法
@Version:
@Last_editor
"""

import re

class ReadGrammar(dict):
    def __init__(self, grammar_file_path):
        super().__init__()
        self.file_path = grammar_file_path
        self.translate()
        self.add_augmented_production()

    def translate(self):
        # 从文件中读取规则
        with open(self.file_path, 'r', encoding='utf-8') as file:
            rules = file.readlines()

        # 遍历每一条规则
        for rule in rules:
            # 使用正则表达式匹配规则的左部和右部
            match = re.match(r'\s*(\w+)\s*->\s*(.+)\s*', rule)
            if match:
                left = match.group(1)
                right = match.group(2)

                # 如果左部非终结符还不存在于字典中,则添加
                if left not in self:
                    self[left] = []

                # 将右部按照单个字符拆分并添加到左部的规则中
                productions = [symbol for symbol in right]
                self[left].append(tuple(productions))

    def add_augmented_production(self):
        # 获取原始文法的起始符号
        original_start_symbol = list(self.keys())[0]

        # 生成新的起始符号
        new_start_symbol = 'S'

        # 创建新的字典,将新的起始产生式添加到新的字典中
        new_dict = {new_start_symbol: [(original_start_symbol,)]}

        # 将原始字典的内容添加到新的字典后面
        new_dict.update(self)

        # 将新的字典设置为当前字典
        self.clear()
        self.update(new_dict)

        # 返回新的起始符号
        return new_start_symbol

if __name__ == '__main__':
    # 定义需要读取的文法文件的路径
    grammar_file_path = 'src/grammar_2.txt'  # 使用非拓广的文法

    # 转换为该解析器能读取的字典格式
    grammar_reader = ReadGrammar(grammar_file_path)

    print("Original Grammar:")
    print(grammar_reader)


main.py

"""
@coding : utf-8
@File   : main.py
@Author : zixian Zhu(hiddensharp)
@Date   : 2023/12/10
@Desc   :
@Version:
@Last_editor
"""
import tkinter as tk
from tkinter import filedialog, messagebox
from read_grammar import ReadGrammar


class LR0Parser:
    def __init__(self, grammar):
        # 初始化LR(0)分析器,接收文法作为参数
        self.grammar = grammar
        # 计算闭包和转移函数
        self.compute_closure_goto()

    def closure(self, items):
        '''
        计算闭包函数
        :param items: 当前项目集的集合
        :return:
        '''

        # 初始化闭包集合,包含输入的项目集
        closure_items = set(items)
        # 标志用于迭代,表示是否有项目被添加到闭包中
        changed = True

        # 循环直到没有新的项目添加到闭包中为止
        while changed:
            # 将标志设为 False,表示没有新的项目添加到闭包中
            changed = False

            # 对当前闭包集合中的每个项目进行遍历
            for item in closure_items.copy():
                # 获取项目中点的位置,如果没有点则使用项目的长度作为点的位置
                dot_index = item[1].index('.') if '.' in item[1] else len(item[1])

                # 如果点的位置不在项目的最后一个位置之前
                if dot_index < len(item[1]) - 1:
                    # 获取点后面的符号
                    next_symbol = item[1][dot_index + 1]

                    # 如果该符号在文法中
                    if next_symbol in self.grammar:
                        # 对该符号的每个产生式进行遍历
                        for production in self.grammar[next_symbol]:
                            # 创建一个新项目,将点移动到产生式的开头
                            new_item = (next_symbol, ('.',) + production)
                            # 如果新项目不在闭包中,则添加到闭包中,并将标志设为 True
                            if new_item not in closure_items:
                                closure_items.add(new_item)
                                changed = True

            # 处理以点结尾的项目的闭包
            for item in closure_items.copy():
                dot_index = item[1].index('.') if '.' in item[1] else len(item[1])

                # 如果点在项目的最后一个位置
                if dot_index == len(item[1]) - 1:
                    # 检查状态集中是否已经存在相同的状态
                    if item not in closure_items:
                        # 添加新项目到闭包中,并将标志设为 True
                        closure_items.add(item)
                        changed = True

        # 返回闭包的冻结集合,确保集合是不可变的
        return frozenset(sorted(closure_items))

    def goto(self, items, symbol):
        '''
        计算转移函数
        :param items: 当前项目集的集合
        :param symbol: 转移的符号
        :return:
        '''

        # 初始化转移后的项目集合
        goto_items = set()

        # 对当前项目集合中的每个项目进行遍历
        for item in items:
            # 获取项目中点的位置,如果没有点则使用项目的长度作为点的位置
            dot_index = item[1].index('.') if '.' in item[1] else len(item[1])

            # 如果点的位置不在项目的最后一个位置之前,并且点后的符号与输入的符号相匹配
            if dot_index < len(item[1]) - 1 and item[1][dot_index + 1] == symbol:
                # 创建一个新项目,将点移动到符号的位置
                new_item = (item[0], item[1][:dot_index] + (symbol, '.') + item[1][dot_index + 2:])
                # 将新项目添加到转移后的项目集合中
                goto_items.add(new_item)

        # 调用闭包函数,计算转移后的闭包
        return self.closure(goto_items)

    def compute_closure_goto(self):
        '''
        计算LR(0)项集规范族中所有状态的闭包和转移函数
        :return:
        '''

        # 初始化状态集合和转移字典
        self.states = []
        self.transitions = {}

        # 获取文法中所有出现的符号,包括终结符和非终结符,并按照大小写顺序排列
        all_symbols = sorted(set(
            symbol for production_list in self.grammar.values() for production in production_list for symbol in
            production))

        # 初始化初始项目和初始状态
        initial_item = ('S', ('.', 'E'))
        initial_state = self.closure({initial_item})
        # 将初始状态添加到状态集合中
        self.states.append(initial_state)

        # 使用队列实现广度优先搜索,初始状态入队
        queue = [initial_state]

        # 循环直到队列为空
        while queue:
            # 出队当前状态
            current_state = queue.pop(0)

            # 对文法中的每个符号进行遍历,包括终结符和非终结符
            for symbol in all_symbols:
                # 计算转移后的项目集
                goto_items = self.goto(current_state, symbol)

                # 如果存在转移后的项目集
                if goto_items:
                    # 计算转移后项目集的闭包
                    closure_goto_items = self.closure(goto_items)

                    # 如果闭包非空且不在已有状态集合中
                    if closure_goto_items and closure_goto_items not in self.states:
                        # 将闭包添加到状态集合中
                        self.states.append(closure_goto_items)
                        # 将闭包入队,以便继续搜索
                        queue.append(closure_goto_items)
                        # 记录当前状态到符号的转移关系
                        self.transitions[(current_state, symbol)] = closure_goto_items

    def is_reduce_state(self, state):
        '''
        判断状态是否为规约状态
        :param state: 状态
        :return: 是否为规约状态
        '''
        # 在这里实现判断状态是否为规约状态的逻辑
        for item in state:
            # 获取项目中点的位置,如果没有点则使用项目的长度作为点的位置
            dot_index = item[1].index('.') if '.' in item[1] else len(item[1])

            # 如果点的位置在项目的最后一个位置之前,说明这是规约状态
            if dot_index < len(item[1]) - 1:
                return False

        # 如果没有任何项目的点在最后,说明这是规约状态
        return True

    def get_reduce_production_index(self, state):
        '''
        获取规约状态对应的产生式的索引
        :param state: 规约状态
        :return: 产生式的索引
        '''
        # 在文法中查找该产生式的位置
        for item in state:
            # 获取项目中点的位置,如果没有点则使用项目的长度作为点的位置
            dot_index = item[1].index('.') if '.' in item[1] else len(item[1])

            # 如果点的位置在产生式右部的最后一个位置,说明这是规约状态
            if dot_index == len(item[1]) - 1:
                # 获取规约项目的产生式左右部
                production_left = item[0]
                production_right = item[1][:dot_index]

                production_index = 0 # 产生式子在文法中的索引
                # 在文法中查找该产生式左右两部分均匹配的位置
                for left_symbol, productions in self.grammar.items():
                    for index, production in enumerate(productions):
                        if left_symbol == production_left and production == production_right:
                            return production_index + index
                    production_index += len(productions)


    def print_states(self):
        '''
        打印所有的状态集
        :return:
        '''
        print("LR(0) Parsing States:")
        # 遍历所有状态
        for i, state in enumerate(self.states):
            # 输出当前状态的编号和项目集
            print(f"State {i}: {state}")

    def print_table(self):
        '''
        打印LR(0)分析表
        :return:
        '''
        # 获取文法中所有出现的符号,包括终结符和非终结符
        all_symbols = sorted(set(
            symbol for production_list in self.grammar.values() for production in production_list for symbol in
            production))

        # 分类大小写字符
        uppercase_symbols = sorted(set(symbol for symbol in all_symbols if symbol.isupper()))
        lowercase_symbols = sorted(set(symbol for symbol in all_symbols if symbol.islower()))
        lowercase_symbols.append('#') # 给ACTION表添加一个#列

        all_sorted_symbols = lowercase_symbols + uppercase_symbols
        # 初始化表格
        self.states_table = [[''] * (len(self.states) + 10) for _ in range(len(all_symbols) + 10)]

        # 设置表头
        self.states_table[0][0] = 'states'

        for row in range(len(self.states)):
            self.states_table[row + 1][0] = row

        for col, symbol in enumerate(all_sorted_symbols, start=1):
            self.states_table[0][col] = symbol

        # 填写表格
        for row in range(1, len(self.states) + 1):
            for col in range(1, len(all_sorted_symbols) + 1):
                # 获取当前符号
                current_states = self.states_table[row][0]
                current_symbol = self.states_table[0][col]

                # 如果是规约状态,则填写规约式的序号
                if self.is_reduce_state(self.states[current_states]):
                    production_index = self.get_reduce_production_index(self.states[current_states])

                    if production_index == 0:  # 增广产生式的索引为0
                        # 只有#列才标注acc
                        if current_symbol == '#':
                            cell_value = 'acc'
                        else:
                            cell_value = ''
                    else: # 除了增广产生式以外的情况
                        if current_symbol in lowercase_symbols: # 只填写终结符栏
                            cell_value = 'r' + str(production_index)
                        else:
                            cell_value = ''

                else:
                    # 计算goto
                    goto_state = self.goto(self.states[current_states], current_symbol)

                    # 如果存在goto状态,填写状态编号,并根据符号类型添加前缀
                    if goto_state:
                        # 查找goto_state在self.states中的索引
                        goto_index = self.states.index(goto_state)
                        cell_value = goto_index
                        if current_symbol.islower():
                            cell_value = 'S' + str(cell_value)
                    else:
                        cell_value = ''

                # 将单元格值填写到表格中
                self.states_table[row][col] = cell_value

        # 打印表格
        for row in range(len(self.states) + 1):
            for col in range(len(all_sorted_symbols) + 1):

                print(f"{self.states_table[row][col]:<10}", end='|')
            print()


    def parse_string(self, input_string):
        '''
        使用LR(0)分析表判断输入字符串是否属于文法
        :param input_string: 输入字符串
        :return: 如果是文法中的句子,返回True;否则,返回False
        '''
        # 将输入字符串添加结束符'#'
        input_string += '#'

        # 初始化分析栈,初始状态,和输入字符串索引
        states_stack = [0]
        symbol_stack = ['#']
        input_index = 0

        step = 1  # 步骤计数
        goto_state = ''  # 初始化goto_state

        while True:


            # 获取当前状态和输入符号
            current_state = states_stack[-1]
            current_symbol = input_string[input_index]

            # 查找LR(0)分析表中的动作
            action = self.get_action(current_state, current_symbol)

            # 打印步骤信息
            print(f"步骤{step:<4} | 状态栈: {str(states_stack):<20} | 符号栈: {str(symbol_stack):<30} | "
                  f"输入串: {input_string[input_index:]:<15} | "
                  f"ACTION: {action:<10} | ", end="")

            # 如果动作为空,说明分析表中无对应的动作,字符串不属于文法
            if not action:
                return False

            # 根据动作类型进行处理
            if action.startswith('S'):
                # 移入动作
                next_state = int(action[1:])
                states_stack.append(next_state)
                symbol_stack += input_string[input_index]
                input_index += 1

                print(f"GOTO: ")

            elif action.startswith('r'):
                # 规约动作
                production_index = int(action[1:])
                production = self.get_production_by_index(production_index)

                # 弹出产生式右部的符号
                for _ in range(len(production[1])):
                    states_stack.pop()
                    symbol_stack.pop()


                # 获取规约后的状态
                goto_state = self.get_action(states_stack[-1], production[0])
                states_stack.append(goto_state)
                symbol_stack.append(production[0])

                print(f"GOTO: {goto_state}")

            elif action == 'acc':

                print(f"GOTO: ")
                # 接受动作,字符串属于文法
                return True

            step += 1  # 步骤计数加一

    def get_action(self, state, symbol):
        '''
        根据状态和符号获取LR(0)分析表中的动作
        :param state: 状态
        :param symbol: 符号
        :return: 动作
        '''
        # 如果状态和符号在分析表中有对应的动作,则返回动作,否则返回空字符串
        symbol_index = self.states_table[0].index(symbol)
        state_index = state + 1

        action = self.states_table[state_index][symbol_index]

        return action

    def get_production_by_index(self, production_index):
        '''
        根据产生式的索引获取产生式
        :param production_index: 产生式的索引
        :return: 产生式
        '''
        # 在文法中查找该产生式的位置
        for left_symbol, productions in self.grammar.items():
            for index, production in enumerate(productions):
                if production_index == 0:
                    return left_symbol, production
                production_index -= 1





if __name__ == '__main__':

    # 创建Tkinter根窗口(不显示)
    root = tk.Tk()
    root.withdraw()  # 隐藏Tkinter根窗口

    # 显示自定义提示窗口
    info_message = """
    导入的文件格式示例:
    E -> aA
    E -> bB
    A -> cA
    A -> d
    B -> cB
    B -> d
    """
    messagebox.showinfo("提示", info_message)

    # 弹出文件选择对话框
    grammar_file_path = filedialog.askopenfilename(
        title="选择文件",
        filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
    )



    # 定义需要读取的文法文件的路径
    # grammar_file_path = 'src/grammar_2.txt'

    # 语法文件不为空
    if(grammar_file_path):
        grammar = ReadGrammar(grammar_file_path)  # 转换为该解析器能读取的字典格式
        lr0_parser = LR0Parser(grammar)  # 创建LR(0)分析器

    while True:
        print("\n选择你想要的功能:")
        print("1. 查看状态集")
        print("2. 查看状态表")
        print("3. 分析字符串")
        print("4. Exit")

        choice = input("Enter your choice (1-4): ")

        if choice == '1':
            lr0_parser.print_states()  # 打印该文法的状态集合
        elif choice == '2':
            print("-------------------------------")
            lr0_parser.print_table()  # 打印LR(0)的状态表
            print("-------------------------------")
        elif choice == '3':
            # 测试字符串 bccd
            input_string = input("Enter the string to parse: ")
            result = lr0_parser.parse_string(input_string)
            if result:
                print(f'该输入串:"{input_string}" 属于该文法')
            else:
                print(f'该输入串:"{input_string}" 不属于该文法')
        elif choice == '4':
            print("成功退出程序")
            break
        else:
            print("非法数字!")


结束语

如果有疑问欢迎大家留言讨论,你如果觉得这篇文章对你有帮助可以给我一个免费的赞吗?我们之间的交流是我最大的动力!

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

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

相关文章

【C#】CNC 机器人的刀具路径生成软件PathCAM源码解析-Geometry

1. Loaders 1.1 DAE_Loader.cs 1.2 OBJ_Loader.cs 1.3 STL_Loader.cs 2. AnalyzedTriangleMesh.cs AnalyzedTriangleMesh类是一个用于分析和处理三角形网格&#xff0c;可以被用于将网格拆分为更小的部件或者识别特定特征的对象&#xff0c;如打印准备或几何分析&#xff0c;非…

网络原理——HTTP

1. 什么是HTTP协议 HTTP是应用层的协议。Java最主要的应用场景是做网站&#xff0c;而网站由 后端&#xff08;HTTP服务器&#xff09; 和 前端&#xff08;浏览器&#xff09;组成&#xff0c;HTTP协议就是负责这里后端和前端的数据交互。 HTTP3.0 之前在传输层是通过 TCP传…

如何移除禁用WordPress默认小工具(附WordPress默认小工具名称)

WordPress 自带的小工具非常多&#xff0c;但是我们用到的也就那么几种&#xff0c;甚至一种都不会用到&#xff0c;所以很有必要注销&#xff08;去除&#xff09;掉一些不用的小工具。实现的方法也很简单&#xff0c;只需将以下代码&#xff0c;根据自己的情况删除需要用的小…

黄仁勋最新专访:机器人基础模型可能即将出现,新一代GPU性能超乎想象

最近&#xff0c;《连线》的记者采访了英伟达CEO黄仁勋。 记者表示&#xff0c;与Jensen Huang交流应该带有警告标签&#xff0c;因为这位Nvidia首席执行官对人工智能的发展方向如此投入&#xff0c;以至于在经过近 90 分钟的热烈交谈后&#xff0c;我&#xff08;指代本采访的…

复旦大学MBA:AIGC时代,科技与商业迸发更绚烂的火花

ChatGPT问世以来&#xff0c;AI技术及应用进入一个全速推进的通道&#xff0c;快速迈入通用大模型时代。从AGI(人工通用智能&#xff09;到AIGC(AI多模态内容生成&#xff09;&#xff0c;AI正在飞速重塑各个行业、人类生活乃至人类的未来。在商业领域更是给营销场景和营销工具…

134 Linux 系统编程11 ,readlink命令,文件目录rwx权限差异,目录操作函数

一 readlink 命令 前面知道&#xff0c;如果a.soft是一个软链接&#xff0c;我们使用 cat a.soft,会直接查看这个软链接指向的文件 那么我们就是想看这个软链接是啥&#xff0c;可以使用 readlink a.soft 二 获取工作目录 getcwd函数 获取进程当前工作目录 (卷3&#xff0c;标…

软考 系统分析师系列知识点之需求获取(1)

所属章节&#xff1a; 第11章. 软件需求工程 第2节. 需求获取 需求获取是一个确定和理解不同的项目干系人的需求和约束的过程。需求获取是一件看上去很简单、做起来却很难的事情。需求获取是否科学、准备是否充分&#xff0c;对获取出来的结果影响很大&#xff0c;这是因为大部…

Studio One 6 for Mac v6.5.1激活破解版(音乐制作工具)

Studio One是一款专业的音乐制作软件&#xff0c;由美国PreSonus公司开发。该软件提供了全面的音频编辑和混音功能&#xff0c;包括录制、编曲、合成、采样等多种工具&#xff0c;可用于制作各种类型的音乐&#xff0c;如流行音乐、电子音乐、摇滚乐等。 Studio One 6是一款功…

Elasticsearch安装需编译的版本分词器,出现的编译问题

一般来说&#xff0c;网上很多教程在讲如何安装es的ik分词器&#xff0c;包括项目文档也有提及&#xff1a;​​​​​​Releases medcl/elasticsearch-analysis-ik GitHub 如果是对应版本作者已经编译好的还比较容易安装&#xff0c;如下图&#xff1a; 但如果是只有源代码…

vue-router 三级路由,路由跳转页面异常白屏或404,或刷新三级路由页面后一级和二级路由菜单丢失

问题描述 情况1. vue-router 定义三级路由&#xff0c;路由跳转了&#xff0c;页面404或者白屏情况2. 点击菜单三级路由后&#xff0c;刷新页面后一级和二级路由菜单丢失 解决方案&#xff1a; 某些时候是因为二级和三级的路由共用router-view&#xff0c;可以使用router-vi…

基于ssm框架的高校班级管理系统设计与实现

为解决当前高校班级管理中管理方式落后、手段落后及效率低下等问题而以当前主流的互联网技术设计一款高校班级管理系统。该系统采用B/S模式的设计思路而将前端&#xff08;JSP技术&#xff09;和后端&#xff08;SSM框架MySQL数据库&#xff09;整合于一体并通过Java语言代码编…

Android java中包的使用

一.包的使用 为了更好的实现项目中类的管理&#xff0c;提供包的概念。 package语句作为Java源文件的第一条语句&#xff0c;指明该文件中定义的类所在的包。(若缺省该语句&#xff0c;则指定为无名包)。 它的格式为&#xff1a;package 顶层包名.子包名 ; 二.java中主要的包…

ES坑-创建索引使用_下划线-黑马旅游搜不到

学ES的时候&#xff0c;星级过滤无效 找不到数据。 需要 但是我们在创建的时候使用的是keyword 通过研究发现&#xff0c;我们导入数据的时候应该默认的为starName 我get库时候发现有2个字段 所以通过star_name搜索因为都是空数据搜不到&#xff0c;而starName类型为text所以…

LeetCode 0235.二叉搜索树的最近公共祖先:用搜索树性质(不遍历全部节点)

【LetMeFly】235.二叉搜索树的最近公共祖先&#xff1a;用搜索树性质&#xff08;不遍历全部节点&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/ 给定一个二叉搜索树, 找到该树中两个指定节点的最近公…

单机取证-信息安全管理与评估-2022年国赛真题-环境+wp

🍬 博主介绍 博主介绍:大家好,我是 Mikey ,很高兴认识大家~ 主攻:【应急响应】 【python】 【数字取证】【单机取证】【流量分析】【MISC】 🎉点赞➕评论➕收藏 == 养成习惯(一键三连)😋 🎉欢迎关注💗一起学习👍一起讨论⭐️一起进步 作者水平有限,欢迎各…

10-pytorch-完整模型训练

b站小土堆pytorch教程学习笔记 一、从零开始构建自己的神经网络 1.模型构建 #准备数据集 import torch import torchvision from torch.utils.tensorboard import SummaryWriterfrom model import * from torch.utils.data import DataLoadertrain_datatorchvision.datasets.…

WPF 启动项目 Grid、StackPanel 布局

WPF 启动项目 <!--x:Class"WPF_Study.App" 对应类&#xff1a;WPF_Study.App--> <!--xmlns:local"clr-namespace:WPF_Study" 命名空间&#xff1a;WPF_Study--> <Application x:Class"WPF_Study.App"xmlns"http://schema…

网络原理TCP之“三次握手“

TCP内核中的建立连接 众所周知,TCP是有连接的. 当我们在客户端敲出socket new Socket(serverIp,severPort)时,就在系统内核就在建立连接 真正建立连接是在系统内核中建立的,我们程序员只是调用相关的api. 在此处,我们把TCP的建立连接称为三次握手. 系统在内核建立连接时如上…

【Linux进程】进程状态---进程僵尸与孤儿

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1.进程排队2.进程状态…

OSCP靶场--Nickel

OSCP靶场–Nickel 考点(1.POST方法请求信息 2.ftp&#xff0c;ssh密码复用 3.pdf文件密码爆破) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.237.99 -sV -sC -p- --min-rate 5000 Starting Nmap 7.92 ( https://nmap.org ) at 2024-02-22 04:06 EST Nm…