社区讨论

萌新刚学OI,不会结构体,求大佬救救,玄关

灌水区参与者 12已保存回复 25

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
25 条
当前快照
1 份
快照标识符
@m027wvns
此快照首次捕获于
2024/08/20 17:23
2 年前
此快照最后确认于
2025/11/05 02:10
4 个月前
查看原帖
CPP
#include<bits/stdc++.h>
#define int long long 
#define maxn 200010
#define endl '\n'
using namespace std;

string in1[maxn],in2[maxn];

pair<int,int> mp(int x,int y){return (pair<int,int>){x,y};}

struct Type{
	string id;
	vector<string> member_id;
	vector<Type*> member_type;
	int size,align;//占用内存大小,对齐要求
	void clear(){
		id.clear();
		member_id.clear();
		member_type.clear();
		size=align=0;
	} 
}type[maxn];
int type_cnt=0;//类型总数 
map<string,Type*> type_mp;

struct Element{
	int addr;//起始地址 
	Type type;
	string id;
	void clear(){
		addr=0;
		id.clear();
		type.clear();
	} 
}element[maxn]; 
int elem_cnt=0;
map<string,Element*> elem_mp;

int addr_cnt=0;
map<pair<int,int>,Element*> addr_mp;

void new_type(string id,int size,string *membertype,string *memberid){
	Type nt;
	nt.clear();
	nt.id=id;
	for(int i=1;i<=size;i++){
		nt.member_type.push_back(type_mp[membertype[i]]);
        nt.member_id.push_back(memberid[i]);
	}
    int addr_pos=0;
	for(auto it:nt.member_type){
		int size=it->size;
		int Align=it->align;
		nt.align=max(nt.align,Align);
		if(addr_pos%Align!=0){
			addr_pos=(addr_pos/Align+1)*Align;
		}
		addr_pos+=size;
	}
	if(addr_pos%nt.align!=0){
		addr_pos=(addr_pos/nt.align+1)*nt.align;
	}
	nt.size=addr_pos;
	type[++type_cnt]=nt;
	type_mp[id]=&type[type_cnt];
	return ;
}

void new_element(string id,string type_id){
	int Size=type_mp[type_id]->size;
	int Align=type_mp[type_id]->align;
	if(addr_cnt%Align!=0){
		addr_cnt=((addr_cnt/Align+1)*Align);
	}
	Element ne;
	ne.clear();
	ne.id=id;
	ne.type=*type_mp[type_id];
	ne.addr=addr_cnt;
	addr_cnt+=ne.type.size;
	//addr_mp[make_pair(addr_cnt,addr_cnt+Size-1)]=&element[elem_cnt];
	element[++elem_cnt]=ne;
	elem_mp[id]=&element[elem_cnt];
	addr_mp[mp(addr_cnt,addr_cnt+Size-1)]=&element[elem_cnt]; 
	addr_cnt+=Size;
	return ;
}

int visit_elelment(string id){
	queue<string> q;
	string tmp;
	tmp.clear();
	for(int i=0;i<id.size();i++){
		if(id[i]=='.'){
			q.push(tmp);
			tmp.clear();
		}
		else{
			tmp+=id[i];
		}
	}
	q.push(tmp);
	int pos=elem_mp[q.front()]->addr;
	Type temp_type=elem_mp[q.front()]->type;
	q.pop();
	while(!q.empty()){
		string name=q.front();
		q.pop();
		auto it1=temp_type.member_id.begin();
		auto it2=temp_type.member_type.begin();
		for(;it1!=temp_type.member_id.end();it1++,it2++){
			if(pos%(*it2)->align){
				pos=(pos/(*it2)->align+1)*(*it2)->align;
			}
			if(*it1==name){
				temp_type=**it2;
				break;
			}
			else{
				pos+=(*it2)->size;
			}
		}
	}
	return pos;
}

/*string visit_address(int address){
	if(address>=addr_cnt){
		return "ERR";
	}
	Element elem;
	for(auto it:addr_mp){
		if(address<it.first.first||address>it.first.second){
			continue;
		}
		elem=*(it.second);
		break;
	}
	int goal=address-elem.addr;
	int Lpos=0;
	int Rpos;
	Type temp_type=elem.type;
	string elem_id;
	elem_id.clear();
	elem_id+=elem.id;
	while(!temp_type.member_id.empty()){
		auto it1=temp_type.member_id.begin();
		auto it2=temp_type.member_type.begin();
		for(;it2!=temp_type.member_type.end();it1++,it2++){
			Rpos=Lpos+(*it2)->size;
			if(goal<Rpos&&goal>=Lpos){
				elem_id+='.'+*it1;
				temp_type=**it2;
				break;
			}
			else{
				if(it2+1==temp_type.member_type.end()){
					return "ERR";
				}
				int Align=(*(it2+1))->align;
				if(Rpos%Align){
					Rpos=(Rpos/Align+1)*Align;
				}
				if(goal<Rpos){
					return "ERR";
				}
				Lpos=Rpos;
			}
		}
	}
	if(elem_id==""){
		return "ERR";
	}
	return elem_id;
}*/

