试题编号: | 201703-3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
试题名称: | Markdown | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
时间限制: | 1.0s | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
内存限制: | 256.0MB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
问题描述: | 问题描述 Markdown 是一种很流行的轻量级标记语言(lightweight markup language),广泛用于撰写带格式的文档。例如以下这段文本就是用 Markdown 的语法写成的: 输入格式 输入由若干行组成,表示一个用本题规定的 Markdown 语法撰写的文档。 输出格式 输出由若干行组成,表示输入的 Markdown 文档转换成产生的 HTML 代码。 样例输入 # Hello 样例输出 <h1>Hello</h1> 评测用例规模与约定 本题的测试点满足以下条件:●本题每个测试点的输入数据所包含的行数都不超过100,每行字符的个数(包括行末换行符)都不超过100。 ●除了换行符之外,所有字符都是 ASCII 码 32 至 126 的可打印字符。 ●每行行首和行末都不会出现空格字符。 ●输入数据除了 Markdown 语法所需,内容中不会出现 `#`、`*`、`_`、`[`、`]`、`(`、`)`、`<`、`>`、`&` 这些字符。 ●所有测试点均符合题目所规定的 Markdown 语法,你的程序不需要考虑语法错误的情况。 每个测试点包含的语法规则如下表所示,其中“√”表示包含,“×”表示不包含。
提示 由于本题要将输入数据当做一个文本文件来处理,要逐行读取直到文件结束,C/C++、Java 语言的用户可以参考以下代码片段来读取输入内容。 |
问题链接:CCF201703-3 Markdown
问题分析:
这是一个文本处理题,将Markdown语言格式的文本转换为标记语言(标签式语言)文本。
一般而言,文本处理使用的技术有这么几种:一是使用C语言的字符串库函数;二是使用C++的string类的方法;三是使用正则表达式。应该说能够使用正则表达式来处理的话,是最佳的做法,但是需要一定的训练才能做到。
本题按照题意进行规则转换即可。
程序说明:
CCF官网支持头文件使用#include <bits/stdc++.h>,一句就解决问题了。
程序中,使用C++的string类的有关方法进行字符串处理。那些方法对于文本处理十分有效,应该了然于心。
题记:(略)
提交后得100分的C++语言程序如下:
/* CCF201703-3 Markdown */
#include <bits/stdc++.h>
using namespace std;
string line, text;
// 段落处理
void solve()
{
// 处理下划线:标签<em></em>
size_t leftp = text.find("_");
while(leftp != string::npos) {
text.replace(leftp, 1, "<em>");
size_t rightp = text.find("_", leftp);
text.replace(rightp, 1, "</em>");
leftp = text.find("_", rightp);
}
// 处理方括号
leftp = text.find("[");
while(leftp != string::npos) {
size_t rightp = text.find("]", leftp);
size_t leftp2 = text.find("(", rightp);
size_t rightp2 = text.find(")", leftp2);
string tmp = text.substr(leftp + 1, rightp - leftp - 1);
string tmp2 = text.substr(leftp2 + 1, rightp2 - leftp2 - 1);
text.replace(text.begin() + leftp, text.begin()+rightp2 + 1, "<a href=\"" + tmp2 + "\">" + tmp + "</a>");
leftp = text.find("[", rightp2);
}
if(text[0] == '#') {
// 处理#:标签<h></h>
int i = 0;
while(text[i] == '#') i++;
text = "<h" + string(1, '0' + i) + ">" + text.substr(i + 1);
text.insert(text.size() - 1, "</h" + string(1, '0' + i) + ">");
} else if(text[0] == '*') {
// 处理*:标签<ul><li></li>......</ul>
text.insert(0, "<ul>\n");
text.insert(text.size(), "</ul>\n");
size_t leftp = text.find("*");
while(leftp != string::npos) {
size_t rightp = text.find("\n", leftp);
text.insert(rightp, "</li>");
text.replace(leftp, 2, "<li>");
leftp = text.find("*", rightp);
}
} else {
// 处理段落:<p></p>
text = "<p>" + text.substr(0, text.size() - 1) + "</p>\n";
}
cout << text;
text = "";
}
int main()
{
bool flag = false;
getline(cin, line);
for(; ;) {
if(line.size() > 0)
text += line + "\n";
else if(line.size() == 0 && text.size() > 0)
solve();
if(flag) break;
if(!getline(cin, line)) {
flag = true;
line = "";
}
}
return 0;
}
/*
# Heading
## Sub-heading
Paragraphs are separated
by a blank line.
text attributes _italic_.
Bullet list:
* apples
* oranges
* pears
A [link](http://example.com).
*/