分享一个的c++写的,模仿awk的框架类CAwkDoc
2010 年 11 月 20 日
这是我好多年前,模仿awk写的。
awk大家都比较熟悉,使用awk处理文件,读取文件,分割字段这些工作awk自己帮你实现了。
程序员只要编写业务逻辑代码,并且awk还提供了很多常用的字符串操作函数,可以方便地调用,所以使用起来很方便。
但awk脚本毕竟不适合开发复杂的逻辑,而且它提供的库函数也有限,不像c++,有很多第三方库可以调用。
于是我就想到了写一个框架类,把按行读文件,分割字段这些基本功能实现了,只留下业务逻辑供开发人员自由实现
这里用了策略模式,程序员把业务逻辑封装成为一个策略类(实现IAwkOneDualItr接口)传给CAwkDoc即可享受CAwkDoc提供的读文件功能。
最开始考虑过使用模板方法就行,但又担心继承CAwkDoc的程序员覆盖了它的实现,所以觉得还是策略方法好。
这是我之前用CAwkDoc实现的一个小工具: 代码生成器
( https://github.com/kingstarer/kingstarer/tree/master/c%2B%2B/feepacker)
当年这个工具给项目组减轻了不少工作量,我同事们当时特别喜欢。
可惜项目现在早就凉了,不然这个工具估计还是在用:)
工具虽然早没用了,但这个代码生成器的思想(代码模板替换)我还是蛮喜欢的,前段时间搞java项目,写了一个curd代码生成器,还是套用了这个方法,使用代码模板思想。
分享一下CAwkDoc的主要代码
AwkBase.h
#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 AwkMapType; typedef vector 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& 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 m_vecParts; map m_strParams; map m_mpParams; map 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 vecLines; SplitStr(inparamStr, "\n", vecLines); if (vecLines.size() == 0) { cerr << "ERR: 文件(" << m_filename << ")为空或不存在!" <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() 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]; }