编译原理第一次实验报告
- 源代码及附件:编译原理实验一源程序及附件资源-CSDN文库
- 实验题目
- 实验要求
- 实验设计
前两部分指出了实验的宏观把控,为了具体实施实验,我们需要预先为实验做出如下设计:
本次实验我选取了C语言的一个子集进行设计词法分析器,其中单词种类如下:(也可参考附件中的单词种类表)
根据题目要求,我们用正则文法来定义我们的子集:
- S→关键字|运算符|分界符|整型常量|浮点型常量|标识符
- 关键字
→ 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的知识有了更深入的了解,编程能力也进一步增强,可以说这次实验是我对编译原理与实际应用的第一次初步实现,对我的影响深远!
相关文章:

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

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

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

环信鸿蒙IM SDK实现附件消息发送与下载
环信HarmonyOS IM SDK 正式版已经发布,该版本全面覆盖即时通讯(IM)的核心功能,为用户提供了完整的IM全功能体验,同时支持从Android APK到 NEXT 的数据迁移,更好地满足企业在不同业务场景下的适配需求。 点…...

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

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

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

Android——横屏竖屏
系统配置变更的处理机制 为了避免横竖屏切换时重新加载界面的情况,Android设计了一中配置变更机制,在指定的环境配置发生变更之时,无需重启活动页面,只需执行特定的变更行为。该机制的视线过程分为两步: 修改 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过程的驱动分析
往期内容 本专栏往期内容: Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析:imx_pinctrl_soc_info结构体 input子系统专栏…...

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

00-开发环境 MPLAB IDE 配置
MPLAB IDE V8.83 File 菜单简介 New (CtrlN): 创建一个新文件,用于编写新的代码。 Add New File to Project...: 将新文件添加到当前项目中。 Open... (CtrlO): 打开现有文件。 Close (CtrlE): 关闭当前打开的文件。 …...

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

C++ 实现俄罗斯方块游戏
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

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

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

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

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

11.1组会汇报-基于区块链的安全多方计算研究现状与展望
基础知识 *1.背书,这个词源来自银行票据业务,是指票据转让时,原持有人在票据背面加盖自己的印鉴,证明该票据真实有效、如果有问题就可以找原持有人。 区块链中的背书就好理解了。可以简单的理解为验证交易并声明此交易合法&…...

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

评估 机器学习 回归模型 的性能和准确度
回归 是一种常用的预测模型,用于预测一个连续因变量和一个或多个自变量之间的关系。 那么,最后评估 回归模型 的性能和准确度非常重要,可以帮助我们判断模型是否有效并进行改进。 接下来,和大家分享如何评估 回归模型 的性能和准…...

如何下载安装TestLink?
一、下载TestLink、XAMPP TestLink 下载 |SourceForge.net 备用:GitHub - TestLinkOpenSourceTRMS/testlink-code: TestLink开源测试和需求管理系统 下载XAMPP: Download XAMPP 注意:TestLink与PHP版本有关系,所以XA…...

基于SSM+微信小程序的订餐管理系统(点餐2)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的订餐管理系统实现了管理员和用户。管理端实现了 首页、个人中心、用户管理、菜品分类管理、菜品信息管理、订单信息管理、配送信息管理、菜品评价管理、订单投诉管理、…...

【C++排序 双指针】1996. 游戏中弱角色的数量|1996
本文涉及的基础知识点 排序 C算法:滑动窗口及双指针总结 本题其它解法 【C单调栈 排序】1996. 游戏中弱角色的数量|1996 LeetCode1996. 游戏中弱角色的数量 你正在参加一个多角色游戏,每个角色都有两个主要属性:攻击 和 防御 。给你一个…...

GESP4级考试语法知识(捕捉异常)
参考程序代码: #include <iostream> using namespace std;double divide(double a, double b) {if (b 0) {throw "Division by zero error"; // 抛出异常}return a / b; }int main() {double num1, num2;cout << "Enter two numbers:…...

HTML 基础标签——元数据标签 <meta>
文章目录 1. `<meta>` 标签概述2. 属性详解2.1 `charset` 属性2.2 `name` 属性2.3 `content` 属性2.4 `http-equiv` 属性3. 其他常见属性小结在 HTML 文档中,元数据标签 <meta> 是一种重要的标签,用于提供关于文档的信息,这些信息不直接显示在网页内容中,但对于…...

栈虚拟机和寄存器虚拟机,有什么不同?
本来这节内容是打算直接讲字节码指令的,但讲之前又必须得先讲指令集架构,而指令集架构又分为两种,一种是基于栈的,一种是基于寄存器的。 那不妨我们这节就单独来讲讲栈虚拟机和寄存器虚拟机,它们有什么不同࿰…...

Windows下基于fping进行批量IP测试
fping是Linux下一个很好用的IP测试工具,结合代码可以完成批量的IP测试,在网络调试中用途很广。本文是基于fping for Windows结合bat批处理,定制的测试脚本样例。 一、程序信息 本次测试使用fpingV5.1 for Windows版,版本信息如下…...

一款实用的Word文档图片转换与水印保护工具
目录 前言软件功能简介软件实现方法及关键代码 1. Word 文档转图片的实现2. 图片水印添加功能3. 生成数字指纹(哈希值)4. 保存图片信息到 JSON 文件 软件的实际使用场景软件操作指南 1. 下载和安装2. 操作流程 总结 1,前言 在日常办公和内…...

优化用于传感应用的衬底集成波导技术
ANSYS HFSS 是一款功能强大的电磁仿真软件,支持为微流体生物传感器应用设计和分析衬底集成波导 (SIW) 技术。它为快速设计优化、材料选择、系统集成和虚拟原型制作提供了一个强大的平台。借助 ANSYS HFSS,研究人员和工程师可以高效…...