概要###
這是一個在實驗樓中找到的一個項目渊迁,用CPP寫的Markdown解釋器蜡歹,具體要求可以點擊這個網頁查看
簡介
在這個Markdown解釋器中,采用的是文件輸入輸出流芋哭,將文件讀入C++中然后進行字符串操作并輸出成html文件
實現(xiàn)的功能
- 處理多級標題
- 處理代碼和代碼塊
- 處理多級引用
- 處理無序富寿、有序列表
- 處理轉義字符
- 處理粗體睬隶、斜體
- 處理分割線
- 處理超鏈接和圖片
運用的庫
- 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解釋器之后的感受
- 過程很艱難...
- debug很蛋疼压鉴,真正體會到design first,code later的重要性和好處
- 降低耦合性這些真的特別重要崖咨,一開始耦合度特別高,然后強行降低了油吭,雖然最后還是有點耦合度的....
- 做個小項目击蹲,其實還是挺有趣的,對迭代器婉宰、對正則歌豺、對各種STL有了更深的理解
- 還有很多不足,還有很多沒有實現(xiàn)的功能心包,例如高級的畫表格类咧。。。例如代碼塊識別出是JS/cpp/java/....例如超鏈接的另一種形式(下面代碼)....例如蛋疼的換行問題(其實不同markdown解釋器好像對換行實現(xiàn)都不大一樣)轮听。骗露。。還順帶寫了markdown的CSS
[Google][link]
[link]: http://www.google.com/ "Google"
PS.實驗樓這個網站上面的小項目好像挺多的