当前位置: 首页 > news >正文

编译原理第一次实验报告

  • 源代码及附件:编译原理实验一源程序及附件资源-CSDN文库
  • 实验题目

  • 实验要求

  • 实验设计

前两部分指出了实验的宏观把控,为了具体实施实验,我们需要预先为实验做出如下设计:

本次实验我选取了C语言的一个子集进行设计词法分析器,其中单词种类如下:(也可参考附件中的单词种类表)

根据题目要求,我们用正则文法来定义我们的子集:

  1. S→关键字|运算符|分界符|整型常量|浮点型常量|标识符
  2. 关键字

→ void|main|int|float|for|while|switch|case|if|else|return|break

(3)运算符 → +|-|*|/|=|==|<|<=|>|>=

(4)分界符 → (|)|[|]|{|}|,|;|:

(5)整型常量 → digit(digit)*

(6)浮点型常量 → digit(digit).digit(digit)

(7)digit→ 0|1|2|3|4|5|6|7|8|9

(8)letter→ a|b|…|z|A|B|…|Z

(9)标识符 → letter(letter|digit)*

  • 实验分析

基本算法思想是:读取文件,逐个字符分析,若是空白符则跳过,为字母时将连续的字母使用超前搜索组合成为变量或关键字;若是数字,则要判断是否为浮点数,即利用超前搜索,判断扫描到的字符是否为小数点;若是分隔符或者操作符,利用switch语句判断并输出,若是其他字符,输出为未定义的字符。

相关代码段:

void lexicalAnalysis(FILE* fp)

