历史遗留问题

  • C 语言不支持真正意义上的字符串
  • C 语言用字符数组和一组函数实现字符串操作
  • C 语言不支持自定义类型,因此无法获得字符串类型

  • 从 C 到 C++ 的进化过程中引入了自定义类型
  • 在 C++ 中可以通过类完成字符串类型的定义

DTLib 中字符串类的定义

image.png

DTLib 中字符串类的实现

class String : public Object
{
public:
    String();
    String(const char *s);
    String(const String &s);
    int length() const;
    const char *str() const;
    
    /* 比较操作符重载函数 */
    /* 加法操作符重载函数 */
    /* 赋值操作符重载函数 */
    
    ~String();
protected:
    char *m_str;
    int m_length;
};

实现时的注意事项

  • 无缝实现 String 对象与 char *字符串的互操作
  • 操作符重载函数需要考虑是否支持 const 版本
  • 通过 C 语言中的字符串函数实现 String 的成员函数

编程实验

文件:DTString.h

#ifndef STRING_H
#define STRING_H

#include "Exception.h"
#include "Object.h"

#include <cstdint>

namespace DTLib
{

class String
{
public:
    String();
    String(const String &s);
    String(const char* s);

    size_t length() const;
    const char *str() const;

    bool operator == (const char *s) const;
    bool operator == (const String &s) const;
    bool operator != (const char *s) const;
    bool operator != (const String &s) const;
    bool operator > (const char *s) const;
    bool operator > (const String &s) const;
    bool operator < (const char *s) const;
    bool operator < (const String &s) const;
    bool operator >= (const char *s) const;
    bool operator >= (const String &s) const;
    bool operator <= (const char *s) const;
    bool operator <= (const String &s) const;

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

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

    ~String();

protected:
    char *m_str = nullptr;
    size_t m_length = 0;
};

}

#endif // STRING_H

文件:DTString.cpp

#include "DTString.h"

#include <cstring>
#include <cstdlib>

namespace DTLib
{

String::String() : String("")
{
}

String::String(const String &s) : String(s.m_str)
{
}

String::String(const char* s)
{
    char* str = strdup(s);

    if (str != nullptr)
    {
        m_str = str;

        m_length = strlen(str);
    }
    else
    {
        THROW_EXCEPTION(NoEnoughMemoryException, "No enogh memory to create str object ...");
    }
}

size_t String::length() const
{
    return m_length;
}

const char *String::str() const
{
    return m_str;
}


bool String::operator == (const char *s) const
{
    return (strcmp(m_str, s ? s : "") == 0);
}

bool String::operator == (const String &s) const
{
    return (strcmp(m_str, s.str()) == 0);
}

bool String::operator != (const char *s) const
{
    return (strcmp(m_str, s ? s : "") != 0);
}

bool String::operator != (const String &s) const
{
    return (strcmp(m_str, s.str()) != 0);
}

bool String::operator > (const char *s) const
{
    return (strcmp(m_str, s ? s : "") > 0);
}

bool String::operator > (const String &s) const
{
    return (strcmp(m_str, s.str()) > 0);
}

bool String::operator < (const char *s) const
{
    return (strcmp(m_str, s ? s : "") < 0);
}

bool String::operator < (const String &s) const
{
    return (strcmp(m_str, s.str()) < 0);
}

bool String::operator >= (const char *s) const
{
    return (strcmp(m_str, s ? s : "") >= 0);
}

bool String::operator >= (const String &s) const
{
    return (strcmp(m_str, s.str()) >= 0);
}

bool String::operator <= (const char *s) const
{
    return (strcmp(m_str, s ? s : "") <= 0);
}

bool String::operator <= (const String &s) const
{
    return (strcmp(m_str, s.str()) <= 0);
}

String String::operator + (const char *s) const
{
    String ret;

    size_t len = m_length + strlen(s ? s : "");

    char *str = reinterpret_cast<char*>(malloc(len + 1));

    if (str != nullptr)
    {
        strcpy(str, m_str);
        strcat(str, s ? s : "");

        free(ret.m_str);

        ret.m_str = str;
        ret.m_length = len;
    }
    else
    {
        THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create str object ...");
    }

    return ret;
}

String String::operator + (const String &s) const
{
    return (*this + s.str());
}

String &String::operator += (const char *s)
{
    return (*this = *this + s);
}

String &String::operator += (const String &s)
{
    return (*this = *this + s.str());
}

String &String::operator = (const char c)
{
    char s[] = {c, '\0'};

    return (*this = s);
}

String &String::operator = (const char *s)
{
    if (m_str != s)
    {
        char *str = strdup(s ? s : "");

        if (str != nullptr)
        {
            free(m_str);

            m_str = str;
            m_length = strlen(str);
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create str object ...");
        }
    }

    return *this;
}

String &String::operator = (const String &s)
{
    return (*this = s.str());
}

String::~String()
{
    free(m_str);
}

}

文件:main.cpp

#include <iostream>
#include "DTString.h"

using namespace std;
using namespace DTLib;

void test_1()
{
    cout << "test_1() begin ..." << endl;

    String s;

    s = "D.T.";

    cout << s.str() << endl;
    cout << s.length() << endl;
    cout << (s == "D") << endl;
    cout << (s > "CCC") << endl;

    s += " Software ";

    cout << s.str() << endl;
    cout << s.length() << endl;
    cout << (s == "D.T. Software " ) << endl;

    cout << "test_1 end ..." << endl;
}

void test_2()
{
    cout << "test_2() begin ..." << endl;

    String a[] = {"E", "D", "C", "B", "A"};
    String min = a[0];

    for (int i = 0; i < 5; ++i)
    {
        if (min > a[i])
        {
            min = a[i];
        }
    }

    cout << "min = " << min.str() << endl;

    cout << "test_2() end ..." << endl;
}

int main()
{
    test_1();

    cout << endl;

    test_2();

    return 0;
}

输出:

test_1() begin ...
D.T.
4
0
1
D.T. Software
14
1
test_1 end ...

test_2() begin ...
min = A
test_2() end ...

小结

  • C/C++ 语言本身不支持字符串类型
  • C 语言通过字符数组和一组函数支持字符串操作
  • C++ 通过自定义字符串类型支持字符串操作
  • 字符串类型通过 C 语言中的字符串函数实现

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


TianSong
734 声望138 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