Abstract
寫文字檔轉檔程式是很常見的需求,一般來說,這種都屬於dirty job,沒什麼技巧,純粹是迴圈硬幹,若使用STL來寫轉檔程式,不只程式超短,一個迴圈都不需要!!
Introduction
昨天網友Momo要我幫他寫一個轉檔程式,將文字檔轉成XML檔,格式如下
文字檔user_b5fix.dat
一元運算符,一元運算子
二叉樹,二元樹
二元運算符,二元運算子
二分查找,二分搜尋法
二進制,二進位
二極管,二極體
人工智能,人工智慧
人工過濾,手動過濾
八進制的,八進位的
XML檔tongwen.xml
<manifest>
<traditional>
<phrase><s>数据</s><r>資料</r></phrase>
<phrase><s>台湾</s><r>台灣</r></phrase>
</traditional>
<simplified>
</simplified>
</manifest>
user_b5fix.dat是個純文字檔,記載著繁體中文和簡體中文的對照表,實際上檔案有三千多筆資料,因為篇幅的關係,我只列出前幾行,希望轉成XML檔後,在<s></s>內放簡體中文,在<r></r>內放繁體中文。
txt_to_xml.cpp
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
整個轉檔的程式的想法是:將文字檔讀進vector後,在vector內作轉檔工作,最後再輸出到XML檔。
21行、22行
ofstream outFile("tongwen.xml");
宣告欲讀入的文字user_b5fix.dat和欲輸出的文字檔tongwen.xml。
24行
宣告一個vector。
25行
將文字檔讀入vector,使用了copy()這個泛型演算法,第一個參數傳入文字檔的開始位置,第二個參數傳入文字檔的結束位置,如此copy()就能從頭到尾的讀取文字檔,第三個參數是將讀進的資料寫到vector。為什麼要用back_inserter()呢?因為我們希望資料是一筆一筆採用附加的方式寫入vector。
26行
這一行算是dirty job,因為原來的user_b5fix.dat文字檔中,第一行是-1,-1,-1,-1,-1,-1這些垃圾資料,所以必須先刪除之,使用了remove()泛型演算法。
27行
轉檔工作正式開始,使用了transform()泛型演算法,一般來說transform()是用來將a容器轉換到b容器使用,但由於現在來源和目的是同一個容器,所以第一個參數和第三個參數一樣。
該如何轉換呢?我們必須將規則告訴transform(),第四個參數op是我們另外寫的function,這個參數可以是一般global function,或者是function object(functor)。
16行
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
就是我們自己寫的global function,首先將","替換成</s><r>,然後在每行前後加上XML tag。
或許你會覺得transform()為了轉換規則,還需另開一個global function很麻煩,在boost和C# 3.0的lambda就是為了解決這個問題,可以直接將轉換規則透過lambda寫在transform()裡。
31行
處理XML檔頭所需的字串,在C++裡,不只cin、cout可以使用<<喔,檔案也可以。
32行
將轉好的vector資料copy到XML檔。
33行
處理XML檔檔尾字串。
35行
outFile.close();
對兩個檔案進行關檔動作。
Conclusion
本來發下豪語要在20行內寫出來,結果現在扣掉註解,還需26行,哈。若使用boost的lambda還可以再省掉三行,不過最少全部使用STL解決,和我預期的目標接近。
若是C#和Java coder看到這種程式碼應該相當震驚,回想我第一次看到STL時那種驚訝的表情,竟然完全沒用到一行迴圈!!這正是STL優雅之處。