CCF201703-3Markdown(字符串处理)

问题描述

试题编号:201703-3
试题名称:Markdown
时间限制:1.0s
内存限制:256.0MB
问题描述:

问题描述

  Markdown 是一种很流行的轻量级标记语言(lightweight markup language),广泛用于撰写带格式的文档。例如以下这段文本就是用 Markdown 的语法写成的:



  这些用 Markdown 写成的文本,尽管本身是纯文本格式,然而读者可以很容易地看出它的文档结构。同时,还有很多工具可以自动把 Markdown 文本转换成 HTML 甚至 Word、PDF 等格式,取得更好的排版效果。例如上面这段文本通过转化得到的 HTML 代码如下所示:



  本题要求由你来编写一个 Markdown 的转换工具,完成 Markdown 文本到 HTML 代码的转换工作。简化起见,本题定义的 Markdown 语法规则和转换规则描述如下:
  ●区块:区块是文档的顶级结构。本题的 Markdown 语法有 3 种区块格式。在输入中,相邻两个区块之间用一个或多个空行分隔。输出时删除所有分隔区块的空行。
  ○段落:一般情况下,连续多行输入构成一个段落。段落的转换规则是在段落的第一行行首插入 `<p>`,在最后一行行末插入 `</p>`。
  ○标题:每个标题区块只有一行,由若干个 `#` 开头,接着一个或多个空格,然后是标题内容,直到行末。`#` 的个数决定了标题的等级。转换时,`# Heading` 转换为 `<h1>Heading</h1>`,`## Heading` 转换为 `<h2>Heading</h2>`,以此类推。标题等级最深为 6。
  ○无序列表:无序列表由若干行组成,每行由 `*` 开头,接着一个或多个空格,然后是列表项目的文字,直到行末。转换时,在最开始插入一行 `<ul>`,最后插入一行 `</ul>`;对于每行,`* Item` 转换为 `<li>Item</li>`。本题中的无序列表只有一层,不会出现缩进的情况。
  ●行内:对于区块中的内容,有以下两种行内结构。
  ○强调:`_Text_` 转换为 `<em>Text</em>`。强调不会出现嵌套,每行中 `_` 的个数一定是偶数,且不会连续相邻。注意 `_Text_` 的前后不一定是空格字符。
  ○超级链接:`[Text](Link)` 转换为 `<a href="Link">Text</a>`。超级链接和强调可以相互嵌套,但每种格式不会超过一层。

输入格式

  输入由若干行组成,表示一个用本题规定的 Markdown 语法撰写的文档。

输出格式

  输出由若干行组成,表示输入的 Markdown 文档转换成产生的 HTML 代码。

样例输入

# Hello

Hello, world!

样例输出

<h1>Hello</h1>
<p>Hello, world!</p>

评测用例规模与约定

  本题的测试点满足以下条件:
  ●本题每个测试点的输入数据所包含的行数都不超过100,每行字符的个数(包括行末换行符)都不超过100。
  ●除了换行符之外,所有字符都是 ASCII 码 32 至 126 的可打印字符。
  ●每行行首和行末都不会出现空格字符。
  ●输入数据除了 Markdown 语法所需,内容中不会出现 `#`、`*`、`_`、`[`、`]`、`(`、`)`、`<`、`>`、`&` 这些字符。
  ●所有测试点均符合题目所规定的 Markdown 语法,你的程序不需要考虑语法错误的情况。
  每个测试点包含的语法规则如下表所示,其中“√”表示包含,“×”表示不包含。
测试点编号段落标题无序列表强调超级链接
1××××
2×××
3×××
4×××
5×××
6××
7××
8××
9××
10

提示

  由于本题要将输入数据当做一个文本文件来处理,要逐行读取直到文件结束,C/C++、Java 语言的用户可以参考以下代码片段来读取输入内容。


 

        本题是非常复杂的字符串处理,如果思路不对,会极大地增加编程难度。本题要处理两个主要难点是:

        1、区块的结束标志字符串的输出。一个解决办法是将一个区块的内容全接收完再输出。另一个解决办法是在当前区块上不管结束字符串,当输入另一个区块时,再处理上一区块结束字符串。我使用的是第二种解决办法。

        2、强调和链接的嵌套的处理。解决方法就是用递归,因为最多只有一层循环,所以只要写好强调和链接的判断处理,再递归调用一次即可。代码如下,详见注释:

