题解 P2395 【BBCode转换Markdown】

· · 题解

我看这题一直没有题解,那我来写一个吧...

头一次写题解,可能不是很擅长写的十分清楚,还请谅解...

总的来说,这道题是纯粹的字符串处理的大模拟,而且不适合离线处理(因为所有的代码块随时处理完之后会带来一系列的变化,这也是我第一版提交又WA又TLE,只有60分的原因。)

所以使用getchar()边读入边处理,直到出现了EOF为止。

首先关于是否嵌套有误,很容易可以拿栈来进行判断,如果在整体处理代码块的时候,读到了文件的末尾,或者出现了需要出栈但是栈空了的状态,则非法

然后剩下的就直接根据题目要求进行处理即可,不需要递归什么的

但是这个代码在读入代码块这里忘记判断如果读到结束了应该怎么进行判断,这里可以改进一下

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<stack>
#include<vector>
#define endline '\n'
#define debugQuote 0
#define debugGetchar 0
using namespace std;
string output;
string tag;
stack<string>parseStack;
stack<string>lastURL;
string quoteBuf;
bool isclose;
char c;
char lastC;
string processTag(string tag) {
    if (tag == "h1")return "#";
    if (tag == "h2")return "##";
    if (tag == "i")return "*";
    if (tag == "b")return "__";
    if (tag == "url")return "[";
    if (tag == "img")return "![";
    return "";
}
bool quoteBufNotOver() {
    string last = quoteBuf.substr(quoteBuf.size() - 8, 8);
    return last != "[/quote]";
}
string handleQuoteSpace(string str) {
    int pos = str.find_first_not_of(" \n\r\t");
    if (pos == str.npos)return str;
    int pos2 = str.find_last_not_of(" \n\r\t");
    if (pos2 != str.npos)return str.substr(pos, pos2 - pos + 1);
    else return str.substr(pos);
}
//重写:直接跳过对这中间指令的判断,这也是在线处理的好处
void addQuote() {
    if (isclose && parseStack.empty()) { puts("Match Error"); exit(0); }
    if (lastC != endline) output += endline;//quote默认上一行非空就要重启一行
    quoteBuf = "";
    while (quoteBuf.length() < 8 || quoteBufNotOver()) {
        char t = getchar();
        if (t == EOF) { printf("Unclo"), puts("sed Mark"); exit(0); }
        quoteBuf.push_back(t);
    }
    quoteBuf = "> " + handleQuoteSpace(quoteBuf.substr(0, quoteBuf.length() - 8));
    for(int pos = 0; pos < quoteBuf.size(); ++pos)
        if(quoteBuf[pos] == '\n')quoteBuf.insert(pos + 1, "> ");
    output += quoteBuf + endline;
}
void addURLorIMG() {
    //img和url就差一个叹号
    if (isclose) {
        if (parseStack.empty() || tag != parseStack.top()) { puts("Match Error"); exit(0); }
        parseStack.pop();
        output += "](" + lastURL.top() + ")";
        lastURL.pop();
    }
    else {
        lastURL.push(tag.substr(4));
        parseStack.push(tag.substr(0, 3));
        output += processTag(tag.substr(0, 3));
    }
}
void addNormal() {
    if (isclose) {
        if (parseStack.empty() || tag != parseStack.top()) { puts("Match Error"); exit(0); }
        parseStack.pop();
        if (tag[0] == 'h')output += " ";
        output += processTag(tag);
    }
    else {
        parseStack.push(tag);
        output += processTag(tag);
        if (tag[0] == 'h')output += " ";
    }
}
int main() {
    //FILE* in;
    //in = freopen("P2395in.txt", "r", stdin);
    lastC = endline;
    while ((c = getchar()) != EOF) {
        if (c == '[') {
            tag = "";
            int i = 0;
            isclose = false;
            char t;
            while ((t = getchar()) != ']') {
                if (t == '/' && i == 0)isclose = true;
                else tag.push_back(t), ++i;
            }
            if (tag == "quote")addQuote();
            else if (tag[0] == 'u' || (tag[0] == 'i' && tag.length() > 1))addURLorIMG();
            else addNormal();
        }
        else output += c;//这样不仅解决了普通tag的问题,还解决了没有在任何tag中的文字的极端情况
        lastC = c;
    }
    if (!parseStack.empty()) { printf("Unclo"), puts("sed Mark"); exit(0); }
    else puts(output.c_str());
}