1231

☀️☃️☃️☃️☀️  •  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;
}


评论:

请先登录,才能进行评论