--------------------------------------------------------------------------------
標題: String 替換函數源碼
作者: 葉飛虎
日期: 2010.03.15
--------------------------------------------------------------------------------
1 /* 頭文件(.h) */
2
3 // 在 AStr 中查找 AOld 串, 并使用 ANew 替換
4 // 注: SameStr(AOld, ANew, true) 必須為 false, 內部不檢查是否相同
5 // 如: StringReplace("aabbccddbbcc", "bc", "x", true) 返回值為: "aabxcddbxc"
6 KYString StringReplace(const char* AStr, long ALength,
7 const char* AOld, long AOldLen,
8 const char* ANew, long ANewLen,
9 bool AReplaceAll = false,
10 bool ACaseSensitive = true);
11 KYString StringReplace(const KYString& AStr, const char* AOld, long AOldLen,
12 const char* ANew, long ANewLen,
13 bool AReplaceAll = false,
14 bool ACaseSensitive = true);
15 inline KYString StringReplace(const KYString& AStr, const KYString& AOld,
16 const KYString& ANew, bool AReplaceAll = false,
17 bool ACaseSensitive = true)
18 {
19 return StringReplace(AStr, (char*)AOld, AOld.Length(),
20 (char*)ANew, ANew.Length(),
21 AReplaceAll, ACaseSensitive);
22 }
23
24 // 給字符串加單引號, 若字符中存在單引號則自動添加二個單引號
25 // 如: QuotedStr("abc'123'def") 返回值為: "'abc''123''def'"
26 KYString QuotedStr(const char* AStr, int ALength);
27 inline KYString QuotedStr(const KYString& AStr)
28 {
29 return QuotedStr((char*)AStr, AStr.Length());
30 }
31
32
33 /* 源文件(.cpp) */
34
35 // 在 AStr 中查找 AOld 串, 并使用 ANew 替換
36 // 如: StringReplace("aabbccddbbcc", "bc", "x", true) 返回值為: "aabxcddbxc"
37 // 注: 1. 若未找到 AOld 串則返回空串并 ANoFound == true, 否則 ANoFound == false;
38 // 2. 參數 AStr, ALength, AOld, ALen 必須合法
39 // 3. SameStr(AOld, ANew, true) 必須為 false, 內部不檢查是否相同
40 static KYString _DoStringReplace(const char* AStr, long ALength,
41 const char* AOld, long AOldLen,
42 const char* ANew, long ANewLen,
43 bool AReplaceAll, bool ACaseSensitive,
44 bool& ANoFound)
45 {
46 // 初始化
47 KYString result, strNext;
48 int* pNext;
49 long intPos;
50
51 // 校正長度
52 if ((ANew == NULL) || (ANewLen < 0))
53 ANewLen = 0;
54
55 // 分配緩沖區
56 strNext.SetLength(sizeof(int) * AOldLen);
57 pNext = (int*)(char*)strNext;
58
59 // 得到目標串的 KMP 的回溯表
60 GetKMPNext(AOld, AOldLen, pNext, ACaseSensitive);
61
62 // 查找第一個匹配
63 ANoFound = false;
64 intPos = _FindNext(AStr, ALength, AOld, AOldLen,
65 pNext, 1, 1, ACaseSensitive) - 1;
66 if (intPos < 0)
67 ANoFound = true;
68 else if (!AReplaceAll)
69 {
70 // 分配空間
71 result.SetLength(ALength + (ANewLen - AOldLen));
72 char* pPos = (char*)result;
73
74 // 拷貝數據
75 if (pPos != NULL)
76 {
77 // 拷貝前半部
78 if (intPos > 0)
79 {
80 memcpy(pPos, AStr, intPos);
81 pPos += intPos;
82 }
83
84 // 拷貝新串
85 if (ANewLen > 0)
86 {
87 memcpy(pPos, ANew, ANewLen);
88 pPos += ANewLen;
89 }
90
91 // 拷貝后半部
92 intPos += AOldLen;
93 ALength -= intPos;
94 if (ALength > 0)
95 {
96 AStr += intPos;
97 memcpy(pPos, AStr, ALength);
98 }
99 }
100 }
101 else
102 {
103 // 初始化
104 KYString strNew;
105 char* pBegin;
106 char* pPos;
107 long intLen;
108
109 // 計算最大尺寸
110 if (ANewLen <= AOldLen)
111 intLen = ALength + (ANewLen - AOldLen);
112 else if (AOldLen == 1)
113 intLen = intPos + ANewLen * (ALength - intPos);
114 else
115 intLen = ALength + (ANewLen - AOldLen) * ((ALength - intPos) / AOldLen);
116
117 // 分配緩沖區
118 strNew.SetLength(intLen);
119 pBegin = (char*)strNew;
120 pPos = pBegin;
121
122 // 拷貝數據
123 if (pPos != NULL)
124 {
125 // 循環查找
126 do
127 {
128 // 拷貝前半部
129 if (intPos > 0)
130 {
131 memcpy(pPos, AStr, intPos);
132 pPos += intPos;
133 }
134
135 // 拷貝新串
136 if (ANewLen > 0)
137 {
138 memcpy(pPos, ANew, ANewLen);
139 pPos += ANewLen;
140 }
141
142 // 查找下一匹配項
143 intPos += AOldLen;
144 AStr += intPos;
145 ALength -= intPos;
146 intPos = _FindNext(AStr, ALength, AOld, AOldLen,
147 pNext, 1, 1, ACaseSensitive) - 1;
148 } while (intPos >= 0);
149
150 // 拷貝后半部
151 if (ALength > 0)
152 {
153 memcpy(pPos, AStr, ALength);
154 pPos += ALength;
155 }
156
157 // 設置結果
158 result.SetString(pBegin, pPos - pBegin);
159 }
160 }
161
162 // 返回結果
163 return result;
164 }
165
166 // 在 AStr 中查找 AOld 串, 并使用 ANew 替換
167 // 注: SameStr(AOld, ANew, true) 必須為 false, 內部不檢查是否相同
168 // 如: StringReplace("aabbccddbbcc", "bc", "x", true) 返回值為: "aabxcddbxc"
169 KYString StringReplace(const char* AStr, long ALength,
170 const char* AOld, long AOldLen,
171 const char* ANew, long ANewLen,
172 bool AReplaceAll, bool ACaseSensitive)
173 {
174 // 初始化
175 KYString result;
176 bool boolNoFound = true;
177
178 // 檢查參數
179 if ((AStr != NULL) && (AOld != NULL) && (AOldLen > 0) && (ALength >= AOldLen))
180 result = _DoStringReplace(AStr, ALength, AOld, AOldLen, ANew, ANewLen,
181 AReplaceAll, ACaseSensitive, boolNoFound);
182
183 // 若未找到則拷貝數據
184 if (boolNoFound)
185 result.SetString(AStr, ALength);
186
187 // 返回結果
188 return result;
189 }
190
191 // 在 AStr 中查找 AOld 串, 并使用 ANew 替換
192 // 注: SameStr(AOld, ANew, true) 必須為 false, 內部不檢查是否相同
193 // 如: StringReplace("aabbccddbbcc", "bc", "x", true) 返回值為: "aabxcddbxc"
194 KYString StringReplace(const KYString& AStr, const char* AOld, long AOldLen,
195 const char* ANew, long ANewLen,
196 bool AReplaceAll,
197 bool ACaseSensitive)
198 {
199 // 初始化
200 KYString result;
201 bool boolNoFound = true;
202
203 // 檢查參數
204 if ((AOld != NULL) && (AOldLen > 0) && (AStr.Length() >= AOldLen))
205 result = _DoStringReplace((char*)AStr, AStr.Length(),
206 AOld, AOldLen, ANew, ANewLen,
207 AReplaceAll, ACaseSensitive, boolNoFound);
208
209 // 若未找到則拷貝數據
210 if (boolNoFound)
211 result = AStr;
212
213 // 返回結果
214 return result;
215 }
216
217 // 給字符串加單引號, 若字符中存在單引號則自動添加二個單引號
218 // 如: QuotedStr("abc'123'def") 返回值為: "'abc''123''def'"
219 KYString QuotedStr(const char* AStr, int ALength)
220 {
221 // 字符
222 #define Char_Quoted '\'' // 單引號
223
224 // 靜態常量
225 static const KYString Str_Null = "''";
226
227 // 初始化
228 KYString result;
229
230 // 判斷是否為空串
231 if ((AStr == NULL) || (ALength <= 0))
232 result = Str_Null;
233 else
234 {
235 // 分配足夠的字符串空間
236 KYString strNew;
237 strNew.SetLength(ALength + ALength + 2);
238
239 // 初始化
240 char* pBegin = (char*)strNew;
241 char* pPos = pBegin;
242 char* pStr = (char*)AStr;
243 char* pEnd = pStr + ALength;
244
245 // 左引號
246 *(pPos++) = Char_Quoted;
247
248 // 循環操作
249 while (pStr < pEnd)
250 {
251 // 判斷是否單引號
252 if (*pStr == Char_Quoted)
253 *(pPos++) = Char_Quoted;
254
255 // 字符賦值, 下一字符
256 *(pPos++) = *(pStr++);
257 }
258
259 // 右引號
260 *(pPos++) = Char_Quoted;
261
262 // 設置返回值
263 result.SetString(pBegin, pPos - pBegin);
264 }
265
266 // 返回結果
267 return result;
268 }
269
posted on 2011-05-22 12:05
Kyee Ye 閱讀(662)
評論(0) 編輯 收藏 引用 所屬分類:
C++類庫KYLib 、
源碼