zoukankan      html  css  js  c++  java
  • 字符串类——字符串类的创建(下)

    1,上篇博文中的 String 创建功能很弱,不能满足开发的需要,本文为这个字符串类开发一系列函数(函数代码已经集成到“字符串类——字符串类的创建(上)”一文中,本节讲述实现原理),使其能够胜任一系列工程开发的需要;

       

    2,字符串类中的常用成员函数:

     

          

    3,重载数组访问操作符 []:

           1,char& operator [] (int i);

                  1,字符串对象应该能够像字符数组一样,通过每一个下标来访问每一个字符;

                  2,引用意味着可以被赋值,可以出现在赋值符号左边(此时是对象),给没有被 const 修饰的版本用;

           2,char operator [] (int i) const;

                  1,不能作为左值,所以不能返回引用对象;给 const 修饰的常对象版本使用;

           3,注意事项:

                  1,当 i 取值不合法时,抛出异常:

                         1,合法范围:(0 <= i) && (i < m_length);

      4,重载操作符的声明:

         char& operator [] (int i); 
         char operator [] (int i) const;  

      5,重载操作符的实现:

     1 char& String::operator [] (int i)
     2 {
     3     if( (0 <= i) && (i < m_length) )
     4     {
     5         return m_str[i];   // 封装;
     6     }
     7     else
     8     {
     9         THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
    10     }
    11 }
    12 
    13 char String::operator [] (int i) const
    14 {
    15     return (const_cast<String&>(*this))[i]; // 在当前版本当中对非 const 代码复用
    16 }

                        

    4,判断是否已指定字符串开始或结束:

     

            1,bool startWith(const char* s) const;

              2,bool startWith(const String& s) const;

              3,bool endOf(const char* s) const;

              4,bool endOf(const String& s) const;

              5,开始或结束成员函数的声明:

    1 /* 判断当前的字符对象是否以 s 开头,判断当前的字符对象是否以 s 结束 */
    2 bool startWith(const char* s) const;
    3 bool startWith(const String& s) const;
    4 bool endOf(const char* s) const;
    5 bool endOf(const String& s) const;

      6,开始或结束成员函数的定义:

     1 /* 比对函数,为 startWith() 和 endOf() 函数服务,前两个参数为字符数组的首地址,第三个参数是字符数组长度;长度范围内字符数组对应元素都相等,返回真; */
     2 bool String::equal(const char* l, const char* r, int len) const
     3 {
     4    bool ret = true;
     5 
     6     for(int i=0; i<len && ret; i++)  // 这里的 ret 看似没用,实则只要有元素不相等就停止循环、非常重要;
     7     {
     8         ret = ret && (l[i] == r[i]);  // 如果有一个位置的字符不相等,则结束比较,返回 false;
     9 }
    10 
    11     return ret;
    12 }
    13 
    14 /* 判断当前的字符对象是否以 s 开头 */
    15 bool String::startWith(const char* s) const
    16 {
    17    bool ret = (s != NULL);
    18 
    19     if( ret )
    20     {
    21         int len = strlen(s);
    22 
    23         ret = (len < m_length) && equal(m_str, s, len);  // 如果参数字符串 s 长度比当前字符串长度更长,直接返回 false;
    24    }
    25 
    26     return ret;
    27 }
    28 
    29 bool String::startWith(const String& s) const
    30 {
    31     return startWith(s.m_str); // 代码复用了上面的
    32 }
    33 
    34 bool String::endOf(const char* s) const  // s 这个字符串是否是以字符开始
    35 {
    36    bool ret = (s != NULL);
    37 
    38     if( ret )
    39     {
    40         int len = strlen(s);
    41         char* str = m_str + (m_length - len);  // 计算最后 n 个字符表示的字符串;
    42 
    43         ret = (len < m_length) && equal(str, s, len);  // 如果参数字符串 s 长度比当前字符串长度更长,直接返回 false;
    44    }
    45 
    46    return ret;
    47 }
    48 
    49 bool String::endOf(const String& s) const
    50 {
    51     return endOf(s.m_str);  // 代码复用了上面的
    52 }

    5,在指定位置插入字符串:

     

           1,String& insert(int i, const char* s);

           2,String& insert(int i, const String& s);

      3,插入字符串成员函数的声明:

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

      4,插入字符串成员函数的定义:

     1 /* 第 i 个位置插入字符串 s,返回字符串对象是为了实现链式操作 */
     2 String& String::insert(int i, const char* s)
     3 {
     4     if( (0 <= i) && (i <= m_length) )
     5     {
     6         if( (s != NULL) && (s[0] != '') )  // 不为空和空字符串;
     7         {
     8             int len = strlen(s);
     9             char* str = reinterpret_cast<char*>(malloc(m_length + len + 1));
    10 
    11             if( str != NULL )
    12             {
    13                 strncpy(str, m_str, i);  //当前字符串的前 i 个字符拷贝出来到 str
    14                 strncpy(str + i, s, len); //将参数字符串s全部拷贝到 str+i 上去
    15                 strncpy(str + i + len, m_str + i, m_length - i); // 将最后字符串拷贝出来
    16                 str[m_length + len] = '';  // 最后添加结束符
    17                 free(m_str);  // 释放当前字符串的堆空间
    18                 m_str = str;  // 使用申请出来的堆空间中的字符串;
    19                 m_length = m_length + len;
    20             }
    21             else
    22             {
    23                 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to insert String value ...");
    24             }
    25         }
    26     }
    27     else
    28     {
    29         THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");
    30    }
    31 
    32     return *this;
    33 }
    34 
    35 String& String::insert(int i, const String& s)
    36 {
    37     return insert(i, s.m_str);
    38 }

          

    6,去掉字符串两端的空白:

      1,String& trim();

      2,去掉字符串两端空白成员函数的声明:

          String& trim();

      3,去掉字符串两端空白成员函数的定义:

     1 String& String::trim()
     2 {
     3     int b = 0;
     4     int e = m_length - 1;
     5 
     6     while( m_str[b] == ' ' ) b++;  // 确定中间字符串开始位置;
     7    while( m_str[e] == ' ' ) e--;  // 确定中间字符窜结束位置;
     8 
     9     if( b == 0 )
    10     {
    11         m_str[e + 1] = '';  // 最开始没有空格的时候;
    12         m_length = e + 1;
    13     }
    14     else
    15     {
    16         for(int i=0, j=b; j<=e; i++, j++)
    17         {
    18             m_str[i] = m_str[j];  // 将当前的含有的非空字符挪到前面去;
    19         }
    20 
    21         m_str[e - b + 1] = '';  // 添加结束符
    22         m_length = e - b + 1;  // 合法的字符个数;
    23    }
    24 
    25     return *this;   // 实现链式调用
    26 }

    7,本节课测试代码:

     1 #include <iostream>
     2 #include "DTString.h"
     3 
     4 using namespace std;
     5 using namespace DTLib;
     6 
     7 int main()
     8 {
     9    String s = "D.T.Software";
    10 
    11     cout << s.startWith("D.T.") << endl;
    12     cout << s.endOf("Software") << endl;
    13     cout << s.startWith("abc") << endl;
    14    cout << s.endOf("111") << endl;
    15 
    16     for(int i=0; i<s.length(); i++)
    17     {
    18         cout << s[i] << endl;
    19    }
    20 
    21     String s1 = "";
    22     s1.insert(0, "D.T.");
    23    s1.insert(4, "Sofgware");
    24 
    25     for(int i=0; i<s.length(); i++)
    26     {
    27         cout << s[i] << endl;
    28    }
    29 
    30     cout << s1.str() << endl;
    31    String s2 = "   abc   ";
    32 
    33    cout << s2.trim().str() << endl;  // 第二个点用了链式操作;
    34 
    35     if( s2.trim().insert(0, "D.T.").endOf("abc") && s2.startWith("D.T.")) // 链式结构
    36     {
    37         cout << s2.str() << endl;
    38    }
    39 
    40     return 0;
    41 }

    8,在 const 函数中调用非 const 函数:

           1,要去掉 const 函数的 const 属性;

           2,给非 const 函数加上 const属性;

           3,给非 const 函数加上 mutable 属性;

  • 相关阅读:
    luogu P2472 [SCOI2007]蜥蜴 网络流 拆点
    luogu P2762 太空飞行计划问题 网络流24
    luogu P2774 方格取数问题 网络流24 最小割
    luogu P2766 最长不下降子序列问题 网络流24
    Codeforces Round #651 (Div. 2) E
    Codeforces Round #651 (Div. 2) D
    Codeforces Round #651 (Div. 2) C
    Codeforces Global Round 8 E
    Codeforces Global Round 8 D
    【最小生成树】Truck History POJ
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10923654.html
Copyright © 2011-2022 走看看