一:回顾

(1)c++中的string类是在面试中和笔试中经常考的题目; 工程代码免费下载 string类的自行实现

(2)c++中的string类和fstream类合起来是处理外部数据的利器

(3)string类经常用到find find_first_of find_first_not_of find_last_of find_last_not_of substr replace等,以及联合使用来达到java中的split和trim

  (4) 使用friend 仅仅是在类中进行声明的非内部 却可以访问内部成员的外部函数,而且在外部不再需要friend关键字;它与成员函数的区别是,friend和外部函数不含有this对象指针;本文用到了const 定义的全局最大值最小值变量(代替#define)

 (5) 有些函数返回的是MyString& 、Char& 等(引用),MyString、Char 等(传值)这得看你返回的对象是函数的局部变量还是全局变量(或者类当前对象成员变量);前者只能返回一个MyString、Char 等;后者强烈建议返回MyString& 、Char& 等(引用);

(6)有些函数的参数是const MyString& ,有些是MyString& (引用);这是为什么?前者是把外部值传提到子函数内部,且不允许改变;后者是作为函数的返回值传递进去的,返回的结果为函数的处理结果(而不用函数自身返回值了)。

二:下面是简单的实现了一下string类,参照的是STL源码,但是自己理解的还是不够深,难免有一些错误,请各位指教

(1)MyString.h文件


1. #ifndef MYSTRING_H
2. #define MYSTRING_H
3. #include "MyExcept.h"
4. #include <cstring>
5. #include <iostream>
6. const int INI_MAX = 0x7fffffff;//2^32npos
7. const int INI_MIN = 0x80000000;// -2^32
8. const int npos = 0xffffffff;// npos
9. using namespace
10.   
11. class
12. {  
13. public:  
14. // constructor
15. //
16. const MyString &);//
17. const char
18. const size_t,const char);  
19. // destructor
20.     ~MyString();  
21. // attributes
22.   
23. size_t length();// 字符串长度
24. bool isEmpty();// 返回字符串是否为空
25. const char* c_str();// 返回c风格的trr的指针
26. // friend funs
27. // read writer operations
28. friend ostream& operator<< (ostream&, const
29. friend
30. //add operation
31. friend MyString operator+(const MyString&,const
32. // compare operations
33. friend bool operator==(const MyString&,const
34. friend bool operator!=(const MyString&,const
35. friend bool operator<(const MyString&,const
36. friend bool operator<=(const MyString&,const
37. friend bool operator>(const MyString&,const
38. friend bool operator>=(const MyString&,const
39. // 成员函数实现运算符重载,其实一般需要返回自身对象的,成员函数运算符重载会好一些
40. // index operation
41. char& operator[](const size_t);  
42. const char& operator[](const size_t)const;  
43. // =
44. const
45. // +=
46. const
47. // +=
48. //MyString operator+=(const MyString&); cannot be overloaded
49. // 成员操作函数
50. // substr
51. size_t pos,const size_t
52. // append
53. const
54. //insert
55. size_t,const
56. //assign 替换
57. size_t,size_t);  
58. // erase 删除
59. size_t,size_t);  
60. //find_first_of 查找某一个字符 size_t 是非符号数的,重载
61. // 查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。
62. //搜索从index开始,如果没找到就返回string::npos
63. int find_first_of(const char* str,size_t
64. int find_first_of(const char ch,size_t
65. int find_first_of(const MyString &,size_t
66. // 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index开始。如果没找到就返回string::nops
67. int find_first_not_of(const char* str,size_t
68. int find_first_not_of(const char ch,size_t
69. int find_first_not_of(const MyString&,size_t
70. // swap
71. void
72. // replace_all
73. const char oldc,const char
74. size_t index,size_t num1,size_t num2,const char
75. //find
76. int find(const char* str,size_t
77. int find(const MyString& str,size_t
78. int find(const char ch,size_t
79.   
80.   
81. //private
82. private:  
83. char
84. size_t
85. };  
86.   
87.   
88. #endif // MYSTRING_H



(2)MyString.cpp文件



1. #include "MyString.h"
2. #include <cassert>
3.   
4. // constructor
5.     MyString::MyString():p_str(NULL),strLength(0){}  
6.   
7. const MyString &str)//
8.     {  
9. if(NULL == str.p_str)  
10.         {  
11. return;  
12.         }  
13.         strLength = str.strLength;  
14. new char[strLength+1];  
15.         strcpy(p_str,str.p_str);  
16.     }  
17. const char
18.     {  
19. if(NULL == str)  
20.         {  
21. return;  
22.         }  
23.         strLength = strlen(str);  
24. new char[strLength+1];  
25.         strcpy(p_str,str);  
26.     }  
27. const size_t len,const char
28.     {  
29. if(NULL == ch)  
30.         {  
31. return;  
32.         }  
33.         strLength = len;  
34. new char[strLength+1];  
35. for(size_t
36.         {  
37.             p_str[i] = ch;  
38.         }  
39. '\0';// 因为strset以'\0'结束的
40. " &&"
41. //strset(p_str,ch);
42. //cout << p_str[0] << ",,,"<<strlen(p_str) << "," << strLength << endl;
43.     }  
44. // destructor
45.     MyString::~MyString()  
46.     {  
47. delete[] p_str;  
48.     }  
49.   
50. // attributes
51. size_t MyString::length()// 字符串长度
52.     {  
53. return
54.     }  
55. bool MyString::isEmpty()// 返回字符串是否为空
56.     {  
57. return strLength==0?true:false;  
58.     }  
59. const char* MyString::c_str()  
60.     {  
61. return
62.     }  
63. // 为什么不是引用呢??? friend 使用在类里面进行声明的,外面就不需要了,而且友元函数不属于类的成员函数,所以不用MyString::
64. // ostream
65. const
66.     {  
67. if(str.p_str != NULL)  
68.         {  
69.             out << str.p_str;  
70.         }  
71. return
72.     }  
73. // istream,一个是const另一个不是,根据变还是不变
74.     istream& operator>> (istream& in, MyString& str)  
75.     {  
76. char tmp[100];// 临时字符串
77. if(in>>tmp)  
78.         {  
79. delete[] str.p_str;  
80.             str.strLength = strlen(tmp);  
81. new char[str.strLength+1];  
82.             strcpy(str.p_str,tmp);  
83.         }  
84. return
85.     }  
86. // + 加
87. const MyString& lhs,const
88.     {  
89.         MyString ret;  
90.         ret.strLength = lhs.strLength + rhs.strLength;  
91. new char[ret.strLength+1];  
92.         strcpy(ret.p_str,lhs.p_str);  
93.         strcat(ret.p_str,rhs.p_str);  
94. return
95.     }  
96. // compare operations
97. bool operator==(const MyString& lhs,const
98.     {  
99. return strcmp(lhs.p_str,rhs.p_str)==0?true:false;  
100.     }  
101. bool operator!=(const MyString& lhs,const
102.     {  
103. return strcmp(lhs.p_str,rhs.p_str)!=0?true:false;  
104.     }  
105. bool operator<(const MyString& lhs,const
106.     {  
107. return strcmp(lhs.p_str,rhs.p_str)<0?true:false;  
108.     }  
109. bool operator<=(const MyString& lhs,const
110.     {  
111. return strcmp(lhs.p_str,rhs.p_str)<=0?true:false;  
112.     }  
113. bool operator>(const MyString& lhs,const
114.     {  
115. return strcmp(lhs.p_str,rhs.p_str)>0?true:false;  
116.     }  
117. bool operator>=(const MyString& lhs,const
118.     {  
119. return strcmp(lhs.p_str,rhs.p_str)>=0?true:false;  
120.     }  
121. // 成员函数实现运算符重载
122. // index operation
123. char& MyString::operator[](const size_t
124.     {  
125. if(index<0 || index>=strLength)  
126.         {  
127. throw
128.         }  
129. return
130.     }  
131. const char& MyString::operator[](const size_t index)const
132.     {  
133. if(index<0 || index>=strLength)  
134.         {  
135. throw
136.         }  
137. return
138.     }  
139. // = 赋值构造函数(判断是否是自身) 为什么要这样删除呢?
140. const
141.     {  
142. if(this
143.         {  
144. if(strLength<other.strLength)  
145.             {  
146. delete[] p_str;  
147. new char[other.strLength+1];  
148.             }  
149.             strLength = other.strLength;  
150.             strcpy(p_str,other.p_str);  
151. // 这样可能会产生多余的未释放的空间
152. return *this;  
153.     }  
154. // += 相当于返回的是备份的,内部对象的销毁,不影响的 和 下面的完全不一样的
155. //    MyString MyString::operator+=(const MyString& other)
156. //    {
157. //        if(NULL == other.p_str)
158. //        {
159. //            return *this;
160. //        }
161. //        MyString ret;
162. //        ret.strLength = strLength + other.strLength;
163. //        ret.p_str = new char[ret.strLength+1];
164. //        strcpy(ret.p_str,p_str);
165. //        strcat(ret.p_str,other.p_str);
166. //        return ret;
167. //    }
168. // 返回的是当前对象的引用,当前对象就在调用函数里,所以不会销毁的
169. // 判断一下是否是自身相加
170. const
171.     {  
172. if(NULL == other.p_str)  
173.         {  
174. return *this;  
175.         }  
176. if(this
177.         {  
178. this);  
179. return *this
180. // 必须判断是否相等的,而且要+=的,这样相当于调用了自身,但是这次直接下面去了,不进入if的
181.         strLength += other.strLength;  
182. //strLength *= 2;
183. char
184. new char[strLength+1];  
185.         strcpy(p_str,p_old);  
186.         strcat(p_str,other.p_str);  
187. delete[] p_old;// 删除旧的空间
188. return *this;  
189.     }  
190. // 成员操作函数
191. // substr  返回应用是不行的,错误的;取从pos开始的n个字符组成的子串
192. //MyString& MyString::substr(size_t pos,const size_t n)
193. size_t pos,const size_t
194.     {  
195. if((pos+n)>=strLength)  
196.         {  
197. throw
198.         }  
199.         MyString ret;  
200.         ret.strLength = n;  
201. //ret.p_str = new char[n+1];
202. new char[ret.strLength+1]; //也可以
203. for(size_t
204.         {  
205.             ret.p_str[i] = p_str[pos+i];  
206.         }  
207. '\0';  
208. //        for(size_t i=0;i<ret.strLength;i++)
209. //        {
210. //            ret[i] = (*this)[pos+i];
211. //            cout << ret[i] << ",,";
212. //        }// 也行的,利用刚刚重载的【】,这样更好,不用再次判断越界了,不知道为什么,报错误的
213. //        ret[ret.strLength] = '\0';
214. return
215.     }  
216. // append 同 += 追加到末尾
217. const
218.     {  
219. this += other;// 利用刚刚那重载的+=
220. return *this;  
221.     }  
222. //insert 从pos开始的插入other
223. size_t pos,const
224.     {  
225. if(pos<0 || pos>=strLength)  
226.         {  
227. throw
228.         }  
229. char
230.         strLength += other.strLength;  
231. new char[strLength+1];  
232. for(size_t
233.         {  
234.             *(p_str+i) = *(p_old+i);  
235.         }  
236. for(size_t
237.         {  
238.             *(p_str+i) = other.p_str[i-pos];  
239.         }  
240. for(size_t
241.         {  
242.             *(p_str+i) = p_old[i-other.strLength];  
243.         }  
244. '\0';  
245. return *this;  
246.     }  
247. //assign 替换  用other的POS开始的n对应替换this的pos开始的
248. size_t pos,size_t
249.     {  
250. //        if(pos<0 || pos>=strLength)
251. //        {
252. //            throw Outofbond();
253. //        }
254. // assert 的好处
255.         assert(pos+n<other.strLength);  
256. if(strLength < pos + n)  
257.         {  
258. char
259.             strLength = pos + n;  
260. new char[strLength+1];  
261. for(size_t
262.             {  
263.                 *(p_str+i) = *(p_old+i);  
264.             }  
265. delete[] p_old;  
266.         }  
267. for(size_t
268.         {  
269.             *(p_str+i) = other.p_str[i];  
270.         }  
271. '\0';  
272. return *this;  
273.     }  
274. // erase 删除 这个方法并不是很好的,并没有释放所erase的空间,请看下面的
275. //    MyString& MyString::erase(size_t pos,size_t n)
276. //    {
277. //        if((pos+n)>strLength)
278. //        {
279. //            throw Outofbond();
280. //        }
281. //        size_t index = pos + n;
282. //        while(*(p_str+index)!='\0')
283. //        {
284. //            *(p_str+index-n) = *(p_str+index);
285. //            ++index;
286. //        }
287. //        *(p_str+index-n) = '\0';
288. //        return *this;
289. //    }
290. // erase 删除 从pos开始的n个字符
291. size_t pos,size_t
292.     {  
293. if((pos+n)>strLength)  
294.         {  
295. throw
296.         }  
297. char
298.         strLength -= n;  
299. new char[strLength+1];  
300. for(size_t
301.         {  
302.             p_str[i] = p_old[i];  
303.         }  
304. for(size_t
305.         {  
306.             p_str[i] = p_old[i+n];  
307.         }  
308. '\0';  
309. return *this;  
310.     }  
311. //find_first_of 查找某一个字符 size_t 是非符号数的
312. // 查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。
313. //搜索从index开始,如果没找到就返回string::npos
314. int MyString::find_first_of(const char* str,size_t
315.     {  
316. if(NULL == str || index >=strLength)  
317. return
318. int
319. size_t
320. for(j=0;j<tmp_len;j++)  
321.         {  
322.             flag = npos;  
323. for(size_t
324.             {  
325. if(str[j] == p_str[i])  
326.                 {  
327.                     flag = i;  
328. break;  
329.                 }  
330.             }  
331. //            indexs[j] = flag;
332. if(flag != npos)  
333.             {  
334.                 min_index = min_index<flag?min_index:flag;  
335.             }  
336.         }  
337. //        for(j=0;j<tmp_len;j++)
338. //        {
339. //            if(indexs[j]!=npos)
340. //                min = min<indexs[j]?min:indexs[j];
341. //        }
342. if(min_index == INI_MAX)  
343.         {  
344. return
345. //            min_index = npos;
346. //           cout << "---npos----" << min_index << ",,,,";
347.         }  
348. return
349.     }  
350. int MyString::find_first_of(const char ch,size_t
351.     {  
352. if(NULL == ch || index >=strLength)  
353. return
354. int
355. size_t
356. for(size_t
357.         {  
358. if(ch == p_str[i])  
359.             {  
360.                 flag = i;  
361. break;  
362.             }  
363.         }  
364. return
365.     }  
366. int MyString::find_first_of(const MyString& str,size_t
367.     {  
368. if(NULL == str || index >=strLength)  
369. return
370. int
371. size_t
372. for(j=0;j<str.strLength;j++)  
373.         {  
374.             flag = npos;  
375. for(size_t
376.             {  
377. if(str[j] == p_str[i])  
378.                 {  
379.                     flag = i;  
380. break;  
381.                 }  
382.             }  
383. if(flag != npos)  
384.             {  
385.                 min_index = min_index<flag?min_index:flag;  
386.             }  
387.         }  
388. if(min_index == INI_MAX)  
389.         {  
390. return
391.         }  
392. return
393.     }  
394. // 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。
395. //搜索从index开始。如果没找到就返回string::nops O(N^2)
396. int MyString::find_first_not_of(const char *str,size_t
397.     {  
398. if(NULL == str || index >=strLength)  
399. return
400. size_t
401. size_t
402. for(i=index;i<strLength;i++)  
403.         {  
404. for(;j<tmp_len;j++)  
405.             {  
406. if(p_str[i]==str[j])  
407. break;  
408.             }  
409. if(j==tmp_len)  
410. break;// 根据跳出的内层for的条件判断,找到即结束循环
411.         }  
412. if(i==strLength)  
413. return npos;// 未找到,// 根据跳出的内层for的条件判断,找到即结束循环
414. return
415.     }  
416. int MyString::find_first_not_of(const MyString& str,size_t
417.     {  
418. if(NULL == str || index >=strLength)  
419. return
420. size_t
421. for(i=index;i<strLength;i++)  
422.         {  
423. for(;j<str.strLength;j++)  
424.             {  
425. if(p_str[i]==str[j])  
426. break;// 如果相等 本轮i就无效了,进行下一轮
427.             }  
428. if(j==str.strLength)  
429. break;// 根据跳出的内层for的条件判断,找到即结束循环
430.         }  
431. if(i==strLength)  
432. return npos;// 未找到,// 根据跳出的内层for的条件判断,找到即结束循环
433. return
434.     }  
435. int MyString::find_first_not_of(const char ch,size_t
436.     {  
437. if(NULL == ch || index >=strLength)  
438. return
439. size_t
440. for(i=index;i<strLength;i++)  
441.         {  
442. if(p_str[i]!=ch)// 跟上面的略微不同,找一个不等就可以了
443. break;  
444.         }  
445. if(i==strLength)  
446. return npos;// 未找到,// 根据跳出的内层for的条件判断,找到即结束循环
447. return
448.     }  
449. // swap  都得变得,所以非const
450. void
451.     {  
452.         lhs.strLength ^= rhs.strLength;  
453.         rhs.strLength ^= lhs.strLength;  
454.         lhs.strLength ^= rhs.strLength;  
455. char
456.         rhs.p_str = lhs.p_str;  
457.         lhs.p_str = p_tmp;  
458.     }  
459. // replace_all  这个东西还是不太好弄的啊,不是很理想
460. const char oldc,const char
461.     {  
462. if(NULL == oldc)  
463.         {  
464. return *(this);  
465.         }  
466. for(size_t
467.         {  
468. if(p_str[i] == oldc)  
469.             {  
470.                 p_str[i] = newc;  
471.             }  
472.         }  
473. return *(this);  
474.     }  
475. size_t index,size_t num1,size_t num2,const char
476.     {  
477.   
478.     }  
479. // find 函数
480. int MyString::find(const char* str,size_t
481.     {  
482.         assert(str!=NULL&&index<strLength);  
483. // kmp 中的getnext函数
484. size_t
485. size_t
486. size_t
487.         next[0] = npos;  
488.         j = 0;  
489.         k = npos;  
490. while(j<len)  
491.         {  
492. if(k==npos || str[j]==str[k])  
493.             {  
494.                 j++;  
495.                 k++;  
496.                 next[j] = k;  
497.             }  
498. else
499.                 k = next[k];  
500.         }  
501. // kmp 算法
502.         k = index;  
503.         j = 0;  
504. while(p_str[k]!='\0')  
505.         {  
506. if(j==0 || p_str[k]==str[j])  
507.             {  
508.                 k++;  
509.                 j++;  
510.             }  
511. else
512.             {  
513. // 消除指针回溯
514.             }  
515. if(str[j] == '\0')//匹配成功
516. return
517.         }  
518. return
519.     }  
520. int MyString::find(const MyString& str,size_t
521.     {  
522. //        if(this == &str)
523. //        {
524. //            MyString other(*this);
525. //            find(other,index);
526. //        }
527.         assert(NULL!=str && index<strLength);  
528. // kmp 中的getnext函数
529.   
530. size_t
531. size_t
532.         next[0] = npos;  
533.         j = 0;  
534.         k = npos;  
535. while(j<str.strLength)  
536.         {  
537. if(k==npos || str.p_str[j]==str.p_str[k])  
538.             {  
539.                 j++;  
540.                 k++;  
541.                 next[j] = k;  
542.             }  
543. else
544.                 k = next[k];  
545.         }  
546. int
547. for(i=1;i<=j;i++)  
548. ",";  
549. // kmp 算法
550.         k = index;  
551.         j = 0;  
552. while(p_str[k]!='\0')  
553.         {  
554. if(j==0 || p_str[k]==str.p_str[j])  
555.             {  
556.                 k++;  
557.                 j++;  
558.             }  
559. else
560.             {  
561. // 消除指针回溯
562.             }  
563. if(str.p_str[j] == '\0')//匹配成功,不知道为什么调用自身的str[]重载总是报错的
564. return
565.         }  
566. if(str.p_str[j] == '\0')// 同一个字符串
567. return
568. return
569.     }  
570. int MyString::find(const char ch,size_t
571.     {  
572.         assert(NULL!=ch && index<strLength);  
573. for(size_t
574.         {  
575. if(p_str[i] == ch)  
576. return
577.         }  
578. return
579.     }


(3)测试函数main.cpp

[cpp] view plain copy

1. #include "MyString.h"
2. #include <iostream>
3. using namespace
4.   
5. int
6. {  
7. int
8. int
9. int
10. char
11.     MyString s1;  
12. "hello");  
13. "HELLO";  
14. "***** welcome *****\n";  
15. "******* MADE BY zyp **********\n";  
16. "s1= " << s1 << "s2= " << s2 << "s3= "
17. "请输入一个长度小于100的字符串:例如world\n";  
18.     cin >> s1;  
19.     s1 = s1;  
20. //s1 = s1+s1;
21.     s1 += s1;  
22.     MyString s4(s1);  
23.     s4.append(s1);  
24.     s2.insert(2,s3);  
25.     s1.erase(4,4);  
26.     s1.assign(s2,1,7);  
27. "s1= " << s1 << "s2= " << s2 << "s3= " << s3 << "s4= "
28.     s2 = s4.substr(2,7);  
29. "s4[3]= " << s4[3] << s4.length() << (s1>=s2) << "s4.substr() "
30. "s1.find_first_of(beLE,2):" << s1.find_first_of("beLE",2) << ",s1.find_first_of(a,3):" << s1.find_first_of('a',3) << ",s1.find_first_of(s3,2):"
31. 'b');  
32.     s5 += s5;  
33. //s5.append(s5);// 不知道为什就是不能append
34. "s5 = " << s5 << "s5.find_first_not_of(aeHLEOl,2):" << s5.find_first_not_of("aeHLEOl",2) << "s5.find_first_not_of(aeHLEOl,0):" << s5.find_first_not_of("aeHLEOl") << endl;  
35. "s5.find_first_not_of(s1,2):" << s5.find_first_not_of(s1,2) << "s5.find_first_not_of(b,2):" << s5.find_first_not_of('b',2) << endl;  
36.     swap(s1,s5);  
37. 'a','J');  
38. "LLO");  
39. "," << s5 << "s5.find(LLO,0) " << s5.find("LLO",0) << "s5.find(s6,0) "
40.     cout << npos << endl;  
41. return
42. }



三:感悟

(1)耗时将近2天的实现了它,自己与其从中学到了很多,倒不如说是重新认识了string类;

(2)自己知道这个简单的string类,距离string源代码还差的很远很远;但是它帮助我更好的理解了string类,至少会简单的应用了。

(3)简单的实现了一下string类,参照的是STL源码,但是自己理解的还是不够深,难免有一些错误,请各位指教,万分感谢!

(4)下一步进军list