string visit_address(int address){
	if(address>=addr_cnt){
		return "ERR";
	}
	Element elem;
	for(auto it:addr_mp){
		if(address<it.first.first||address>it.first.second){
			continue;
		}
		elem=*(it.second);
		break;
	}
	int goal=address-elem.addr;
	int Lpos=0;
	int Rpos;
	Type temp_type=elem.type;
	string elem_id;
	elem_id.clear();
	elem_id+=elem.id;
	while(!temp_type.member_id.empty()){
		auto it1=temp_type.member_type.begin();
		auto it2=temp_type.member_id.begin();
		for(;it1!=temp_type.member_type.end();it1++,it2++){
			Rpos=Lpos+(*it1)->size;
			if(goal<Rpos&&goal>=Lpos){
				elem_id+='.'+*it2;
				temp_type=**it1;
				break;
			}
			else{
				if(it1+1==temp_type.member_type.end()){
					return "ERR";
				}
				int Align=(*(it1+1))->align;
				if(Rpos%Align){
					Rpos=(Rpos/Align+1)*Align;
				}
				if(goal<Rpos){
					return "ERR";
				}
				Lpos=Rpos;
			}
		}
	}
	if(elem_id==""){
		return "ERR";
	}
	return elem_id;
}

string Visit_Addr(int address){
    if(address>=addr_cnt)return "ERR";//判断地址是否在某个元素中
    Element ele;
    map<pair<int,int>,Element*>::iterator it=addr_mp.begin();
    for(;it!=addr_mp.end();it++){//寻找地址所处的元素
        if(address<(*it).first.first or address>(*it).first.second)continue;
        ele=*((*it).second);
        break;
    }
    int pos_goal=address-ele.addr,pos_s=0,pos_t;//目标地址、起始地址、终止地址
    Type type=ele.type;//当前元素类型
    string ele_name;//元素名称
    ele_name.clear();
    ele_name+=ele.id;//元素名称先加上最外层元素名称
    while(!type.member_id.empty()){//循环直到元素类型为基本类型(此时元素类型没有成员)
        vector<Type*>::iterator it1=type.member_type.begin();//遍历当前元素类型的成员类型
        vector<string>::iterator it2=type.member_id.begin();//遍历当前元素类型的成员名称
        for(;it1!=type.member_type.end();it1++,it2++){
            pos_t=pos_s+(*it1)->size;//更新终止地址
            if(pos_goal<pos_t and pos_goal>=pos_s){//如果目标地址在此成员中
                ele_name+='.'+*it2;//更新元素名称
                type=**it1;//更新元素类型
                //这两行代码需要注意:不可调换位置
                //因为 it2 是 type 的迭代器,type 更改后,it2 也会相应改变
                //因此需要在改变 type 之前调用 it2
                break;
            }
            else{//如果目标地址不在此成员中
                if(it1+1==type.member_type.end())return "ERR";//如果这个成员是最后一个成员了,说明目标地址为空洞
                int Align=(*(it1+1))->align;//该成员的对齐要求
                if(pos_t%Align)pos_t=(pos_t/Align+1)*Align;//如果终止地址不满足对齐规则
                if(pos_goal<pos_t)return "ERR";//如果目标地址在满足对齐规则后处于此成员内了,那么说明目标地址为空洞
                pos_s=pos_t;//更新起始位置
            }
        }
    }
    if(ele_name=="")return "ERR";//特判,若名称为空,则说明不存在元素包含这个地址
    return ele_name;
}

void init(){
	//cout<<"! 1"<<endl;
	type[1].id="byte";
	type[2].id="short";
	type[3].id="int";
	type[4].id="long";
	type[1].align=type[1].size=1;
	type[2].align=type[2].size=2;
	type[3].align=type[3].size=4;
	type[4].align=type[4].size=8;
	type_mp["byte"]=&type[1];
	type_mp["short"]=&type[2];
	type_mp["int"]=&type[3];
	type_mp["long"]=&type[4];
	type_cnt=4;
	//cout<<"! 2"<<endl;
	return ;
}

void worrk(){
	//cout<<"! 4"<<endl;
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		int op;
		cin>>op;
		if(op==1){
			int k;
			string str;
			cin>>str>>k;
			for(int j=1;j<=k;j++){
				cin>>in1[j]>>in2[j];
			}
			new_type(str,k,in1,in2);
			cout<<type[type_cnt].size<<" "<<type[type_cnt].align<<endl;
		}
		else if(op==2){
			string t,nt;
			cin>>t>>nt;
			new_element(nt,t);
			cout<<element[elem_cnt].addr<<endl;
		}
		else if(op==3){
			string s;
			cin>>s;
			cout<<visit_elelment(s)<<endl;
		}
		else{
			int num;
			cin>>num;
			for(int i=1;i<=addr_cnt;i++){
				cout<<addr_mp[i]<<" ";
			}
			cout<<'\n';
		}
	}
	return ;
} 

main(){
	std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
	init();	
	//cout<<"! 3"<<endl;
	worrk();
	return 0;
}

/*
5
1 a 2
short aa
int ab
1 b 2
a ba
long bb
2 b x
3 x.ba.ab
4 10
*/

回复

25 条回复,欢迎继续交流。

正在加载回复...