编程时,程序员心中会有图形,而有些代码本身就是图形,不但可读而且可看。
#include "stdafx.h" #include <deque> #include <map> #include <string> using namespace std; //图形由点组成 class TNode { public: wchar_t * name; //构造函数 TNode(wchar_t * _name):name(_name){} virtual const wchar_t * toString(){return name;} }; class TEmp; //组织结构 class TOrg : public TNode { public: TEmp* manager; //负责人 TOrg* parent; //直接上级组织 TOrg(wchar_t * _name): TNode(_name),manager(NULL),parent(NULL){} }; //职员 class TEmp : public TNode { public: TOrg * org; //所属组织 TEmp(wchar_t * _name) : TNode(_name),org(NULL){} }; //定义空节点,效果类似于NULL,从下面的代码看出,是非常需要的。 TNode nil(NULL); /*以下是一些辅助函数,这些辅助函数用于以下的宏,使用辅助函数可以减少 宏的付作用而引起意外的结果。 */ //指定节点的上下级关系 TNode & operator << (TNode & _Left , TNode & _Right) { if(&_Left == &nil || & _Right == &nil) return _Left; TOrg* pOrg = dynamic_cast<TOrg*>(&_Left); if(!pOrg) return _Left; if(dynamic_cast<TOrg*>(&_Right)) ((TOrg*)&_Right)->parent = pOrg;//部门 else ((TEmp*)&_Right)->org = pOrg; //职员 return _Left; } //指定组织的负责人 TNode & operator >> (TNode & _Left , TNode & _Right) { if(&_Left == &nil || & _Right == &nil) return _Left; TEmp* pEmp = dynamic_cast<TEmp*>(&_Left); if(!pEmp) return _Left; ((TOrg*)&_Right)->manager = pEmp; return _Left; } TNode & UpNode(TNode & _Node) { //空节点不处理 if(&_Node == &nil ) return _Node; if(dynamic_cast<TOrg*>(&_Node)) { //部门 return ((TOrg*)&_Node)->parent ? *((TOrg*)&_Node)->parent : nil; } else { //职员 TOrg * org = ((TEmp*)&_Node)->org; while(org) { if(org->manager && org->manager != &_Node) return *org->manager; org = org->parent; } return nil; } } //增加上下文节点 TNode & pushContext(map<wstring, TNode *> & context,TNode * base) { context.insert(pair<wstring, TNode *>(base->name,base)); return *base; } //上下文查找 TNode & findContext(map<wstring, TNode *> & context,wchar_t * name) { if(context.find(name)==context.end()) return nil; return *context[name]; } //增加人员节点 TNode & pushEmps(deque<TEmp>& emps,TEmp & emp) { emps.push_back(emp); return emps[emps.size() - 1]; } //增加组织节点 TNode & pushOrgs(deque<TOrg>& orgs,TOrg & org) { orgs.push_back(org); return orgs[orgs.size() - 1]; } /* 平常的程序语义一般为值代换,宏则提供了形式代换的能力,增强了程序的 表现能力,但也带来许多付作用(意想不到的作用),所以很多教科书和新的语义 都提倡限制宏的作用。 为减少宏的付作用,在书写宏时一般要遵循一些约定: 1、宏参量在使用时,一般要用括号括起来,使其保持整体性,同时式子本身也要括号 扩起来。 //error define #define mul(x,y) x * y // 当x是a+b时,就与原意不符了。 //normal define #define mul(x,y) ((x) * (y)) 2、宏的每一个参量,一般在表达式里只能使用一次。 这是因为宏参量可能会用有付作用(这里指对状态的修改)的式子替换,替换后这样 的付作用会执行多次。 #define ↘ρ(x) (context.insert(pair<wstring, TNode *>((x)->name,&x)),&x) 如果用这个宏替换正文中对应的宏,你会发现,程序执行后所有的人员和部门都 会有三条记录,而不是一条。这是因为对于↘ρ(e(张三))这样的语句,宏参数x所 替换的e(张三),包含了创建与压栈的动作,宏替换后,这样的动作被重复执行了三 次,而不是预想中的一次。 要避免出现这样情况,宏变量在应用时尽可能只使用一次,必要时可以创建辅助 函数来避免这样的情况,这也是本文中出现多个辅助函数的原因。 3、当可预知宏参量可以是语句的时候,除非有特异的需求,需要用大括号把变量封 闭起来,防止替换后声明外泄等一些问题。 以下定义的宏,是尽可能让结构语义形象化、图形化。与计算语义不一样,结构本身是一个几何的概念。 */ //创建职员节点 #define e(x) pushEmps(emps,TEmp(L###x)) //创建组织节点 #define d(x) pushOrgs(orgs,TOrg(L###x)) //上下文压栈 #define ↘ρ(x) pushContext(context,&(x)) //上下文查找 #define ρ(x) findContext(context,L###x) //对于组织,指定组织的上下级关系;对于职员,指定职员所在的组织 #define ← << //指定组织的负责人 #define → >> //对于职员,标示职员的上级;对于组织,标示上一级组织 #define ↑(x) UpNode(x) int _tmain(int argc, _TCHAR* argv[]) { //这是需要的,否则printf语句不好好输出中文。 setlocale( LC_ALL, "" ); /* vector对象在做增加元素操作的时候,当数据块容量不够时,会重建数据块。在程序 上就表现为引用失效。 例子: vector<TEmp> emps; emps.push_back(TEmp(L"x1")); TEmp & e1 = emps[0]; emps.push_back(TEmp(L"x3")); _tprintf(L"%s",e1.name); //插入"x3"后,e1可能会失效 而在下面的代码,会频繁使用引用操作,所以使用deque代替vector 由于上下文引用的不是map的元素,而是真实的节点对象,所以map插入操作是否引起 本身元素的移动,已经是无关紧要了。 */ deque<TEmp> emps; deque<TOrg> orgs; map<wstring, TNode *> context; //上下文 //创建职员 ↘ρ(e(张三)); ↘ρ(e(李四)); ↘ρ(e(王五)); ↘ρ(e(赵六)); ↘ρ(e(周七)); ↘ρ(e(李八)); ↘ρ(e(孙九)); ↘ρ(e(张十)); //创建业务部 ↘ρ(d(业务部))← ↘ρ(d(业务一部))← ↘ρ(d(业务二部)); //指定业务部的职员 ρ(业务一部)← ρ(张三)← ρ(李四); ρ(业务二部)← ρ(王五)← ρ(赵六); //创建其他部门,并指定职员 ↘ρ(d(财务部))← ρ(周七); ↘ρ(d(办公室))← ρ(李八); ↘ρ(d(经理室))← ρ(孙九)← ρ(张十); //创建企业 ↘ρ(d(大洋贸易))← ρ(经理室)← ρ(业务部)← ρ(财务部)← ρ(办公室); //指定企业负责人 ρ(孙九)→ ρ(大洋贸易)→ ρ(经理室); //指定其他部门的负责人 ρ(周七)→ ρ(财务部); ρ(李八)→ ρ(办公室); ρ(张三)→ ρ(业务部); //输出一些结果 printf("赵六的上司: %S\r\n",↑(ρ(赵六)).name); printf("业务部的上一组织: %S\r\n",↑(ρ(业务部)).name); printf("\r\n"); printf("部门信息:\r\n"); for(size_t i=0;i<orgs.size();i++) { printf("%8S\t负责人: %S\t上级部门: %S\r\n",orgs[i].name, orgs[i].manager?orgs[i].manager->name:L"无", ↑(orgs[i]).name); } printf("\r\n"); system("pause"); exit(1); }
现在再看看运行的结果:
是否跟想像的一致?