C++實現(xiàn)一個簡單的Markdown解釋器

概要###

這是一個在實驗樓中找到的一個項目渊迁,用CPP寫的Markdown解釋器蜡歹,具體要求可以點擊這個網頁查看

簡介

在這個Markdown解釋器中,采用的是文件輸入輸出流芋哭,將文件讀入C++中然后進行字符串操作并輸出成html文件

實現(xiàn)的功能

  1. 處理多級標題
  2. 處理代碼和代碼塊
  3. 處理多級引用
  4. 處理無序富寿、有序列表
  5. 處理轉義字符
  6. 處理粗體睬隶、斜體
  7. 處理分割線
  8. 處理超鏈接和圖片

運用的庫

  • fstream
  • string
  • sstream
  • vector
  • stack
  • queue
  • regex

項目結構

  • 程序文件
  • main.cpp
  • mdtransform.h
  • mdtransform.cpp
  • 待處理文件
  • test.md
  • 輸出文件
    • index.html
    • my-markdown.css

函數(shù)

//mdtransform.h

#ifndef MARKDOWNTRANSFORM_H
#define MARKDOWNTRANSFORM_H
class MarkdownTransform
{
public:
    MarkdownTransform(std::string);
    ~MarkdownTransform();
    std::string getContents();
    void process_title(std::vector<std::string>::iterator &, std::vector<std::string> & );//標題
    void process_code(std::vector<std::string>::iterator &, std::vector<std::string> &);//代碼
    void process_refer(std::vector<std::string>::iterator &, std::vector<std::string> &);//引用
    void process_list(std::vector<std::string>::iterator &, std::vector<std::string> &);//列表
    void process_escape_first(std::vector<std::string>::iterator &, std::vector<std::string> & , std::queue<char>&);//轉義字符
    void process_escape_last(std::vector<std::string>::iterator &, std::vector<std::string> &, std::queue<char>&);//轉義字符
    void process_bold_and_italic(std::vector<std::string>::iterator &, std::vector<std::string> &);//粗體斜體
    void process_parting_line(std::vector<std::string>::iterator &, std::vector<std::string> &);//分割線
    void process_linebreak(std::vector<std::string>::iterator&, std::vector<std::string>&);//換行
    void process_emptyline(std::vector<std::string>::iterator&, std::vector<std::string>&);//處理空行
    void process_url(std::vector<std::string>::iterator&, std::vector<std::string>&);//超鏈接
    void process_image(std::vector<std::string>::iterator&, std::vector<std::string>&);//圖片
    //輔助函數(shù)
    int assist_list(int, std::string);
    void change_list(int, std::vector<std::string>::iterator &,int);

    void split(std::string str, std::string limit, std::vector<std::string> &);
    std::string assist_url(std::string &, std::regex &, std::regex &, std::regex &);
    std::string assist_image(std::string &, std::regex &, std::regex &, std::regex &);

private:
    std::string file_position;
};

#endif // !MARKDOWNTRANSFORM_H

//mdtransform.cpp
函數(shù)getContents()

std::string MarkdownTransform::getContents()
{
    std::string md2html_outfile = "";//最后輸出的總文件
    std::ifstream fin;
    std::queue<char> charqueue;//用于辨別轉義字符
    fin.open(file_position);
    if (fin.is_open())
    {
        std::string get_oneline;
        std::vector<std::string> totalstring;

        while (getline(fin, get_oneline))//連續(xù)獲取fin中的一行,并把每一行添加到vector容器
        {
            totalstring.push_back(get_oneline);

        }
        int strveclen = totalstring.size();
        auto vit = totalstring.begin();
        process_escape_first(vit, totalstring,charqueue);
        process_code(vit, totalstring);//加入code標識符作喘,必須最先理疙,因為code中的東西無用
        process_list(vit, totalstring);
        process_parting_line(vit, totalstring);
        process_title(vit, totalstring); //加入h1~h5標識符,必須先于引用
        process_refer(vit, totalstring);
        process_bold_and_italic(vit, totalstring);
        process_image(vit, totalstring);
        process_url(vit, totalstring);
        process_linebreak(vit, totalstring);
        process_escape_last(vit, totalstring, charqueue);
        process_emptyline(vit, totalstring);

        for (auto ptr = totalstring.begin(); ptr != totalstring.end(); ptr++)
        {
            md2html_outfile += (*ptr) + '\n';
        }
        fin.close();
    }
    return md2html_outfile;
}

函數(shù)具體實現(xiàn)

基本上所有的函數(shù)都是利用迭代器的二重循環(huán)去遍歷文件然后對字符串做對應的修改

