这题图片很多就不贴图和复制题目了,直接进入正题
这题在第三题里面算是中等难度,但是我在练习时也花了很多时间,唉!这道题其实还是挺麻烦,很恶心的。
思路
一行行读取代码,遇到某行是空的,而且上一行是有代码的就表示此区块代码结束。我们要做的是在某个区块结束后输出某个区块的转换代码。
在读到区块首行的时候要判断是什么区块类型。是标题,列表还是段落?然后在区块代码blockCode中加入对应的头标签。结束的时候在区块代码blockCode里加对应的尾标签。
在读行的时候处理所有的链接和强调,处理完加入到区块代码blockCode中。
import java.util.Scanner;
public class Markdown {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String blockCode = "";
String preLine = "";
while (input.hasNextLine()) {
String line = input.nextLine();
//给此区间加头标签,当且仅当此行是区间首行且是非空行
if (blockCode.length() == 0 && line.length() > 0) {
if (line.charAt(0) == '#') {
int hn = 0;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == '#')
hn++;
else
break;
}
line = line.replaceFirst("#* *", "<h" + hn + ">");
}
else if (line.charAt(0) == '*')
blockCode += "<ul>\n";
else
blockCode += "<p>";
}
//判断该行是否为列表
if (line.contains("*"))
line = "<li>" + line.replaceFirst("\\* *", "") + "</li>";
//处理每行里面的行内标签
line = transToEm(line);
line = transToLink(line);
//识别到区间分割,给此区间加尾标签,然后输出
//当此行为空且前面行有内容,说明区间在此行开始分隔
if (preLine.length() > 0 && line.length() == 0) {
blockCode = addLast(blockCode);
System.out.println(blockCode);
blockCode = "";
}
//把非空行加入区间代码块中
if (line.length() > 0)
blockCode += line + "\n";
preLine = line;
}
//最后一行因为没被识别到,要另外加尾标签然后输出
blockCode = addLast(blockCode);
System.out.println(blockCode);
}
static String addLast(String blockCode) {
//去掉代码块最后的换行符
blockCode = blockCode.substring(0, blockCode.length()-1);
if (blockCode.contains("<h")) {
int hn = blockCode.charAt(2) - '0';
blockCode += "</h" + hn + ">";
} else if (blockCode.contains("<ul>"))
blockCode += "\n</ul>";
else if (blockCode.contains("<p>"))
blockCode += "</p>";
return blockCode;
}
static String transToEm(String line) {
while (line.contains("_")){
line = line.replaceFirst("_", "<em>");
line = line.replaceFirst("_", "</em>");
}
return line;
}
static String transToLink(String line) {
while (line.contains("[")) {
String text = "";
String link = "";
int tIndexf = line.indexOf("[");
int tIndexl = line.indexOf("]");
int lIndexf = line.indexOf("(");
int lIndexl = line.indexOf(")");
text = line.substring(tIndexf + 1, tIndexl);
link = line.substring(lIndexf + 1, lIndexl);
line = line.replace(line.substring(tIndexf, lIndexl + 1),
"<a href=\"" + link + "\">" + text + "</a>");
}
return line;
}
}
新思路,先把代码读取成段落块,之后处理每个段落块,一行且开头是“#”的输出对应等级的标题标签和内容;开头是“*”的就是无序列表;剩余的就是段落。
行内标签用了正则表达式来替换。比之前的代码简洁了许多。注意一行会有多个行内标签,要区分开每个标签。
python代码:
import re
# em和a标签的正则表达式对象
em_obj = re.compile(r'_[^_]*_')
a_obj = re.compile(r'\[[^\[\]\(\)]*\]\([^\[\]\(\)]*\)')
# 替换em标签
def em_repl(match):
return '<em>{}</em>'.format(match.group()[1:-1].strip())
# 替换a标签
def a_repl(match):
s = match.group()
idx1, idx2 = s.index(']'), s.index('(')
cont, link = s[1:idx1], s[idx2 + 1:-1]
return '<a href="{}">{}</a>'.format(link, cont)
codes = [] # 所有区块
part = [] # 一个区块
# 读取数据
try:
while True:
ip = input()
if ip:
part.append(ip)
else:
codes.append(part)
part = []
except EOFError:
pass
if part:
codes.append(part)
# 确定行数的测试代码
# for i in range(19):
# ip = input()
# if ip:
# part.append(ip)
# elif part:
# codes.append(part)
# part = []
# if part:
# codes.append(part)
# 读取每个区块
for code in codes:
# 标题
if len(code) == 1 and code[0][0] == '#':
h = code[0]
i = h.count('#')
content = h[i + 1:].strip()
content = em_obj.sub(em_repl, content)
content = a_obj.sub(a_repl, content)
print('<h{}>{}</h{}>'.format(i, content, i))
# 无序列表
elif code[0][0] == '*':
print('<ul>')
for e in code:
content = e[2:].strip()
content = em_obj.sub(em_repl, content)
content = a_obj.sub(a_repl, content)
print('<li>{}</li>'.format(content))
print('</ul>')
# 段落
else:
print('<p>', end='')
for j, e in enumerate(code):
content = e.strip()
content = em_obj.sub(em_repl, content)
content = a_obj.sub(a_repl, content)
print(content, end='')
if j < len(code) - 1:
print()
print('</p>')
# ### Hello
#
#
# Hello, world!
#
# _ Hello, world! _
#
#
# a [hello](https://www.zhihu.com) .
# a _[hello](https://www.zhihu.com)_ .
# a [_hello_](https://www.zhihu.com) .
#
#
# * 132
# * ewv
# * 888ev
#
# _ 1181 _ _ erverver _ _ rerrrg _
# a [_hello_](https://www.zhihu.com) . --- [_hello_](https://www.zhihu.com)
#