{

    char ch;        

    while ((ch = fgetc(fp)) != EOF)    /

    {

        token = ch;                                   

        if (ch == ' ' || ch == '\t' || ch == '\n'//忽略空格、Tab和回车

        {

             if (ch == '\n')                            //遇到换行符,记录行数的row加1

                 row++;

             continue;                                

        }

        else if (isLetter(ch))        //以字母开头,关键字或标识符

        {

             token = "";                   //token初始化

             while (isLetter(ch) || isDigit(ch)) //非字母或数字时退出,将单词存储在token中

             {

                 token.push_back(ch);  //将读取的字符ch存入token中

                 ch = fgetc(fp);           //获取下一个字符

             }

             //文件指针后退一个字节,即重新读取上述单词后的第一个字符

             fseek(fp, -1L, SEEK_CUR);

             if (isKey(token)) //关键字

                 code = TokenCode(getKeyID(token));

             else //标识符

                 code = TK_IDENT; //单词为标识符

        }

        else if (isDigit(ch)) //无符号常数以数字开头

        {

             int isdouble = 0; //标记是否为浮点数

             token = "";          //token初始化

             while (isDigit(ch))   //当前获取到的字符为数字

             {

                 token.push_back(ch);      //读取数字,将其存入token中

                 ch = fgetc(fp);               //从文件中获取下一个字符

                 //该单词中第一次出现小数点

                 if (ch == '.' && isdouble == 0)

                 {

                     //小数点下一位是数字

                     if (isDigit(fgetc(fp)))

                     {

                         isdouble = 1;    //标记该常数中已经出现过小数点

                         fseek(fp, -1L, SEEK_CUR);     //将超前读取的小数点后一位重新读取

                         token.push_back(ch);          //将小数点入token中

                         ch = fgetc(fp);               //读取小数点后的下一位数字

                     }

                 }

             }

             if (isdouble == 1)

                 code = TK_DOUBLE; //单词为浮点型

             else

                 code = TK_INT;                //单词为整型

             //文件指针后退一个字节,即重新读取常数后的第一个字符

             fseek(fp, -1L, SEEK_CUR);

        }

        else switch (ch)

        {

             /*运算符*/

        case '+': code = TK_PLUS;     //+加号         

             break;

        case '-': code = TK_MINUS;    //-减号

             break;

        case '*': code = TK_STAR;     //*乘号     

             break;

        case '/': code = TK_DIVIDE;        //除号

             break;

        case '=':

        {

             ch = fgetc(fp);               //超前读取'='后面的字符

             if (ch == '=')                //==等于号

             {

                 token.push_back(ch);  //将'='后面的'='存入token中

                 code = TK_EQ;        //单词为"=="

             }

             else {                        //=赋值运算符

                 code = TK_ASSIGN;     //单词为"="

                 fseek(fp, -1L, SEEK_CUR); //将超前读取的字符重新读取

             }

        }

        break;

        case '<':

        {

             ch = fgetc(fp);               //超前读取'<'后面的字符

             if (ch == '=')                //<=小于等于号

             {

                 token.push_back(ch);  //将'<'后面的'='存入token中

                 code = TK_LEQ;            //单词为"<="

             }

             else {                        //<小于号

                 code = TK_LT;        //单词为"<"

                 fseek(fp, -1L, SEEK_CUR); //将超前读取的字符重新读取

             }

        }

        break;

        case '>':

        {

             ch = fgetc(fp);               //超前读取'>'后面的字符

             if (ch == '=')                //>=大于等于号

             {

                 token.push_back(ch);  //将'>'后面的'='存入token中

                 code = TK_GEQ;            //单词为">="

             }

             else {                        //>大于号

                 code = TK_GT;        //单词为">"

                 fseek(fp, -1L, SEEK_CUR); //将超前读取的字符重新读取

             }

        }

        break;

        /*分界符*/

        case '(': code = TK_OPENPA;        //(左圆括号

             break;

        case ')': code = TK_CLOSEPA;   //)右圆括号

             break;

        case '[': code = TK_OPENBR;        //[左中括号

             break;

        case ']': code = TK_CLOSEBR;   //]右中括号

             break;

        case '{': code = TK_BEGIN;    //{左大括号

             break;

        case '}': code = TK_END;      //}右大括号

             break;

        case ',': code = TK_COMMA;    //,逗号

             break;

        case ';': code = TK_SEMOCOLOM; //;分号

             break;

        case':':code = TK_MAO;//:冒号

             break;

             //未识别符号

        default: code = TK_UNDEF;

        }

        print(code);              //打印词法分析结果

    }

}

定义了如下数据结构作为状态终态:

    /* 关键字 */

    KW_VOID, //void关键字

    KW_MAIN, //main关键字

    KW_INT,      //int关键字

    KW_DOUBLE,   //double关键字

    KW_FOR,      //for关键字

    KW_WHILE,    //while关键字

    KW_SWITCH,   //switch关键字

    KW_CASE, //case关键字

    KW_IF,       //if关键字

    KW_ELSE, //else关键字

    KW_RETURN,   //return关键字

    KW_BREAK,//break关键字

    /* 运算符 */

    TK_PLUS, //+加号

    TK_MINUS,    //-减号

    TK_STAR, //*乘号

    TK_DIVIDE,   ///除号

    TK_ASSIGN,   //=赋值运算符

    TK_EQ,       //==等于号

    TK_LT,       //<小于号

    TK_LEQ,      //<=小于等于号

    TK_GT,       //>大于号

    TK_GEQ,      //>=大于等于号

    TK_MAO,    //:冒号

    /* 分隔符 */

    TK_OPENPA,   //(左圆括号

    TK_CLOSEPA//)右圆括号

    TK_OPENBR,   //[左中括号

    TK_CLOSEBR//]右中括号

    TK_BEGIN,    //{左大括号

    TK_END,      //}右大括号

    TK_COMMA,    //,逗号

    TK_SEMOCOLOM, //;分号

    /* 常量 */

    TK_INT,      //整型常量

    TK_DOUBLE,   //浮点型常量

    /* 标识符 */

TK_IDENT

  为了使得输出有所取分,使用不同颜色输出:

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED); //未识别的符号为红色

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);    //关键字为蓝色

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);   //运算符和分隔符为绿色

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);   //常量为黄色

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY); //关键字为灰色

利用文件作为输入。

输入文档1.txt:

double add(double x, double y)

{

    double a = 3.456;

    return x + y;

}