std::vector<std::string>::iterator  viter;
std::vector<std::string> totalstr;
for (; viter != totalstr.end(); viter++)
    {
        std::string::iterator striter = (*viter).begin();
        if (!(*viter).empty())
        {
            for (; striter != (*viter).end(); striter++)
            {
            }
        }
    }
  • process_title中使用了計數(shù)器泞坦,記錄title等級并寫入h1~h5中
  • process_code中分為兩種情況,一種是處理代碼塊砖顷,一種是處理行內代碼
  • 處理代碼塊的時候用的是匹配字符串```贰锁,然后尋找下一行的```并保護其中的成員不被別的行數(shù)所修改
  • 處理行內代碼是采用stack和counter判斷應該添加什么html標記
  • process_refer用了stack處理多級引用
  • process_list用了三個函數(shù),主函數(shù)是process_list
  • assist_list判斷是有序列表還是無序列表
  • change_list修改行內內容,然后添加html標記
  • process_list用stack處理各種情況滤蝠,并用flag標記一行的列表級數(shù)
  • process_escape用了兩個函數(shù)
    • process_escape_first先把轉義字符后面的那個字符壓入queue
    • process_escape_last把queue中的字符逐一替代轉義字符
  • process_bold_and_italic用了計數(shù)器去處理豌熄,0/1時輸出不同的html標記
  • process_parting_line用了計數(shù)器
  • process_linebreak沒啥好講
  • process_emptyline同上
  • process_url用了三個函數(shù),主函數(shù)是process_url
  • split是一個字符串分割函數(shù)物咳,用了string的find()和substr()函數(shù)分割锣险,并放入容器中
  • assist_url通過正則表達式處理最后的url并添加html標記
  • process_url定義各種正則表達式,然后遍歷文件和對文件進行處理
  • process_image同process_url
具體代碼

在github上面有具體代碼览闰,=-=其實代碼寫的挺啰嗦的芯肤,而且挺一般。

碼完這個Markdown解釋器之后的感受

  1. 過程很艱難...
  2. debug很蛋疼压鉴,真正體會到design first,code later的重要性和好處
  3. 降低耦合性這些真的特別重要崖咨,一開始耦合度特別高,然后強行降低了油吭,雖然最后還是有點耦合度的....
  4. 做個小項目击蹲,其實還是挺有趣的,對迭代器婉宰、對正則歌豺、對各種STL有了更深的理解
  5. 還有很多不足,還有很多沒有實現(xiàn)的功能心包,例如高級的畫表格类咧。。。例如代碼塊識別出是JS/cpp/java/....例如超鏈接的另一種形式(下面代碼)....例如蛋疼的換行問題(其實不同markdown解釋器好像對換行實現(xiàn)都不大一樣)轮听。骗露。。還順帶寫了markdown的CSS
[Google][link]
[link]: http://www.google.com/ "Google"

PS.實驗樓這個網站上面的小項目好像挺多的

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末血巍,一起剝皮案震驚了整個濱河市萧锉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌述寡,老刑警劉巖柿隙,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鲫凶,居然都是意外死亡禀崖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門螟炫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來波附,“玉大人,你說我怎么就攤上這事昼钻〉牛” “怎么了?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵然评,是天一觀的道長仅财。 經常有香客問我,道長碗淌,這世上最難降的妖魔是什么盏求? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮亿眠,結果婚禮上碎罚,老公的妹妹穿的比我還像新娘。我一直安慰自己缕探,他們只是感情好魂莫,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爹耗,像睡著了一般耙考。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上潭兽,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天倦始,我揣著相機與錄音,去河邊找鬼山卦。 笑死鞋邑,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播枚碗,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼逾一,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肮雨?” 一聲冷哼從身側響起遵堵,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怨规,沒想到半個月后陌宿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡波丰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年壳坪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掰烟。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡爽蝴,死狀恐怖,靈堂內的尸體忽然破棺而出媚赖,到底是詐尸還是另有隱情霜瘪,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布惧磺,位于F島的核電站,受9級特大地震影響捻撑,放射性物質發(fā)生泄漏磨隘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一顾患、第九天 我趴在偏房一處隱蔽的房頂上張望番捂。 院中可真熱鬧,春花似錦江解、人聲如沸设预。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鳖枕。三九已至,卻和暖如春桨螺,著一層夾襖步出監(jiān)牢的瞬間宾符,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工灭翔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留魏烫,地道東北人。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像哄褒,于是被迫代替她去往敵國和親稀蟋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內容