大帅傅

li yue  •  1个月前


include

include

include

include

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 tv; //类型表 unordered_map<string, var> slist; //根据变量名快速查到变量 vector 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& 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;

}

© 2019 - 2026王码编程  滇ICP备19007937号-1如果您有任何问题,请联系


评论:

请先登录,才能进行评论