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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章