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

[P4911]河童重工的计算机 - 题解

原题链接

题意简述

一道大模拟题,要求实现一种汇编语言的编译器。

主要操作有:

  • 内存操作
  • 寄存器操作
  • 函数调用
  • 各种逻辑和数值计算
  • I/O 操作

实现技巧

对于每一行的输入(除去注释),我们开一个结构体存函数名和各个参数。函数名可以使用字符串,参数使用一个多个字符串的数组(具体参见代码)。

可以预处理出一个 map 来存储每一个函数需要的参数个数。注意到题目并没有说一个函数不能输入大于所需个数的参数,但是多余的要过滤掉。

对于内存,开一个静态数组模拟就可以了。

对于 sADDr 栈,开一个栈模拟就可以了。

对于题目里的各个函数,把它们实现成多个独立的函数会更方便。

另外,由于对于一个参数我们需要进行复杂的判断,而这样的判断有很多,所以把取值和赋值分别写成两个函数调用会更好。

取值函数要输入当前行号和参数标号,然后经过以下判断:

  1. 该参数是否为寄存器
  2. 该参数是否为内存地址
  3. 该参数是否为寄存器所存的位置的内存地址
  4. 该参数是否为常量
  5. 该参数是否为编译时常量

判断完毕后根据参数的含义输出其中的值就行了。

赋值函数要输入当前行号和参数标号,然后经过以下判断:

  1. 该参数是否为寄存器
  2. 该参数是否为内存地址
  3. 该参数是否为寄存器对应的内存地址

判断完后根据参数含义改变其数值即可。

为便于调试和写部分分,建议先从 I/O 操作开始实现代码。

使用匿名函数实现题目所指的各个函数,可以方便地使用 map 来解决函数调用。以作者代码举例,直接使用 fc[fu[i].name](i) 即可访问第 i 行的函数。

要点概括

有如下难点:

  • 函数调用
  • 输入源代码
  • 注释处理

函数调用

开一个数组,存函数开始位置,在输入时如果输入到了函数定义就存一下对应的行号,在主循环上不使用 i++,而是实现一个跳转用的变量,调用的时候直接跳转到行。

输入源代码

需要自己写快读,每个单词开一个字符串,如果当前位是合法字符(不为注释和符号)就拼在字符串后面,输入完遇到空格或者分号就写入结构体然后清空。然后输入参数,与之类似,但是记得在输入个数足够的参数后就停止,不要输入过多个数的参数导致错误和超出数组长度。

换行一定用分号判!!!

经实验,判断换行符极易导致最后一个点 TLE,猜测不只有 '\n' 换行。

注释处理

实现一个变量,记录是否遇到左括号,但是只用实现为 bool 类型,不需要累加个数,因为只有第一个左括号作数,当它碰到第一个右括号就结束了注释。

注释嵌套不用管。

