CCF-201703-3-Markdown-(Java-100分)

这题图片很多就不贴图和复制题目了,直接进入正题
这题在第三题里面算是中等难度,但是我在练习时也花了很多时间,唉!这道题其实还是挺麻烦,很恶心的。

思路
一行行读取代码,遇到某行是空的,而且上一行是有代码的就表示此区块代码结束。我们要做的是在某个区块结束后输出某个区块的转换代码。

在读到区块首行的时候要判断是什么区块类型。是标题,列表还是段落?然后在区块代码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)
#

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值