#include<iostream>
#include<string>
bool list=false;
bool para=false;
using namespace std;
//处理上一区块遗留的符号 
void solve()
{
	//列表的结束标志 
	if(list)
	{
		cout<<"</ul>"<<endl;
		list=false;
	}
	//段落的结束标志
	if(para)
	{
		cout<<"</p>"<<endl;
		para=false;
	}
}
//检查是否有强调或者链接
string check(string a,int start,int end)
{
	string text;
	string link;
	string res="";
	int s1,s2;
	int i=start;
	//遍历字符串的每个字符 
	while(i<end)
	{
		switch(a[i])
		{
			//如果遇到了强调 
			case '_':{
				//i++跳到_后的那个字符
				i++;
				//s1表示强调的内容的起始位置 
				s1=i;
				//找到强调的内容的终止位置 
				for(;i<end && a[i]!='_';i++);
				s2=i;
				//跳到强调的第二个_的后一个字符上 
				i++;
				//检查强调的内容是否有嵌套
				res+="<em>"+check(a,s1,s2)+"</em>";
				break;
			}
			//如果遇到了链接 
			case '[':{
				//跳到[的下一个字符 
				i++;
				//s1表示text的内容的起始位置
				s1=i;
				//找到text的内容的终止位置 
				for(;i<end && a[i]!=']';i++);
				s2=i;
				//i+=2,越过 ] 和 ( ,跳到link的内容上
				i+=2;
				//检查text中是否有嵌套 
				text=check(a,s1,s2);
				//s1表示link的起始位置 
				s1=i;
				for(;i<end&& a[i]!=')';i++);
				//s2表示link的终止位置 
				s2=i;
				//跳到链接的后一个字符上 
				i++;
				link=a.substr(s1,s2-s1);
				res+="<a href=\""+link+"\">"+text+"</a>";
				break;
			}
			//如果遇到的是普通字符则不做处理 
			default:{
				res+=a[i];
				i++;
				break;
			}
		}
	}
	return res;
}
int main()
{
	string line;
	while(getline(cin,line))
	{
		int len=line.length();
		//输入遇到了换行,则证明开始了另一个区块,则要输出上一区块的结束符
		if(line=="")
		{
			solve();
			continue;
		}
		//输入的是标题
		if(line[0]=='#')
		{
			int j,k,pos;
			//j用来计算#的个数
			for(j=0;line[j]=='#';j++);
			//k用来找到标题内容的起始位置
			for(k=j;line[k]==' ';k++);
			//检查是否有强调或链接 
			string res=check(line,k,len);
			printf("<h%d>",j);
			cout<<res;
			printf("</h%d>\n",j);
		}
		//列表
		else if(line[0]=='*')
		{
			//列表的开始符号 
			if(!list)
			{
				cout<<"<ul>"<<endl;
				list=true;
			}
			//k用来找到列表内容的起始位置 
			int k;
			for(k=1;k<len && line[k]==' ';k++);
			cout<<"<li>"<<check(line,k,len)<<"</li>"<<endl;
		}
		//段落 
		else
		{
			//输出上一行的换行符 
			if(para)
				cout<<endl;
			//输出行首标志
			if(!para)
			{
				cout<<"<p>";
				para=true;
			}
			int k;
			for(k=0;k<len && line[k]==' ';k++);
			cout<<check(line,k,len);
		}
	}
	//输入结束后,检查一下是否遗漏了结束符 
	solve();
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是第一段代码的解答: ccf201703-2是一个关于学生移位操作的问题。代码中使用了结构体来存储学生的编号和他在队伍中的位置,并通过重载运算符来对学生元素按照位置进行排序。首先,输入学生的数量n,并初始化一个vector来存储学生的信息。然后,根据学生的数量循环输入每个学生的编号和初始位置,并将其添加到vector中。接下来,输入移位操作的次数m,并循环输入每个移位操作的目标学生编号和移动的位置。根据目标学生编号,找到对应的学生在vector中的位置,并将其位置更新为目标位置。如果目标位置大于0,则将其前面的学生位置都减1;如果目标位置小于0,则将其后面的学生位置都加1。最后,对vector进行排序,并输出排序后的学生编号。 请注意,这段代码中使用了C++的一些语法和库函数,需要在编译时包含相关的头文件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [CCF:201703-2 学生排队](https://blog.csdn.net/weixin_42729072/article/details/105435070)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [第十次ccf 学生排队](https://blog.csdn.net/xiaoli_nu/article/details/65468043)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CCF-CSP 201703-2学生排队 一维数组满分题解](https://blog.csdn.net/m0_53641110/article/details/121446439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值