[[][] 等价,两个方括号中间的全是注释,这之间不用管单个左括号,只用看右括号。

指导

对于 string 类型,我们使用 map<string,int> 就可以实现在方括号中直接填寄存器名称字符串就可以访问到寄存器值的效果。

另外,map<string,function<void(int)>> 则可以直接把方括号填函数名的 map 当成函数,比如 fc[fu[i].name](i) 就可以直接访问第 i 行对应的函数,输入的参数为 i,但是这要求所有函数都是同一个类型(如 void),并且参数个数要一致,不过这在本题中很适用。

总结

这是一道很好的大模拟入门题,很适合作为新手第一道大模拟题,需要细心和耐心。

另外,大模拟考验程序设计能力,抄袭易被抓哦。

代码

#include<bits/stdc++.h>
using namespace std;
struct func{string name,c[11];} fu[1000005];//每一行的函数
int d[16777217],qp,ff,opt=1,pl,n;//d模拟内存
map<string,int> b={{"r1",0},{"r2",0},{"r3",0},{"r4",0},{"e1",0},{"e2",0},{"e3",0},{"e4",0},{"flag",0},{"val",0},{"ret",0},{"line",0}},f={{"udef",0},{"hlt",0},{"nop",0},{"set",2},{"jmp",1},{"jif",2},{"call",1},{"ret",1},{"inv",2},{"add",3},{"sub",3},{"mult",3},{"idiv",3},{"mod",3},{"lsft",3},{"rsft",3},{"band",3},{"bor",3},{"bxor",3},{"lgr",3},{"lls",3},{"lge",3},{"lle",3},{"leql",3},{"land",3},{"lor",3},{"rint",1},{"rch",1},{"wint",1},{"wch",1},{"function",1},{"callfunc",1},{"call",1}},fuct;//b存储各个寄存器值,f存储函数需要的参数个数
stack<pair<int,int>> sr;
int main()
{scanf("%d",&n);auto read=[](int h)//凭个人喜好使用了匿名函数,正常函数也可{char l=getchar();while(l=='\n'||l=='\r') l=getchar();string word;while(l!='\n'&&l!='\r') {if(l==' '||l==';'){if(word.size()!=0){if(f.count(word)>0&&fu[h].name.size()==0) fu[h].name=word;else{int flag=0;for(int i=1;!flag&&i<=f[fu[h].name];i++) if(fu[h].c[i].size()==0) flag=1,fu[h].c[i]=word;}word.erase();}}else{if(l=='[') qp=1;if(qp==0) if(l!=';') word+=l; if(l==']') qp=0;}if(l==';') return;l=getchar();}};for(int i=1;i<=n;i++) {read(i);if(fu[i].name=="function")fuct.insert({fu[i].c[1],i});}auto qz=[&](int h,int w)->int//取值{if(fu[h].c[w].size()==0) fu[h].c[w]="%val";int num,t=0;string l;if(fu[h].c[w][0]=='%') for(int i=1;i<fu[h].c[w].size();i++) l+=fu[h].c[w][i],t=b[l];else if(fu[h].c[w][0]=='@') {if(fu[h].c[w][1]=='%') for(int i=2;i<fu[h].c[w].size();i++) l+=fu[h].c[w][i],t=d[b[l]];else{for(int i=1;i<fu[h].c[w].size();i++) t*=10,t+=fu[h].c[w][i]-'0';t=d[t];}}else if(fu[h].c[w][0]=='#') {if(fu[h].c[w]=="#line") t=h;else for(int i=1;i<fu[h].c[w].size();i++) t*=10,t+=fu[h].c[w][i]-'0';}else for(int i=0;i<fu[h].c[w].size();i++) t*=10,t+=fu[h].c[w][i]-'0';return t;};auto fz=[&](int h,int w,int num)->void//赋值{if(fu[h].c[w].size()==0) fu[h].c[w]="%val";string l;if(fu[h].c[w][0]=='%') {for(int i=1;i<fu[h].c[w].size();i++) l+=fu[h].c[w][i];b[l]=num;}else if(fu[h].c[w][0]=='@') {if(fu[h].c[w][1]=='%') {for(int i=2;i<fu[h].c[w].size();i++) l+=fu[h].c[w][i];d[b[l]]=num;}else {int t=0;for(int i=1;i<fu[h].c[w].size();i++) t*=10,t+=fu[h].c[w][i]-'0';d[t]=num;}}};auto rint=[&](int h){int num;scanf("%d",&num);fz(h,1,num);};auto rch=[&](int h){fz(h,1,getchar());};auto wint=[&](int h){printf("%d",qz(h,1));};auto wch=[&](int h){putchar(qz(h,1));};auto add=[&](int h){fz(h,3,qz(h,1)+qz(h,2));};auto inv=[&](int h){fz(h,2,-qz(h,1));};auto sub=[&](int h){fz(h,3,qz(h,1)-qz(h,2));};auto mult=[&](int h){fz(h,3,qz(h,1)*qz(h,2));};auto idiv=[&](int h){fz(h,3,qz(h,1)/qz(h,2));};auto mod=[&](int h){fz(h,3,qz(h,1)%qz(h,2));};auto lsft=[&](int h){fz(h,3,qz(h,1)<<qz(h,2));};auto rsft=[&](int h){fz(h,3,qz(h,1)>>qz(h,2));};auto band=[&](int h){fz(h,3,qz(h,1)&qz(h,2));};auto bor=[&](int h){fz(h,3,qz(h,1)|qz(h,2));};auto bxor=[&](int h){fz(h,3,qz(h,1)^qz(h,2));};auto lgr=[&](int h){fz(h,3,qz(h,1)>qz(h,2));};auto lls=[&](int h){fz(h,3,qz(h,1)<qz(h,2));};auto lge=[&](int h){fz(h,3,qz(h,1)>=qz(h,2));};auto lle=[&](int h){fz(h,3,qz(h,1)<=qz(h,2));};auto leql=[&](int h){fz(h,3,qz(h,1)==qz(h,2));};auto land=[&](int h){fz(h,3,qz(h,1)&&qz(h,2));};auto lor=[&](int h){fz(h,3,qz(h,1)||qz(h,2));};auto call=[&](int h){sr.push({h+1,b["line"]});opt=qz(h,1)-h;};auto jmp=[&](int h){opt=b["line"]+qz(h,1)-h;};auto ret=[&](int h){if(!sr.empty()){opt=sr.top().first-h;sr.pop();}if(!fu[h].c[1].empty()) b["ret"]=qz(h,1);};auto callf=[&](int h){sr.push({h+1,b["line"]});opt=fuct[fu[h].c[1]]-h+1;b["line"]=opt+h-1;};auto funct=[&](int h){if(!sr.empty()){opt=h-sr.top().first;}};auto set=[&](int h){fz(h,2,qz(h,1));};auto jif=[&](int h){if((!fu[h].c[2].empty()&&qz(h,2)!=0)||(fu[h].c[2].empty()&&b["flag"]>0)) opt=qz(h,1)+b["line"]-h;};auto stop=[](int h){ff=1;};auto udef=[](int h){return;};map<string,function<void(int)>> fc={{"rint",rint},{"rch",rch},{"wint",wint},{"wch",wch},{"add",add},{"hlt",stop},{"ret",ret},{"inv",inv},{"sub",sub},{"mult",mult},{"idiv",idiv},{"mod",mod},{"lsft",lsft},{"rsft",rsft},{"band",band},{"bor",bor},{"bxor",bxor},{"function",funct},{"callfunc",callf},{"call",call},{"jmp",jmp},{"set",set},{"jif",jif},{"lgr",lgr},{"lls",lls},{"lge",lge},{"lle",lle},{"leql",leql},{"land",land},{"lor",lor},{"udef",udef},{"nop",udef}};//函数表,凭函数名字符串即可访问到函数for(int i=1;!ff&&i<=n;i+=opt,opt=1) fc[fu[i].name](i);return 0;
}
http://www.rkmt.cn/news/61718.html

相关文章:

  • 计算H和F矩阵变换图像 - MKT
  • 级语言程序设计课程第七次个人作业
  • 工业相机成像基础:传感器和分辨率
  • 评测姬
  • Kuscia 1.1.0 发布:新增带宽调度、Envoy 粘性会话与全面安全升级
  • 2025孕妇护手霜推荐:专治干燥敏感,孕期带娃安心无添加爆款实测
  • 鸿蒙一多开发:多设备适配
  • 海淀区婚姻律师推荐:专注婚姻家事法律服务机构参考
  • 有什么好玩的游戏?多款热门多人竞技游戏推荐
  • 适合和朋友一起玩的游戏推荐,这些互动体验值得尝试
  • jsdiff Webpack插件制作:实现构建过程中的代码差异分析
  • 深入解析:【论文阅读】SelfReg-UNet: Self-Regularized UNet for Medical Image Segmentation
  • 工厂用工业洗地机:提升车间清洁效率的实用设备
  • 转载,数据结构与算法----数组链表
  • 上海高温炉品牌推荐:聚焦工业加热设备优质选择
  • 新手购买云服务器怎么知道配置带宽是否够用
  • 国产仓储软件(WMS):助力企业实现精益智能仓储管理
  • 国内值得关注的高温炉工厂有哪些?
  • 防爆烘箱厂家哪家强?国内优质厂商及设备特点解析
  • 仓储软件(WMS)值得推荐的行业应用与选择参考
  • JavaScript 事件循环,Promise 与 async/await
  • 删除现有k8s集群
  • 习题解析之:列表删除数据
  • 2025年挂镀生产线直销厂家权威推荐榜单:吊镀设备/热镀锌生产线/吹镀设备源头厂家精选
  • 基于自适应双门限的能量检测算法
  • 笔试强训:Week-3 - 详解
  • 2025年粉末冶金件夹爪供应商推荐:柔性抓取技术如何赋能精密制造
  • 2025年无花果酒产业链供应厂家深度解析:五家特色企业综合评测
  • 动态前瞻技术提升语音识别准确率
  • 2025年无线投屏产品推荐:从专业到家用,全方位解析,精准避坑