社区讨论
萌新刚学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 条回复,欢迎继续交流。
正在加载回复...