$

int main()

{

            int i;

            switch(i)

           {

               case 1:   break;

            }

            if(double(i,i)>i)

                  break;

            int a[10];

}         

输出结果为:

其中注意红色标记:

说明我们实现了错误识别的功能。

  • 源代码

#include <iostream>

#include <string>

#include <Windows.h>

using namespace std;

/* 单词编码 */

enum TokenCode

{

    /*未定义*/

    TK_UNDEF = 0,

    /* 关键字 */

    KW_VOID, //void关键字

    KW_MAIN, //main关键字

    KW_INT,      //int关键字

    KW_DOUBLE,   //double关键字

    KW_FOR,      //for关键字

    KW_WHILE,    //while关键字

    KW_SWITCH,   //switch关键字

    KW_CASE, //case关键字

    KW_IF,       //if关键字

    KW_ELSE, //else关键字

    KW_RETURN,   //return关键字

    KW_BREAK,//break关键字

    /* 运算符 */

    TK_PLUS, //+加号

    TK_MINUS,    //-减号

    TK_STAR, //*乘号

    TK_DIVIDE,   ///除号

    TK_ASSIGN,   //=赋值运算符

    TK_EQ,       //==等于号

    TK_LT,       //<小于号

    TK_LEQ,      //<=小于等于号

    TK_GT,       //>大于号

    TK_GEQ,      //>=大于等于号

    TK_MAO,    //:冒号

    /* 分隔符 */

    TK_OPENPA,   //(左圆括号

    TK_CLOSEPA//)右圆括号

    TK_OPENBR,   //[左中括号

    TK_CLOSEBR//]右中括号

    TK_BEGIN,    //{左大括号

    TK_END,      //}右大括号

    TK_COMMA,    //,逗号

    TK_SEMOCOLOM, //;分号

    /* 常量 */

    TK_INT,      //整型常量

    TK_DOUBLE,   //浮点型常量

    /* 标识符 */

    TK_IDENT

};

TokenCode code = TK_UNDEF;    //记录单词的种别码

const int MAX = 12;               //关键字数量

int row = 1;                  //记录字符所在的行数

string token = "";                //用于存储单词

char  keyWord[][10] = { "void","main","int","double","for","while","switch","case","if","else","return","break"};    //存储关键词

void print(TokenCode code)

{

    switch (code)

    {

        /*未识别的符号*/

    case TK_UNDEF:

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED); //未识别的符号为红色

        cout << '(' << code << ',' << token << ")" << "未识别的符号在第" << row << "行。" << endl;

        return;

        break;

        /*关键字*/

    case KW_VOID:

    case KW_MAIN:

    case KW_INT:    

    case KW_DOUBLE

    case KW_FOR:    

    case KW_WHILE:  

    case KW_SWITCH

    case KW_CASE:

    case KW_IF:     

    case KW_ELSE:

    case KW_RETURN

    case KW_BREAK:

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);    //关键字为蓝色

        break;

        /* 运算符 */

    case TK_PLUS:

    case TK_MINUS:  

    case TK_STAR:

    case TK_DIVIDE

    case TK_ASSIGN

    case TK_EQ:     

    case TK_LT:     

    case TK_LEQ:

    case TK_GT:     

    case TK_GEQ:        

    /* 分隔符 */

    case TK_OPENPA

    case TK_CLOSEPA:

    case TK_OPENBR

    case TK_CLOSEBR:

    case TK_BEGIN:  

    case TK_END:

    case TK_COMMA:  

    case TK_SEMOCOLOM:   

    case TK_MAO:   

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);   //运算符和分隔符为绿色

        break;

        /* 常量 */

    case TK_INT:

    case TK_DOUBLE

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);   //常量为黄色

        if (token.find('.') == token.npos)

             cout << '(' << code << ',' << atoi(token.c_str()) << ")" << endl;                     

        else

             cout << '(' << code << ',' << atof(token.c_str()) << ")" << endl;                         

        return;

        break;

        /* 标识符 */

    case TK_IDENT:

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY); //关键字为灰色

        break;

    default:

        break;

    }

    cout << '(' << code << ',' << token << ")" << endl;

}

