题目大意
给出一段 BBCode 格式的待转换字符串,要求将其转换为 Markdown 格式。
文本形式 | BBCode 表示 | Markdown 表示 |
---|---|---|
一级标题 | [h1]标题[/h1] | # 标题 # |
二级标题 | [h2]标题[/h2] | ## 标题 ## |
斜体 | [i]文字[/i] | *文字* |
粗体 | [b]文字[/b] | __文字__ |
链接 | [url=地址]文字[/url] | [文字](地址) |
图片 | [img=地址]说明[/img] | ![说明](地址) |
代码(\n 表示换行符) | [quote]代码1\n代码2 [/quote] | > 代码1\n> 代码2 |
解题思路
对于输入中的非标签内容直接输出即可;对于一二级标题、斜体、粗体的标签,我们可以直接将其替换 Markdown 格式的;而对于链接和图片,可以将链接保存下来,等到结束标签时在将文字描述一起按格式输出;代码段可以通过逐行输入,并忽略除 [/quote]
以外的标签。
几个需要注意的点:
标签中可能有嵌套,可以用栈来维护;链接和图片也有可能嵌套,所以需要另一个栈来维护链接。也可以使用 stack
配合 pair
来同时维护标签和链接。
遇到 Unclosed Mark
(可以忽略题目中让我们分两段输出该错误的信息)和 Match Error
的错误时,你的程序应当只输出两个错误之一。可以通过判断栈顶和当前结束标签来判断是否出现 Match Error
;通过在格式转换部分全部运行结束之后判断栈是否为空来判断是否出现 Unclosed Mark
。注意可能出现栈为空时读入一个结束标签的情况,这种情况属于 Match Error
。
按照原输入的换行进项输出,除了 [quote]
标签中代码的的首尾空行,这些空行不应在你的输出中出现。对于 [quote]
标签不在单独一行的情况,你的程序应该让代码段独立成行。注意,在 [/quote]
标签后应该加上一个换行。如:
输入:
test[quote]
123
vytu[/quote]456
输出
test
> 123
>
>
> vytu
456
代码
// Problem: Luogu P2395
// Auther: gtafics
#include <bits/stdc++.h>
using namespace std;
string output,nowformat,url,waiting,line,word;
stack<pair<int,string>> format_;
bool getting_format(0),unchange(0),meet(1);
int frontgetid(string _format)
{
url="";
if(_format=="[h1]")
{
return 1;
}
if(_format=="[h2]")
{
return 2;
}
if(_format=="[i]")
{
return 3;
}
if(_format=="[b]")
{
return 4;
}
if(_format[1]=='u')
{
for(int i=5;i<(int)_format.size()-1;++i)
{
url+=_format[i];
}
return 5;
}
if(_format[1]=='i')
{
for(int i=5;i<(int)_format.size()-1;++i)
{
url+=_format[i];
}
return 6;
}
if(_format=="[quote]")
{
return 7;
}
return -1;
}
int backgetid(string _format)
{
if(_format=="[/h1]")
{
return 1;
}
if(_format=="[/h2]")
{
return 2;
}
if(_format=="[/i]")
{
return 3;
}
if(_format=="[/b]")
{
return 4;
}
if(_format[2]=='u')
{
return 5;
}
if(_format[2]=='i')
{
return 6;
}
if(_format=="[/quote]")
{
return 7;
}
return -1;
}
void front_format(int formatid)
{
if(formatid==1)
{
nowformat+="# ";
return;
}
if(formatid==2)
{
nowformat+="## ";
return;
}
if(formatid==3)
{
nowformat+="*";
return;
}
if(formatid==4)
{
nowformat+="__";
return;
}
if(formatid==5)
{
nowformat+="[";
return;
}
if(formatid==6)
{
nowformat+="![";
return;
}
return;
}
void back_format(int formatid)
{
if(formatid==1)
{
nowformat+=" #";
return;
}
if(formatid==2)
{
nowformat+=" ##";
return;
}
if(formatid==3)
{
nowformat+="*";
return;
}
if(formatid==4)
{
nowformat+="__";
return;
}
if(formatid==5||formatid==6)
{
nowformat+="]("+format_.top().second+")";
return;
}
return;
}
int main()
{
while(word=nowformat="",getline(cin,line))
{
for(int i(0);i<(int)line.size();++i)
{
if(unchange)
{
if(getting_format&&line[i]==']')
{
word+=']';
if(word[1]=='/')
{
int formatid=backgetid(word);
if(formatid==7)
{
output+=nowformat+'\n',nowformat=word=waiting="";
format_.pop();
unchange=getting_format=0,meet=1;
continue;
}
}
nowformat+=waiting+word,getting_format=0,waiting=word="";
continue;
}
if(line[i]=='[')
{
nowformat+=word,getting_format=1,word="";
}
word+=line[i],meet=1;
if(word[0]!='[')
{
output+=waiting,waiting="";
}
continue;
}
if(getting_format&&line[i]==']')
{
word+=']';
if(word[1]=='/')
{
int formatid=backgetid(word);
if(!format_.empty()&&format_.top().first==formatid)
{
back_format(formatid);
output+=nowformat,nowformat="";
format_.pop();
}
else
{
printf("Match Error");
return 0;
}
}
else
{
int formatid=frontgetid(word);
front_format(formatid);
format_.push({formatid,url});
if(formatid==7)
{
unchange=1,meet=0;
if(i!=6)
{
nowformat+='\n';
}
nowformat+="> ";
}
}
getting_format=0,word="";
continue;
}
if(line[i]=='[')
{
nowformat+=word,getting_format=1,word="";
}
word+=line[i];
}
output+=nowformat+word;
if(meet&&unchange)
{
waiting+="\n> ";
}
else
{
output+=(meet?"\n":"");
}
}
if(!format_.empty())
{
printf("Unclosed Mark");
return 0;
}
cout<<output;
return 0;
}