CCP-CSP认证考试 201703-3 Markdown c/c++题解

题目描述

题解:

这道题我做了挺长时间了(看起来挺简单的,但是做起来还是有点难度),结果还只有70分
我只说下我的过程:
1、只考虑区块(标题、无序列表、段落): 4个测点,正好拿了40分
2、考虑区块内的强调:多了两个测点,60分
3、考虑区块内的超链接:只多过了一个测点,应该是有错误,70分(最后的分数,懒得调试了)
注意点:

  1. 输出时删除所有分隔区块的空行,也就是没有空行
  2. 强调 和 超链接是行内,也就是是包括在区块中的(标题、无序列表、段落)
  3. 解题策略:拿到这种题目不要想着拿满分的,以这种思路去写代码,会完全的考虑大多数情况,但是实际上这样会很麻烦,还不如从最小的点开始,一步步的调试优化。

代码(70分)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <bitset>
#include <iterator>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll  INF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double E = exp(1.0);
const int MOD = 1e9+7;
const int MAX = 1e5+5;
vector <string> markdown;
//vector <string> html;

// 将markdown的强调(其实就是斜体)形式转换为html形式:__item__ => <em>item</em>
bool judgeEmphasize(string mkdown)
{
    // 判断有无强调(下划线)
    int len = mkdown.length();
    for(int i = 0; i < len; i++)
    {
        if(mkdown[i] == '_')
            return true;
    }
    return false;
}
string emphasize(string mkdown)
{
    int flag = 0;// 0 -> <em>           1 -> </em>
    int len = mkdown.length();
    int i = 0;
    while(1)
    {
        /*
        如果遇到'_' 且 flag = 0: 将'-'替换成"<em>"、flag = 1
        如果遇到'_' 且 flag = 1: 将'-'替换成"</em>"、flag = 0
        */
        if(mkdown[i] == '_')
        {
            if(flag == 0)
            {
                mkdown.replace(i,1,"<em>",4);
                flag = 1;
                i += 4;
            }
            else
            {
                mkdown.replace(i,1,"</em>",5);
                flag = 0;
                i += 5;
            }
        }
        else
        {
            i++;
        }
        if(i == mkdown.length())
            break;
    }
    return mkdown;
}

// 将markdown的超链接形式转换为html形式:[item](www.baidu.com) => <a herf="www.baidu.com">item</a>
string hyperlink(string mkdown)
{
    int num = 0;// 计算'[' or ']' or '(' or ')'的数量,如果为偶数个即有超链接
    int len = mkdown.length();
    for(int i = 0; i < len; i++)
    {
        if(mkdown[i] == '[' || mkdown[i] == ']' || mkdown[i] == '(' || mkdown[i] == ')')
        {
            num++;
        }
    }
    if(num % 2 != 0 || num == 0)
    {
        // 如果没有超链接,直接返回
        return mkdown;
    }
    else
    {
        int index1,index2,index3,index4;
        for(int i = 0; i < len; i++)
        {
            if(mkdown[i] == '[') index1 = i;
            if(mkdown[i] == ']') index2 = i;
            if(mkdown[i] == '(') index3 = i;
            if(mkdown[i] == ')') index4 = i;
        }
        string str1 = mkdown.substr(index1+1,index2-index1-1);
        string str2 = mkdown.substr(index3+1,index4-index3-1);
        //cout << str1 << " " << str2 << endl;
        string link =  "<a href=\"";
        link += str2 + '\"' + ">" + str1 + "</a>";
        //cout << link << endl;
        mkdown.replace(index1,index4-index1+1,(char *)link.c_str(),link.length());
        return mkdown;
    }
}

// 将markdown的段落形式转换为html形式:正常的分段 => <p></p>
void paragraph(int startRow,int endRow,int num)
{
    /*
        段落可能会有连续的几行,每一行放到一个string里面,
        1. 如果只有一行 num = 1:
        markdown[startCol]的前面要加个<p>,后面加个</p>

        2. 如果有多行 num >= 2:
        markdown[startCol]的前面要加个<p>,
        markdown[endCol]的后面要加个</p>
    */
    if(num == 1)
    {
        markdown[startRow] = "<p>" + markdown[startRow] + "</p>";
    }
    else
    {
        markdown[startRow] = "<p>" + markdown[startRow];
        markdown[endRow] = markdown[endRow] + "</p>";
    }
}