bool isKey(string token)

{

    for (int i = 0; i < MAX; i++)

    {

        if (token.compare(keyWord[i]) == 0)

             return true;

    }

    return false;

}

int  getKeyID(string token)

{

    for (int i = 0; i < MAX; i++)

    {   //关键字的内码值为keyWord数组中对应的下标加1

        if (token.compare(keyWord[i]) == 0)

             return i + 1;

    }

    return -1;

}

bool isLetter(char letter)

{

    if ((letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z'))

        return true;

    return false;

}

bool isDigit(char digit)

{

    if (digit >= '0' && digit <= '9')

        return true;

    return false;

}

void lexicalAnalysis(FILE* fp1)

{

    char ch;        

    while ((ch = fgetc(fp1)) != EOF)  

    {

        token = ch;                                   

        if (ch == ' ' || ch == '\t' || ch == '\n'

        {

             if (ch == '\n')                           

                 row++;

             continue;                                

        }

        else if (isLetter(ch))       

        {

             token = "";                  

             while (isLetter(ch) || isDigit(ch))

             {

                 token.push_back(ch); 

                 ch = fgetc(fp1);     

             }

             fseek(fp1, -1L, SEEK_CUR);

             if (isKey(token))

                 code = TokenCode(getKeyID(token));

             else

                 code = TK_IDENT;

        }

        else if (isDigit(ch))

        {

             int isdouble = 0;

             token = "";         

             while (isDigit(ch))  

             {

                 token.push_back(ch);     

                 ch = fgetc(fp1);             

                

                 if (ch == '.' && isdouble == 0)

                 {

                     if (isDigit(fgetc(fp1)))

                     {

                         isdouble = 1;   

                         fseek(fp1, -1L, SEEK_CUR);   

                         token.push_back(ch);         

                         ch = fgetc(fp1);             

                     }

                 }

             }

             if (isdouble == 1)

                 code = TK_DOUBLE;

             else

                 code = TK_INT;               

             fseek(fp1, -1L, SEEK_CUR);

        }

        else switch (ch)

        {

        case '+': code = TK_PLUS;                 

             break;

        case '-': code = TK_MINUS;   

             break;

        case '*': code = TK_STAR;             

             break;

        case '/': code = TK_DIVIDE;       

             break;

        case '=':

        {

            ch = fgetc(fp1);             

             if (ch == '=')               

             {

                 token.push_back(ch); 

                 code = TK_EQ;       

             }

             else {                       

                 code = TK_ASSIGN;    

                 fseek(fp1, -1L, SEEK_CUR);

             }

        }

        break;

        case '<':

        {

             ch = fgetc(fp1);             

             if (ch == '=')               

            {

                 token.push_back(ch); 

                 code = TK_LEQ;           

             }

             else {                       

                 code = TK_LT;       

                 fseek(fp1, -1L, SEEK_CUR);

             }

        }

        break;

        case '>':

        {

             ch = fgetc(fp1);             

             if (ch == '=')               

             {

                 token.push_back(ch); 

                 code = TK_GEQ;           

             }

             else {                       

                 code = TK_GT;       

                 fseek(fp1, -1L, SEEK_CUR);

             }

        }

        break;

       

        case '(': code = TK_OPENPA;       

             break;

        case ')': code = TK_CLOSEPA;  

             break;

        case '[': code = TK_OPENBR;       

             break;

        case ']': code = TK_CLOSEBR;  

             break;

        case '{': code = TK_BEGIN;   

             break;

        case '}': code = TK_END;     

             break;

        case ',': code = TK_COMMA;   

             break;

        case ';': code = TK_SEMOCOLOM;

             break;

        case':':code = TK_MAO;

             break;

            

        default: code = TK_UNDEF;

        }

        print(code);              //打印词法分析结果

    }

}

int main()

{

    string filename;     

    FILE* fp1;               

    cout << "请输入源文件名:" << endl;

    while (true) {

        cin >> filename;     

        if ((fopen_s(&fp1, filename.c_str(), "r")) == 0)    

             break;

        else

             cout << "路径输入错误!" << endl; 

    }

    cout << "/=***************************词法分析结果***************************=/" << endl;

    lexicalAnalysis(fp1);     //词法分析

    fclose(fp1);

    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); //字体恢复原来的颜色

    return 0;

}

  • 实验总结

这是编译原理的第一次实验,之前因为理解题意不明,也与老师探讨了多次,上网查阅各种资料等等,最终终于完成了实验。

在实验过程中发生过种种问题,一开始为图方便,想到过使用硬编码来实现实验,但最终还是使用了FA的方式。

通过本次实验,我对NFA、DFA的知识有了更深入的了解,编程能力也进一步增强,可以说这次实验是我对编译原理与实际应用的第一次初步实现,对我的影响深远!

相关文章:

编译原理第一次实验报告

源代码及附件&#xff1a;编译原理实验一源程序及附件资源-CSDN文库实验题目 实验要求 实验设计 前两部分指出了实验的宏观把控&#xff0c;为了具体实施实验&#xff0c;我们需要预先为实验做出如下设计&#xff1a; 本次实验我选取了C语言的一个子集进行设计词法分析器&…...

uniapp的video视频属性打包app后层级过高

问题&#xff1a;在使用uniapp开发APP时&#xff0c;使用video标签显示视频发现H5可以正常展示&#xff0c;但是打包到APP后&#xff0c;它的层级过高&#xff0c;把底部导航都盖住了。 官网说明&#xff1a;uni-app官网 官网给了cover-view组件或plus.nativeObj.view、subNVue…...

问:Redis为什么这么快?

Redis&#xff0c;全称Remote Dictionary Server&#xff0c;是一个开源的高性能键值对数据库。它以其卓越的性能、丰富的数据结构和灵活的使用方式&#xff0c;在现代互联网应用中扮演着重要角色。本文将探讨Redis之所以快的原因&#xff0c;包括其数据结构、内存管理、IO多路…...

环信鸿蒙IM SDK实现附件消息发送与下载

环信HarmonyOS IM SDK 正式版已经发布&#xff0c;该版本全面覆盖即时通讯&#xff08;IM&#xff09;的核心功能&#xff0c;为用户提供了完整的IM全功能体验&#xff0c;同时支持从Android APK到 NEXT 的数据迁移&#xff0c;更好地满足企业在不同业务场景下的适配需求。 点…...

探索NetCat:网络流量监测与数据传输的利器

从简单的数据传输到复杂的网络调试&#xff0c;NetCat的灵活性和多功能性让人赞叹不已&#xff0c;在这篇文章中我将深入探讨NetCat的魅力&#xff0c;揭示它的基本功能、实用技巧以及在日常工作中的应用场景&#xff0c;发现如何用这一小工具提升的网络技能与效率。 目录 Net…...

【运动的&足球】足球运动员球守门员裁判检测系统源码&数据集全套:改进yolo11-DBBNCSPELAN

改进yolo11-FocalModulation等200全套创新点大全&#xff1a;足球运动员球守门员裁判检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.28 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示…...

求最大公约数,最小公倍数

输入两个正整数 m 和 n&#xff0c;求其最大公约数和最小公倍数。 求最小公倍数算法&#xff1a; 最小公倍数 两整数的乘积 最大公约数 根据求最小公倍数的算法&#xff0c;可以看出如果已知最大公约数&#xff0c;就能很容易求出最小公倍数。而通过辗转相除法和相减法&#…...

Android——横屏竖屏

系统配置变更的处理机制 为了避免横竖屏切换时重新加载界面的情况&#xff0c;Android设计了一中配置变更机制&#xff0c;在指定的环境配置发生变更之时&#xff0c;无需重启活动页面&#xff0c;只需执行特定的变更行为。该机制的视线过程分为两步&#xff1a; 修改 Androi…...

scala---10.30

val、var package com_1030class Person {var name:String"rose"def sum(n1:Int,n2:Int):Int{n1n2} } object Person{def main(args: Array[String]): Unit {//创建person对象var personnew Person()println(person.sum(10,20))//30println(person.name)person.nam…...

Pinctrl子需要中client端使用pinctrl过程的驱动分析

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体 input子系统专栏…...

【网络】传输层协议TCP

目录 四位首部长度 序号 捎带应答 标记位 超时重传机制 连接管理机制&#xff08;RST标记位&#xff09; 三次握手及四次挥手的原因 TCP的全称是传输控制协议&#xff08;Transmission Control Protocol&#xff09;&#xff0c;也就是说&#xff0c;对于放到TCP发送缓冲…...

00-开发环境 MPLAB IDE 配置

MPLAB IDE V8.83 File 菜单简介 New (CtrlN)&#xff1a; 创建一个新文件&#xff0c;用于编写新的代码。 Add New File to Project...&#xff1a; 将新文件添加到当前项目中。 Open... (CtrlO)&#xff1a; 打开现有文件。 Close (CtrlE)&#xff1a; 关闭当前打开的文件。 …...

<meta property=“og:type“ content=“website“>

<meta property"og:type" content"website"> ​ 这段代码是HTML中的一部分&#xff0c;具体来说&#xff0c;它是一个用于定义Open Graph协议的meta标签。 代码分析 <meta> 标签&#xff1a;这是一个HTML标签&#xff0c;用于在HTML文档的头…...

C++ 实现俄罗斯方块游戏

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

QT打包Macosx应用发布App Store简易流程

1、QC里编译工程&#xff0c;生成Release版的的app文件&#xff1b; 2、运行macdeployqt把需要的文件打包进app文件中&#xff1b; % ~/Qt/5.15.0/clang_64/bin/macdeployqt {编译的app文件所在路径}/Release/xxxx.app 3、使用codesign对app进行签名&#xff0c;如果要发App…...

untiy mlagents 飞机大战 ai训练

前言 之前那个python源码的飞机大战bug过多&#xff0c;还卡顿&#xff0c;难以继续训练。可直接放弃的话又不甘心&#xff0c;所以找了个unity版本的飞机大战继续(终于不卡了)&#xff0c;这次直接使用现成的mlagents库。 过程 前前后后花了两周时间&#xff0c;甚至因此拖…...

从0开始学统计-什么是中心极限定理

引言 中心极限定理&#xff08;Central Limit Theorem, CLT&#xff09;是统计学中的一块基石&#xff0c;它揭示了一个难以置信的数学现象&#xff1a;无论一个随机变量的原始分布如何&#xff0c;只要我们取足够大的样本量&#xff0c;这些样本的平均值&#xff08;或总和&a…...

工具方法 - 个人活动的分类

人类活动的分类是一个复杂的话题&#xff0c;因为人类的活动范围非常广泛且相互交叉。然而&#xff0c;我们可以尝试将人类的活动大致分为以下几个主要类别&#xff1a; 工作活动 工作活动是人类生活中不可或缺的一部分&#xff0c;通常包括以下方面&#xff1a; 1. 职业工作&a…...

11.1组会汇报-基于区块链的安全多方计算研究现状与展望

基础知识 *1.背书&#xff0c;这个词源来自银行票据业务&#xff0c;是指票据转让时&#xff0c;原持有人在票据背面加盖自己的印鉴&#xff0c;证明该票据真实有效、如果有问题就可以找原持有人。 区块链中的背书就好理解了。可以简单的理解为验证交易并声明此交易合法&…...

ubuntu【桌面】 配置NAT模式固定IP

DHCP分配导致虚拟机IP老变&#xff0c;SSH老要重新配置&#xff0c;设成静态方便些 一、设NAT模式 1、设为NAT模式 2、看模式对应的虚拟网卡 - VMnet8 3、共享主机网卡网络到虚拟网卡 - VMnet8 二、为虚拟网卡设置静态IP 记住这个IP 三、设置ubuntu固定IP 1、关闭DHCP并…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...