浅谈IM软件业务知识-实现富文本解析,如:解析字符串、网络链接等

前言

之前在某IM项目中做开发,项目涉及到字符串解析的功能,例如:在输入框输入"/微笑"到聊天窗口中就可以显示为微笑的图片。如何实现这种“文本->图片”的转换,还有一些比如http:\\开头或者com结尾的也能解析成链接,甚至手机号也能自动解析出来,这就使用到了多叉树的数据结构。

该富文本解析适合有限字符集的解析,另附源码点击这里下载

整个过程需要三步:

第一步:准备好表情资源;创建数据结构,把资源放到数据结构中

实现一个map<int , EmotionDataBase>,int就是表情的序号,EmotionDataBase是表情图片的信息。

为了节省空间将所有表情合成一张长条png图片,程序加载的时候再分割成一个个png。这么做唯一好处就是节省安装包大小。


拿表情前3个,微笑 大笑眨眼  为例,每一个表情定义一个结构体

struct EmotionDataBase
{
m_EmotionIndex //表情码
m_EmotionName  //表情名字
m_EmotionTrace //其他信息
m_pBmp         //表情图片
}

这里我们给“微笑”、“大笑”和“眨眼”三个表情进行编码(即index)1000,1001,1002。再定义一个map<int , EmotionDataBase>,目的是通过index可以找到表情所有信息。程序启动后,将表情图放到EmotionDataBase里,同时将表情的名字也放到EmotionDataBase里。

到此,表情资源map已经准备好了。

第二步:创建表情多叉树。

首先写一个多叉树的结构:
class  EmotionTreeNode{
public:
	int                         m_EmotionIndex;
	CPChar                      m_EmotionSymbol;
	vector<EmotionTreeNode*>*   m_Child;
    void bornChild(){
        vector<EmotionTreeNode*>* newVector = new vector<EmotionTreeNode*>;
        newVector->clear();
        m_Child = newVector;
    }
	~EmotionTreeNode()
	{
		if(m_Child){
			m_Child->clear();
			delete m_Child;
			m_Child = NULL;
		}
	}
	EmotionTreeNode(){
		m_EmotionIndex = -1;
		m_Child = NULL;
	} 
};

然后,“/微笑”,“/大笑”,“/眨眼”在内存中,以下面的形式存放


浅谈IM软件业务知识-实现富文本解析,如:解析字符串、网络链接等_第1张图片


当然这个结构很简单,因为除了遍历没有其他操作。将第一步生成的map放到这棵树中来,如上图所示:

【特殊的情况】比如:“/赞”和 “/赞同”。这样的前面是后面的子集;那么在解析的时候需要注意一下!

浅谈IM软件业务知识-实现富文本解析,如:解析字符串、网络链接等_第2张图片

解析到“/赞”的时候,立即获取表情码:1100. 在解析/赞同的时候,遇到“赞”继续往下执行,知道词语末尾,得到表情码1200

第三步、解析

假如,用户输入了“今天天气好/大笑”,解析的步骤是这样的:

从字符串的第一个字符开始查找,查找到/的位置,然后把/后面的字符放到tree中去找,知道找到tree的叶子得到一个index,即1000.那么直接冲map中渠道key=1000的EmotionDataBase,从而得到图片的名字,显示即可

使用多叉树的好处是,遍历一遍字符串可以解析出来,所有的表情。其实,如果我们直接搜索“\大笑”,也能达到这个效果,只是遍历很多次。有10个表情,就要遍历10次,效率太低了。

解析链接

解析连接:我们事先要把常用网站的PreFix(开头)和Postfix(结尾)录入代码中。比如添加PreFix的代码:

void EmotionPaser::_InitData_LinkPrefix()
{
	FT_VL();
	vector<NSString*> * pvws = new vector<NSString*> ();
	pvws->push_back(@"http://");
	pvws->push_back(@"https://");
	pvws->push_back(@"ftp://");
	pvws->push_back(@"www.");
	pvws->push_back(@"wap.");
	pvws->push_back(@"3g.");
	pvws->push_back(@"Www.");
	pvws->push_back(@"WWW.");
	AddEmotionData(CV_INDEX_LINK_PREFIX,@"LINK_PREFIX", pvws,0);<span style="font-family: Menlo;">//创建树</span>
	
	if (pvws != NULL)
	{
		delete pvws;
		pvws = NULL;
	}
}

添加Postfix的代码

void EmotionPaser::_InitData_LinkPostfix()
{
	FT_VL();
	vector<NSString*> * pvws = new vector<NSString*>();
	
	pvws->push_back(@".net");
	pvws->push_back(@".org");
	pvws->push_back(@".gov");
	pvws->push_back(@".edu");
	pvws->push_back(@".mil");
	pvws->push_back(@".biz");
	pvws->push_back(@".info");
	pvws->push_back(@".mobi");
	pvws->push_back(@".pro");
	pvws->push_back(@".cc");
	pvws->push_back(@".ws");
	pvws->push_back(@".travel");
	pvws->push_back(@".tv");
	pvws->push_back(@".fm");
	pvws->push_back(@".museum");
	pvws->push_back(@".int");
	pvws->push_back(@".areo");
	pvws->push_back(@".post");
	pvws->push_back(@".rec");
	pvws->push_back(@".asia");
	pvws->push_back(@".cn");
	pvws->push_back(@".hk");
    
	pvws->push_back(@".jp");
	pvws->push_back(@".mo");
	pvws->push_back(@".sg");
    
	pvws->push_back(@".tw");
    
	pvws->push_back(@".uk");
	pvws->push_back(@".us");
    
	
	pvws->push_back(@".html");
	pvws->push_back(@".htm");
	pvws->push_back(@".php");
	pvws->push_back(@".asp");
	pvws->push_back(@".aspx");
	pvws->push_back(@".jsp");
	pvws->push_back(@".cgi");
	
	pvws->push_back(@".com");
	
	AddEmotionData(CV_INDEX_LINK_POSTFIX,@"LINK_POSTFIX",pvws,0);//创建树
	
	if (pvws != NULL)
	{
		delete pvws;
		pvws = NULL;
	}
}
从代码中不难看出,http://和https://都对应同一个CV_INDEX_LINK_PREFIX

.net、.edu、.php和.asp等都对应同一个CV_INDEX_LINK_POSTFIX。

也就是说,只要解析出两个CV_INDEX_LINK_PREFIX,CV_INDEX_LINK_POSTFIX中的任何一个,都认为是一个链接。

源码

之前项目是symbian开发的,现在移植到iOS平台,源码我放到: http://download.csdn.net/detail/hherima/5161117 

你可能感兴趣的:(多叉树,富文本解析,表情解析)