需求很简单:
有一堆关键词(短句),需要给它们分组。分组逻辑很简单:给出一些归类词语,把包含这些归类词语的关键词归到一类。
归类词语需要支持简单的与或算术逻辑,例如“日记|博客”,意思就是把包含日记或者博客关键词归到一类。
例如这两个关键词都符合归类要求:日记软件,博客工具
又如:“社保&药店”,意思是把包含社保又包含药店的关键词归到一类。
例如:北京的社保药店就符合归类要求,但如果只是北京社保局就不符合归类要求
再如:“(日记|博客)&(社保&药店)”,意思是把即符合“日记|博客”归类要求,又符合“社保&药店”归类要求的关键词归到一类。
一个实际例子:
现在有下面的关键词:
附近专业保洁公司
北京清洁公司
家政公司
北京好的家政公司
保姆
家教公司
有名的家政
口碑好的保姆
归类词语如下:
(专业|好的|有名)&(清洁|家政)&公司
北京&家政
附近
保姆
家政|清洁
分类结果如下:
这是另一个案例分词结果截图:
其实这个需求在linux下直接用grep工具加上简单的shell还是很容易做的,但让我朋友为了这个从头学shell和linux不太现实,所以我帮他做了这个工具。如果有人有兴趣也可以去下载:
下载地址:
链接:https://pan.baidu.com/s/1r6YR8qJGOBxvA9GDPsevzw
提取码:8dmn
===============================================
下面是相关代码,里面用到了中序表达式转成后序表达式计算的技巧
stdafx.h
1 // stdafx.h : 标准系统包含文件的包含文件, 2 // 或是经常使用但不常更改的 3 // 特定于项目的包含文件 4 // 5 6 #pragma once 7 8 #include "targetver.h" 9 10 #include <stdio.h> 11 #include <tchar.h> 12 13 #define NUMOF(arr) (sizeof(arr)/sizeof(arr[0])) 14 15 16 // TODO: 在此处引用程序需要的其他头文件 17 #include <string> 18 #include <vector> 19 #include <iostream> 20 #include <stack> 21 using namespace std;
GetWord.h
1 #pragma once 2 #include "stdafx.h" 3 4 #define TYPE_WORD 0 5 #define TYPE_AND 1 6 #define TYPE_OR 2 7 #define TYPE_BOOL 3 8 #define TYPE_LEFT 4 9 #define TYPE_RIGHT 5 10 11 typedef struct 12 { 13 int nWordType; 14 string sValue; 15 16 void output() 17 { 18 switch (nWordType) 19 { 20 case TYPE_WORD: 21 cout << "TYPE_WORD " <<sValue << endl; 22 break; 23 case TYPE_AND: 24 cout << "TYPE_AND" << endl; 25 break; 26 case TYPE_OR: 27 cout << "TYPE_OR" << endl; 28 break; 29 case TYPE_BOOL: 30 cout << "TYPE_BOOL" << endl; 31 break; 32 case TYPE_LEFT: 33 cout << "TYPE_LEFT" << endl; 34 break; 35 case TYPE_RIGHT: 36 cout << "TYPE_RIGHT" << endl; 37 break; 38 default: 39 cout << "unknow" << endl; 40 break; 41 } 42 } 43 }ST_WORD; 44 45 class CGetWord 46 { 47 public: 48 CGetWord(const char *str); 49 ~CGetWord(void); 50 void rewrind(); //重置到开头 51 bool getWord(ST_WORD &opr); //读取一个单词 52 53 private: 54 char *m_strInput; 55 int m_nPos; 56 };
PostfixExpressions.h
1 #pragma once 2 #include "GetWord.h" 3 4 class CPostfixExpressions 5 { 6 public: 7 CPostfixExpressions(void); 8 bool parse(const char *strIntermediateOrerExpressions); //输入中序 转换成后缀表达式 方便计算 9 bool grep(const char *str); 10 ~CPostfixExpressions(void); 11 void showExpr() 12 { 13 cout << "m_expr.size() = " << m_expr.size() << endl; 14 for (size_t i = 0; i < m_expr.size(); ++i) 15 { 16 m_expr[i].output(); 17 } 18 } 19 private: 20 vector<ST_WORD> m_expr; 21 };
targetver.h
1 #pragma once 2 3 // 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。 4 5 // 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将 6 // WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。 7 8 #include <SDKDDKVer.h>
divide_group.cpp
1 // divide_group.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "GetWord.h" 6 #include "PostfixExpressions.h" 7 8 bool checkHaveNotGbk(const char *buf, const size_t nLen) 9 { 10 //检查是否有非GBK字符(不严谨) 11 //碰到非英文字符 12 bool bHaveNotGbk = false; 13 for (size_t i = 0; i < nLen; ++i) 14 { 15 /* 16 GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。 17 总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。 18 */ 19 unsigned char ch = buf[i]; 20 if ((ch & 0x80) != 0) 21 { 22 if (ch >= 0x81 && ch <= 0xfe) 23 { 24 ch = buf[++i]; 25 if (!(ch >= 0x40 && ch <= 0xFe && ch != 0x7F)) 26 { 27 bHaveNotGbk = true; 28 break; 29 } 30 } 31 else 32 { 33 bHaveNotGbk = true; 34 break; 35 } 36 } 37 } 38 39 return bHaveNotGbk; 40 } 41 42 char *getline(char *buf, size_t nBufSize, FILE *fp) 43 { 44 if ( fgets(buf, nBufSize, fp) == NULL) 45 { 46 return NULL; 47 } 48 49 size_t nLen = strlen(buf); 50 if (nLen > 0 && buf[nLen - 1] == ' ') 51 { 52 buf[--nLen] = '