這是我好多年前,模仿awk寫的。
awk你們都比較熟悉,使用awk處理文件,讀取文件,分割字段這些工做awk本身幫你實現了。
程序員只要編寫業務邏輯代碼,而且awk還提供了不少經常使用的字符串操做函數,能夠方便地調用,因此使用起來很方便。
但awk腳本畢竟不適合開發複雜的邏輯,並且它提供的庫函數也有限,不像c++,有不少第三方庫能夠調用。
因而我就想到了寫一個框架類,把按行讀文件,分割字段這些基本功能實現了,只留下業務邏輯供開發人員自由實現java
這裏用了策略模式,程序員把業務邏輯封裝成爲一個策略類(實現IAwkOneDualItr接口)傳給CAwkDoc便可享受CAwkDoc提供的讀文件功能。
最開始考慮過使用模板方法就行,但又擔憂繼承CAwkDoc的程序員覆蓋了它的實現,因此以爲仍是策略方法好。c++
這是我以前用CAwkDoc實現的一個小工具:代碼生成器(https://github.com/kingstarer/kingstarer/tree/master/c%2B%2B/feepacker)
當年這個工具給項目組減輕了很多工做量,我同事們當時特別喜歡。
惋惜項目如今早就涼了,否則這個工具估計仍是在用:)
工具雖然早沒用了,但這個代碼生成器的思想(代碼模板替換)我仍是蠻喜歡的,前段時間搞java項目,寫了一個curd代碼生成器,仍是套用了這個方法,使用代碼模板思想。git
分享一下CAwkDoc的主要代碼程序員
AwkBase.hgithub
#pragma once #include "AwkFunc.h" class CAwkDoc; class IAwkOneDualItr { public: virtual int dualBegin(CAwkDoc &Doc) = 0; //返回0表明正常,繼續處理下一條 返回1表明退出文本處理直接到End階段 返回-1表明處理出錯,直接退出 virtual int dualOneLine(CAwkDoc &Doc) = 0; virtual int dualEnd(CAwkDoc &Doc) = 0; }; class CAwkOneDualItrBase:public IAwkOneDualItr { public: virtual int dualBegin(CAwkDoc& Doc) { return 0; } virtual int dualEnd(CAwkDoc& Doc) { return 0; } }; class CAwkDoc { public: typedef map<string, string> AwkMapType; typedef vector<string> AwkVecType; public: CAwkDoc(void); CAwkDoc(IAwkOneDualItr* lineopr, const string& filepath); virtual ~CAwkDoc(void); virtual bool run(); void setFileName(const string& filepath) { m_filename = filepath; } void setDelimer(const string delimer) { m_delimer = delimer; } vector<string>& Parts() { return m_vecParts; } void setStrParam(const string& paramname, const string& paramvalue); string& getStrParam(const string& paramname); AwkVecType& getVecParam(const string& paramname); AwkMapType& getMapParam(const string& paramname); public: int m_nf; int m_nr; string m_filename; string m_line; string m_delimer; vector<string> m_vecParts; map<string, string> m_strParams; map< string, AwkMapType > m_mpParams; map< string, AwkVecType > m_vecParams; public: IAwkOneDualItr *m_lineopr; };
AwkBase.cpp框架
#include "stdafx.h" #include "AwkBase.h" CAwkDoc::CAwkDoc(void) { m_delimer = " "; m_nf = m_nr = 0; m_lineopr = NULL; } CAwkDoc::CAwkDoc(IAwkOneDualItr* lineopr, const string& filepath): m_lineopr(lineopr), m_filename(filepath) { m_nf = m_nr = 0; m_delimer = " "; } CAwkDoc::~CAwkDoc(void) { } bool CAwkDoc::run() { //讀取文件 string inparamStr = FileToString(m_filename); //將文件分行 vector<string> vecLines; SplitStr(inparamStr, "\n", vecLines); if (vecLines.size() == 0) { cerr << "ERR: 文件(" << m_filename << ")爲空或不存在!" << endl; return false; } assert(m_lineopr != NULL); m_lineopr->dualBegin(*this); for (size_t i = 0; i < vecLines.size(); i++) { m_line = vecLines[i]; if (m_line == "") { continue; } //刪除多餘空格(爲後面分割作準備) string theline = m_line; //constrictSpace(theline); m_nr++; m_nf = SplitStr(theline, m_delimer, m_vecParts); if (m_vecParts.size() < 20) { m_vecParts.resize(20); } int ret = m_lineopr->dualOneLine(*this); //1是正常結束 -1是異常結束 if ( ret == 1 ) { break; } else if ( ret == -1 ) { return false; } } m_lineopr->dualEnd(*this); return true; } void CAwkDoc::setStrParam(const string& paramname, const string& paramvalue) { m_strParams[paramname] = paramvalue; } string& CAwkDoc::getStrParam(const string& paramname) { return m_strParams[paramname]; }