☀️☃️☃️☃️☀️ • 4天前
#include<iostream>
#include<vector>
#include<unordered_map>
#include<unordered_set>
using namespace std;
struct var { //变量
long long addr; //起始地址
string name; //变量名
int type; //类型编号
};
struct type { //变量类型
unordered_map<string, var> slist; //根据名称查到子成员的哈希表
vector<var> vlist; //子成员列表,视为变量
long long size = 0; //占用大小
int align = 0; //对齐大小
type() {
}
type(long long s) {
size = align = s;
}
};
unordered_map<string, int> tm; //根据名称查到变量类型在类型表tv的数组下标
vector<type> tv; //类型表
unordered_map<string, var> slist; //根据变量名快速查到变量
vector<var> vlist; //内存中的变量表
long long addr; //已用内存
inline void alignM(long long& a, int b) { //a对齐b,即向上取整
if (a % b) a = a / b * b + b;
}
var lower(vector<var>& a, long long addr) {
//二分查找,占用起始内存地址小于addr的最大变量
int left = 0, right = a.size() - 1;
while (left < right) {
int mid = (left + right) / 2 + 1;
if (a[mid].addr <= addr) left = mid;
else right = mid - 1;
}
return a[left];
}
int main() {
int n, op, k;
string s, t;
cin >> n;
tv.push_back(type(1)); //手动输入基础类型
tm["byte"] = 0;
tv.push_back(type(2));
tm["short"] = 1;
tv.push_back(type(4));
tm["int"] = 2;
tv.push_back(type(8));
tm["long"] = 3;
for (int a = 0; a < n; a++) {
cin >> op;
if (op == 1) { //操作1
type nt;
cin >> s >> k;
for (int i = 0; i < k; i++) {
var v;
cin >> t >> v.name; //输入的子成员变量类型和名称
v.type = tm[t]; //在变量类型中根据名称快速找出变量类型
int align = tv[v.type].align; //根据变量类型得出对齐大小
nt.align = max(align, nt.align); //结构是每个子成员对齐大小的最大值
alignM(nt.size, align); //安排这个新成员时,在结构体内,先给他对齐
v.addr = nt.size; //这个新成员在结构内的起始地址即为对齐后的占用内存大小
nt.size += tv[v.type].size; //总占用内存加上这个元素占用的内存
nt.slist[v.name] = v; //放入名称查询子成员表
nt.vlist.push_back(v); //放入子成员列表
}
alignM(nt.size, nt.align); //最后再对齐
tm[s] = tv.size(); //放入名称查询变量类型表
tv.push_back(nt); //放入变量类型列表
cout << nt.size << " " << nt.align << endl;
}
else if (op == 2) { //操作2
var v;
cin >> t >> v.name; //输入变量类型和名称
v.type = tm[t]; //根据名称查出类型
type ty = tv[tm[t]]; //找到 变量类型
alignM(addr, ty.align); //总内存对齐
v.addr = addr; //起始地址即为对齐后总内存
addr += ty.size; //总内存占用加上这个变量占用的内存
vlist.push_back(v); //加入内存变量表
slist.insert({ v.name, v }); //放入名称查询变量表
cout << v.addr << endl;
}
else if (op == 3) { //操作3
cin >> s;
string first = s.substr(0, s.find('.')); //取出第一个.前的
var v = slist[first]; //在内存变量表中找到这个变量
type ty = tv[v.type]; //找到变量对于的类型
long long ans = v.addr; //先记录此变量在内存中的起始地址,后续再加上偏移地址
while (s.find('.') != -1) { //找到最后一层为止
s = s.substr(s.find('.') + 1);
string name = s.substr(0, s.find('.')); //取出下一层成员的名称
v = ty.slist[name]; //在变量类型的子成员表中找出子成员(变量)
ty = tv[v.type]; //再根据子成员的类型在变量类型表中找出类型
ans += v.addr; //加上这个子成员在结构体内的起始地址(即偏移地址)
}
cout << ans << endl;
} if (op == 4) { //操作4
long long addr;
cin >> addr;
string ans = "";
if (vlist.size() == 0) { //特判如果内存中无变量,必然不存在
ans = "ERR";
}
else {
var v = lower(vlist, addr); //先在内存变量表中找到起始地址小于addr,最大下标的变量
addr -= v.addr; //减去此变量的起始地址,考虑addr在此变量内部的偏移地址
type ty = tv[v.type]; //找到变量对应的类型
if (addr >= ty.size) ans = "ERR"; //如果类型的占用的空间比addr小,那个位置就是空着的
else { //因为题目要求直到基础类型位置
ans = v.name; //记录变量名
while (ty.vlist.size()) { //子成员的数量=0即为基础类型
v = lower(ty.vlist, addr); //在子成员列表中找到起始地址小于addr,最大下标的子成员
addr -= v.addr; //减去子成员的起始地址,考虑addr在此变量内部的偏移地址
ty = tv[v.type]; //找到子成员对应的类型
if (addr >= ty.size) { //如果(子成员)类型的占用的空间比addr小,那个位置就是空着的
ans = "ERR";
break;
}
ans += '.' + v.name; //记上答案
}
}
}
cout << ans << endl;
}
}
return 0;
}
评论:
请先登录,才能进行评论