// 将markdown的标题形式转换为html形式:# => <h1></h1>
string itos(int i)
{
    vector <int> tmp;
    while(i)
    {
        tmp.push_back(i%10);
        i /= 10;
    }
    string str = "";
    int len = tmp.size();
    for(int i = len - 1; i >= 0; i--)
    {
        str += ('0' + tmp[i]);
    }
    return str;
}
string title(string mkdown)
{
    int index = 0;// 判断有几个'#'
    while(mkdown[index] == '#') index++;
    string content = mkdown.substr(index+1);
    // 标题属于区块,区块就可能有强调或者超链接
    content = hyperlink(content);
    content = emphasize(content);
    string res = "<h" + itos(index) + ">" + content + "</h" + itos(index) + ">";
    return res;
}

// 将markdown的无序列表形式转换为html形式:* item => <ul> <li>item</li> </ul>
vector <string> unorderList(int startRow,int endRow,int num)
{
    // 对于无序列表的处理:
    vector <string> res;
    res.push_back("<ul>");
    for(int i = startRow; i <= endRow; i++)
    {
        int index = 0;
        while(!isalnum(markdown[i][index]))
            index++;
        string tmp = markdown[i].substr(index); // 无序列表项属于区块,区块就可能有强调或者超链接
        tmp = hyperlink(tmp);
        tmp = emphasize(tmp);
        res.push_back("<li>" + tmp + "</li>");
    }
    res.push_back("</ul>");
    return res;
}

/*  Markdown 文本到 HTML 代码的转换 */
int main()
{
    /*
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    */

    string str;
    while(getline(cin,str))
    {
        markdown.push_back(str);
    }
    int rowNums = markdown.size();
    /*
    for(int i = 0; i < rowNums; i++)
    {
        cout << markdown[i] << " " << markdown[i].size() << endl;
    }
    */


    int i = 0;
    while(i < rowNums)
    {
        //cout << "i: " << i << " markdown[i][0]:" << markdown[i][0] << endl;
        if(markdown[i][0] == '#')// 只考虑有标题
        {
            // cout << "标题的情况" << endl;
            //html[i].push_back(title(markdown[i]);
            cout << title(markdown[i]) << endl;
            i++;
        }
        else if(markdown[i][0] == '*')// 如果遇到了列表,要看看下面有几个"*"
        {
            // cout << "列表的情况" << endl;
            int num = 0;// 记录下"*"的个数
            int j = i;
            while(j < rowNums && markdown[j][0] == '*')
            {
                j++; num++;
            }
            // 这里可能要返回多行,所以用vector <string>来保存
            vector <string> res(num+2);
            res = unorderList(i,j-1,num);// 从markdown的i~j-1行,总共num个*,也就是num行数据
            int len = res.size();
            for(int k = 0; k < len; k++)
            {
                cout << res[k] << endl;
            }
            i = j;
        }
        else if(markdown[i].size() != 0)// markdown[i][0],也就是第一个字符,如果不是'#',也不是'*',那一定是段落的形式,前面后面加个<p> </p>
        {
            // cout << "段落的情况" << endl;
            // 段落也要考虑有几行
            int num = 0;
            int j = i;
            while(j < rowNums && markdown[j].size() != 0)
            {
                j++; num++;
            }
            // 调用段落函数以后吗,原数组markdown的行就会加上段落的标志
            paragraph(i,j-1,num);
            for(int k = i; k <= j-1; k++)
            {
                string tmp = markdown[k]; // 段落属于区块,区块就可能有强调或者超链接
                tmp = hyperlink(tmp);
                tmp = emphasize(tmp);
                cout << tmp << endl;
            }
            i = j;
        }
        else
        {
            //cout << "空的情况" << endl;
            i++;
        }
    }
    /*
    for(int i = 0; i < rowNums; i++)
    {
        cout << html[i] << endl;
    }*/

    return 0;
}
发布了197 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_41708792/article/details/103465357
今日推荐