鄙人不才,此中鄙陋甚多,望海涵!!!
题目要求编写一个简易的Markdown语法工具,有比较复杂的语法规则和转换规则!(重点用红色标注)
语法规则:
区块:本题有三种区块!
区块一:段落,即连续的几行。
区块二:标题,以若干连续#
开头,最后一个#后跟有若干空格
,空格后才是标题的内容!
区块三:无序列表,每行由 *
开头,接着若干空格,然后才是列表项目的内容,无序列表只有一层(也就是说带*的行是一行或者连续的几行
)
行内:所谓行内就是指上面三种区块内(有许多人理解为行内只有段落,不包括标题和无序列表)
一:强调:形如_Text_
且不会出现嵌套,即每行中 _
的个数一定是偶数,且不会连续相邻(不相邻就不会嵌套)。注意 _Text_
的前后不一定是空格字符。
二:超级链接:形如[Text](Link)
。
注意:超级链接和强调可以相互嵌套,但每种格式不会超过一层。(也就是Text和link内也会出现强调,强调内也会出现超链接
)
转化规则:
段落:段落的转换规则是在段落的第一行行首插入 <p>
,在最后一行行末插入 </p>
。(注意是整个段落,不是段落的每行
)
标题:转换时,# Heading
转换为 <h1>Heading</h1>
,## Heading
转换为 <h2>Heading</h2>
,以此类推。标题等级最深为 6。
无序列表:转换时,在最开始插入一行 <ul>
,最后插入一行 </ul>
;对于每行,* Item
转换为 <li>Item</li>
。(注意是英文字母l
,不是数字1
).
强调:_Text_
转换为 <em>Text</em>
。
超链接:[Text](Link)
转换为 <a href="Link">Text</a>
。这里我们为更好的理解嵌套,再加一组样例:[_sdsd_](ssf_hjkhj_kjjk_odj_).
转化为<p><a href="ssf<em>hjkhj</em>kjjk<em>odj</em>"><em>sdsd</em></a>.</p>
(这里的text和link都带有强调)
接下来是最重要的一点,题目中说相邻两个区块之间用一个或多个空行分隔。输出时删除所有分隔区块的空行。
,言外之意就是我们可以用是否为空行去检测当前区块是否结束,完成转化的最后一步(例如段落结尾的</p>,无序列表结尾的</ul>
),但也要注意相邻区块可以用空行检测,如果区块在最后一行结束我们就不能用空行检测,只能特判!
明白了语法规则和转化顺序后我们最重要的是去想一种恰当的处理顺序,仔细想想,其实除了标题和无序列表的处理方式有些特殊,其他的行内规则都是一样的,这里就直接上代码吧!文本题不要嫌烦,多注意细节!
C++code
#include<iostream>
using namespace std;
string s[110],pa="<em>",pb="</em>";
int j,cnt=1,flag,mark,fp;//mark用来处理 _ ,flag用来处理无序列表开头的<ul>,fp是用来处理
//段落开头的<p>,cnt是数据的行数,j为全局变量,便于将主函数与转化函数相连!
void revert(string str)//行内转化函数
{
if(str[j]=='_')
{
if(mark==0) printf("<em>"),mark=1;
else printf("</em>"),mark=0;
}
else if(str[j]=='[')
{
string a,b;//a中是text的内容,b中是link的内容!
j++;
for(;;j++)
{
if(str[j]!=']')
{
if(str[j]=='_')
{
if(mark==0) a+=pa,mark=1;
else a+=pb,mark=0;
}
else a+=str[j];
}
else break;
}
j++;
for(;;j++)
{
if(str[j]!=')' && str[j]!='(')
{
if(str[j]=='_')
{
if(mark==0) b+=pa,mark=1;
else b+=pb,mark=0;
}
else b+=str[j];
}
else if(str[j]==')') break;
}
printf("<a href=\"");
cout<< b << '"' << '>' << a ;
printf("</a>");
}
else printf("%c",str[j]);
}
int main()
{
while(getline(cin,s[cnt])) cnt++;//读入数据
cnt--;//这是为了最后一次特判准备!
for(int i=1;i<cnt;i++)
{
if(s[i][0]=='#')//检测标题
{
int res=0;
for(j=0;;j++)
{
if(s[i][j]=='#') res++;//标记#的数量
else if(s[i][j]!=' ') break;//跳过空格
}
printf("<h%d>",res);
for(;j<s[i].size();j++) revert(s[i]);//行内转化
printf("</h%d>\n",res);
}
if(s[i][0]=='*')//检测无序列表
{
int res=1;
while(s[i][res]==' ') res++;//跳过空格
flag++;
if(flag==1) printf("<ul>\n");//处理<ul>
printf("<li>");
for(j=res;j<s[i].size();j++) revert(s[i]);//行内转化
printf("</li>\n");
}
if(s[i].size()==0 && s[i-1][0]=='*') printf("</ul>\n"),flag=0;
//处理无序列表的结束
if(s[i][0]!='#' && s[i][0]!='*' && s[i].size()!=0)//处理普通段落
{
if(fp==0) printf("<p>"),fp=1;
for(j=0;j<s[i].size();j++) revert(s[i]);//处理行内
//接下来就是处理普通段落的结尾,如果当前没有结束就输出换行,否则为</p>.
if(s[i+1][0]!='#' && s[i+1][0]!='*' && s[i+1].size()!=0) printf("\n");
else
{
if(s[i+1].size()==0 || s[i+1][0]=='#' || s[i+1][0]=='*')
{
printf("</p>\n");
fp=0;
}
}
}
}
//与前面转化顺序完全相同,特判结尾行!
if(s[cnt][0]=='*')
{
int res=1;
while(s[cnt][res]==' ') res++;
flag++;
if(flag==1) printf("<ul>\n");
printf("<li>");
for(j=res;j<s[cnt].size();j++) revert(s[cnt]);
printf("</li>\n");
printf("</ul>\n");
}
if(s[cnt][0]!='#' && s[cnt][0]!='*' && s[cnt].size()!=0)
{
if(fp==0) printf("<p>"),fp=1;
for(j=0;j<s[cnt].size();j++) revert(s[cnt]);
printf("</p>\n");
}
if(s[cnt][0]=='#')
{
int res=0;
for(j=0;;j++)
{
if(s[cnt][j]=='#') res++;
else if(s[cnt][j]!=' ') break;
}
printf("<h%d>",res);
for(;j<s[cnt].size();j++) revert(s[cnt]);
printf("</h%d>\n",res);
}
return 0;
}
最后附带一组检测样例与答案,便于调试
输入
# heading
## sub-heading
pdefe dfe _dfefe_
busdfe sdfe fe
efewfew
buiuhkj dewf:
* sfwef
* wefe
* fewfe
A [link](svefwefefef)[sdsd](ssf_hjkhj_kjjk_odj_).
### _ub_-heading[_sdsd_](ssf_hjkhj_kjjk_odj_).
输出
<h1>heading</h1>
<h2>sub-heading</h2>
<p>pdefe dfe <em>dfefe</em>
busdfe sdfe fe</p>
<p>efewfew</p>
<p>buiuhkj dewf:</p>
<ul>
<li>sfwef</li>
<li>wefe</li>
<li>fewfe</li>
</ul>
<p>A <a href="svefwefefef">link</a><a href="ssf<em>hjkhj</em>kjjk<em>odj</em>">sdsd</a>.</p>
<h3><em>ub</em>-heading<a href="ssf<em>hjkhj</em>kjjk<em>odj</em>"><em>sdsd</em></a>.</h3>
客串一下hh
hhh
干完提高课后就刷ccf,以后一起交流
嗯,好的!谢大佬抬爱!
ccf第三题最近几年的好恶心感觉
大模拟太烦了
是啊,没办法。。。可以先看4,5,这个三题是我们的实验报告,我就顺带写了一下!
加油