1 ///@brief 使用空白字符匹配
2 #define USE_WHITE_SPACE_MATCH
3
4 /*!
5 * @brief 匹配一個(gè)字符串模版
6 * @param pszText 需要匹配的字符串
7 * @param uTextLen 需要匹配的字符串長(zhǎng)度
8 * @param pszTemplateText 需要匹配的模版字符串
9 * @param uTemplateTextLen 需要匹配的模版字符串的長(zhǎng)度
10 * @param pMatchedLen 返回的完成匹配的字符串長(zhǎng)度
11 * @return 返回是否匹配成功
12 * @retval true on 匹配成功
13 * @retval false on 匹配失敗
14 */
15 bool _MatchTemplate( const wchar_t * pszText, size_t uTextLen, const wchar_t * pszTemplateText, size_t uTemplateTextLen, size_t * pMatchedLen )
16 {
17
18 size_t uTextPos = 0u, uTemplateTextPos = 0u;
19 size_t uLastStarPos = ~(size_t)0u;
20
21 // 沒(méi)有匹配的模版,直接匹配成功
22 if( uTemplateTextLen == 0 )
23 {
24 if( pMatchedLen != NULL )
25 *pMatchedLen = uTextPos;
26 return true;
27 }
28 while( true )
29 {
30 wchar_t cTemplate = pszTemplateText[uTemplateTextPos];
31 switch( cTemplate )
32 {
33 #ifdef USE_WHITE_SPACE_MATCH
34 case L'.':
35 {
36 if( pszText[uTextPos] != 0x20 &&
37 pszText[uTextPos] != 0x3000 )
38 {
39 if( pMatchedLen != NULL )
40 *pMatchedLen = uTextPos;
41 return false;
42 }
43 ++uTemplateTextPos;
44 ++uTextPos;
45 }
46 break;
47 #endif
48 case L'?':
49 {
50 ++uTemplateTextPos;
51 ++uTextPos;
52 }
53 break;
54 case L'*':
55 {
56 if( uTemplateTextPos >= uTemplateTextLen-1 )
57 {
58 // 結(jié)尾的*,直接認(rèn)為是匹配所有字符(包括空)
59 if( pMatchedLen != NULL )
60 *pMatchedLen = uTextLen;
61 return true;
62 }
63
64 wchar_t cNextTemplate = pszTemplateText[uTemplateTextPos+1];
65 // 跳過(guò)重復(fù)的*
66 if( cNextTemplate == '*' )
67 {
68 ++uTemplateTextPos;
69 break;
70 }
71 // 記錄最后一個(gè)*的出現(xiàn)位置
72 if( uLastStarPos != uTemplateTextPos )
73 uLastStarPos = uTemplateTextPos;
74 // 檢查下一個(gè)模版字符是否匹配
75
76 // ?匹配直接跳過(guò)
77 if( cNextTemplate == '?' )
78 {
79 uTemplateTextPos+= 2;
80 }
81 #ifdef USE_WHITE_SPACE_MATCH
82 // 空格匹配
83 else if( cNextTemplate == '.' )
84 {
85 if( pszText[uTextPos] == 0x20 ||
86 pszText[uTextPos] == 0x3000 )
87 {
88 uTemplateTextPos+=2;
89 }
90 }
91 #endif
92 // 字符匹配
93 else if( cNextTemplate == pszText[uTextPos] )
94 {
95 uTemplateTextPos+=2;
96 }
97 // 下一個(gè)字符
98 ++uTextPos;
99 }
100 break;
101 default:
102 if( cTemplate != pszText[uTextPos] )
103 {
104 // 如果遇到過(guò)*就回退到最后一個(gè)*
105 if( uLastStarPos < uTemplateTextLen )
106 {
107 uTemplateTextPos = uLastStarPos;
108 cTemplate = pszTemplateText[uTemplateTextPos];
109 ++uTextPos;
110 break;
111 }
112 if( pMatchedLen != NULL )
113 *pMatchedLen = uTextPos;
114 return false;
115
116 }
117 ++uTextPos;
118 ++uTemplateTextPos;
119 break;
120 }
121 // 成功匹配完城所有的
122 if( uTemplateTextPos >= uTemplateTextLen )
123 {
124 break;
125 }
126 // 沒(méi)有成功匹配完整個(gè)模版,文字就沒(méi)有了
127 if( uTextPos >= uTextLen )
128 {
129 if( pMatchedLen != NULL )
130 *pMatchedLen = uTextPos;
131 return false;
132 }
133 }
134 if( pMatchedLen != NULL )
135 *pMatchedLen = uTextPos;
136 return true;
137 }
138
模版支持三種匹配符號(hào) '*','?','.'
*匹配任意多個(gè)任意字符串
?匹配一個(gè)字符串
.匹配一個(gè)空格
可以通過(guò)注釋掉宏來(lái)禁止匹配空格
達(dá)到的效果和文件系統(tǒng)的文件名匹配差不多
關(guān)于遞歸的方法:
VCZH提供了一個(gè)遞歸的解法,并且“寥寥數(shù)行,瞬間搞定”。
不過(guò),遞歸會(huì)帶來(lái)堆棧的問(wèn)題。
而且他的方法里存在BUG,我就不貼上來(lái)了。
據(jù)他稱那種方法來(lái)自一本 beautiful code的書(shū)。此書(shū)我沒(méi)看過(guò),所以不清楚。
從他的方法本身看,他只能提供是否匹配的一個(gè)結(jié)果,并且匹配模版和待匹配的字符串必須是0結(jié)尾,并且不返回結(jié)束匹配時(shí)的匹配進(jìn)度。
并且在處理*的時(shí)候,有些許小BUG。
雖然他一直在堅(jiān)持自己是在做學(xué)術(shù)研究,也有不少人匿名來(lái)支持他,不過(guò)我覺(jué)得他還是有些態(tài)度問(wèn)題。
總是喜歡在別人的貼上表現(xiàn)自己。做的太過(guò)了就是顯擺了。
從他回帖說(shuō)的那些話,比如“寥寥數(shù)行,瞬間搞定”這些,以及并不完善的代碼看來(lái),他根本就沒(méi)有看過(guò)我的代碼,只是憑字面意思就開(kāi)始貼代碼。
我實(shí)在不清楚他說(shuō)這些話和貼代碼的原因是什么。這些我就不再討論了,我也刪除了他的回復(fù)。
不過(guò)我想說(shuō),如果你一直以這種態(tài)度來(lái)回別人的帖子,那你會(huì)成為一個(gè)令人討厭的人。