字符串类——KMP算法的应用

1,字符串类中的新功能(本文代码已集成到字符串类——字符串类的创建(上)中,这里讲述函数实现原理):

 

      

2,子串查找(KMP 算法直接运用):

       1,int indexOf(const char* s) const;

       2,int indexOf(const String& s) const;

       3,子串查找成员函数的声明:

    int indexOf(const char* ) const;
    int indexOf(const String& s) const;

  4,子串查找成员函数的定义:

1 int String::indexOf(const char* s) const // 子串查找,返回下标
2 {
3     return kmp(m_str, s ? s : "");
4 }
5 
6 int String::indexOf(const String &s) const
7 {
8     return kmp(m_str, s.m_str);
9 }
 

3,在字符串中将指定的子串删除:

       1,String& remove(const char* s);

       2,String& remove(const String& s);

              1,根据 kmp 在目标字符串中查找子串的位置;

              2,通过子串位置和子串长度进行删除;

     3,删除指定字符串成员函数的声明:

     String& remove(int i, int len);
     String& remove(const char* s);
     String& remove(const String& s);

  4,删除指定字符串成员函数的定义:

 1 /* 删除下标 i 处长度为 len 的字符串 */
 2 String& String::remove(int i, int len)   // 和 insert() 返回的是相同的函数,还可以以字符串类继续访问,如查看删除后的字符串等
 3 {
 4     if( (0 <= i ) && (i < m_length) )
 5     {
 6         int n = i;
 7         int m = i + len; // 在 (n, m) 范围之内的字符都要删除掉
 8 
 9         while( (n < m) && (m < m_length) ) // 删除的字符串长度是不能大于当前的长度的,否则没有意义
10         {
11             m_str[n++] = m_str[m++];   // 这个赋值很经典
12         }
13 
14         m_str[n] = '\0'; //这里为什么是 n,因为n是不断增加的,直到 m 为等于 length
15         m_length = n;  // 不应该是 m_length - n 吗?
16 }
17 
18     return *this;
19 }
20 
21 String& String::remove(const char *s) // 删除子串
22 {
23     return remove(indexOf(s), s ? strlen(s) : 0);  
24 }
25 
26 String& String::remove(const String &s) // 删除子串
27 {
28     return remove(indexOf(s), s.length());
29 }

             

4,字符串的减法操作定义(operator - ):

       1,使用 remove 实现字符串间的减法操作;

              1,字符串自身不被修改;

              2,返回产生的新串;

 

  2,减法操作符重载的声明:

    String operator - (const String& s) const;
    String operator - (const char* s) const;
    String& operator -= (const String& s); 
    String& operator -= (const char* s);

  3,减法操作符重载的定义:

 1 String String::operator - (const String& s) const  // 字符串自身会被改变
 2 {
 3     return String(*this).remove(s);  // 直接调用构造函数产生一个新的临时字符串对象,值和当前字符串对象值相同,然后调用临时对象的remove() 函数将子串删除,最后将删除结果返回,但是当前的字符串没有被改变,因为是拷贝赋值
 4 }
 5 
 6 String String::operator - (const char* s) const  // 字符串自身会被改变
 7 {
 8     return String(*this).remove(s);  
 9 }
10 
11 String& String::operator -= (const String& s) // 字符串自生不会被改变
12 {
13     return remove(s);
14 }
15 
16 String& String::operator -= (const char* s)
17 {
18     return remove(s);
19 }

5,字符串中的子串替换:

       1,String& replace(const char* t, const char* s);

       2,String& replace(const String& t, const char* s);

       3,String& replace(cosnt char* t, const String& s);

       4,String& replace(const String& t, const String& s);

  5,子串替换成员函数的声明:

    String& replace(const char* t, const char* s);
    String& replace(const String& t, const char* s);
    String& replace(const char* t, const String& s);
    String& replace(const String& t, const String& s);

  6,子串替换成员函数的定义:

 1 /* 用 s 替换字符串中的 t */
 2 String& String::replace(const char* t, const char* s)
 3 {
 4     int index = indexOf(t); // 查找 t 的位置
 5 
 6     if( index >= 0 ) // t 存在于当前的字符串中
 7     {
 8         remove(t);  // 不要复制粘贴代码,要复用
 9         insert(index, s);
10    }
11 
12     return *this;
13 }
14 
15 String& String::replace(const String& t, const char* s)
16 {
17     return replace(t.m_str, s);
18 }
19 
20 String& String::replace(const char* t, const String& s)
21 {
22     return replace(t, s.m_str);
23 }
24 
25 String& String::replace(const String& t, const String& s)
26 {
27     return replace(t.m_str, s.m_str);
28 }

6,从字符串中创建子串:

       1,String sub(int i, int len) const;

              1,以 i 为起点去长度为 len 的子串;

              2,子串提取不会改变字符串本身的状态;

 

  2,从字符串中创建子串成员函数的声明:

    String sub(int i, int len) const; // 因为这里不会改变当前字符串状态,所以为 const 成员函数;

  3,从字符串中创建子串成员函数的定义:

 1 String String::sub(int i, int len) const  // 查找当前字符串中第 i 个位置长度为 len 的字符串
 2 {
 3    String ret;
 4 
 5     if( (0 <= i) && (i < m_length) )
 6     {
 7         if( len < 0 ) len = 0; // 当小于零时候,不可能,要归一化到 0
 8         if(len+i > m_length) len = m_length - i; // 只能够提取这么长的长度
 9 
10         char* str = reinterpret_cast<char*>(malloc(len + 1));
11 
12         if( str != NULL )
13         {
14             strncpy(str, m_str + i, len); // 从 m_str + i 位置拷贝 len 长度的字符串,这里 m_str 是字符串起始位置
15         }
16 
17         str[len] = '\0';
18         ret = str;  // 返回子串
19 
20         free(str);
21     }
22     else
23     {
24         THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invaid ...");
25    }
26 
27     return ret;
28 }

7,本节课测试代码:

 1 #include <iostream>
 2 #include "DTString.h"
 3 #include "malloc.h"
 4 #include <cstring>
 5 
 6 using namespace std;
 7 using namespace DTLib;
 8 
 9 int main()
10 {
11     String s = "ababax";
12    String s1 = s- "bax";
13 
14     cout << s.str() << endl;
15    cout << s1.str() << endl;
16 
17     s -= "ba";
18    s -= s;
19 
20    cout << "[" << s.str() << "]" << endl;
21 
22     String s2 = "ababax";
23    s2.replace("baba", "xyz");
24 
25    cout << s2.str() << endl;
26 
27     String s3 = "ababax";
28    String s4 = s3.sub(3, 2);
29 
30    cout << s4.str() << endl;
31 
32     return 0;
33 }

             

8,小结:

       1,字符串类是工程开发中必不可少的组件;

       2,字符串中应该包含常用字符串操作函数:

              1,增:insert,operator +,...;

                     1,当前字符串增加;

              2,删:remove,operator -,...;

                     1,当前字符串删除;

              3,查: indexOf,...

                     1,当前字符串查找;

              4,改:replace,...

                     1,当前字符串更改;

猜你喜欢

转载自www.cnblogs.com/dishengAndziyu/p/10923733.html