文章目录
1 字符串类的初步设计
1.1 历史遗留问题
- C语言不支持真正意义上的字符串。
- C语言用字符数组和一组函数实现字符串操作。
- C语言不支持自定义类型,因此无法获得字符串类型。
- 从C到C++的进化过程中引入了自定义类型,在C++中可以通过类完成字符串类型的定义。
1.2 字符串类的初步设计

类的声明如下:

实现时的注意事项:
- 无缝实现String对象与char*字符串的互操作。
- 操作符重载函数需要考虑是否支持const操作。
- 通过C语言中的字符串函数实现String的成员函数。
1.3 代码实现
String.h:
#ifndef LSTRING_H
#define LSTRING_H
#include "Object.h"
#include "Exception.h"
namespace LemonLib {
#define STR(str) (str ? str : "")
class String : public Object
{
protected:
char* m_str;
int m_length;
void init(const char* str);
public:
String();
String(const char* str);
String(char c);
String(const String& s);
String& operator = (const char* str);
String& operator = (const String& s);
String& operator = (char c);
bool operator == (const char* str) const;
bool operator == (const String& s) const;
bool operator != (const char* str) const;
bool operator != (const String& s) const;
bool operator > (const char* str) const;
bool operator > (const String& s) const;
bool operator >= (const char* str) const;
bool operator >= (const String& s) const;
bool operator < (const char* str) const;
bool operator < (const String& s) const;
bool operator <= (const char* str) const;
bool operator <= (const String& s) const;
String operator + (const char* str) const;
String operator + (const String& s) const;
String& operator += (const char* str);
String& operator += (const String& s);
int length() const;
const char* str() const;
~String();
};
}
#endif // STRING_H
String.cpp:
#include "LString.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace LemonLib {
void String::init(const char* str)
{
m_str = strdup(STR(str));
if (m_str != NULL)
{
m_length = strlen(m_str);
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "string init error, no enough memory");
}
}
String::String()
{
init("");
}
String::String(const char* str)
{
init(str);
}
String::String(char c)
{
char str[] = {c, '\0'};
init(str);
}
String::String(const String& s)
{
init(s.m_str);
}
String& String::operator = (char c)
{
char str[] = {c, '\0'};
return (*this = str);
}
String& String::operator = (const char* str)
{
if (m_str != str)
{
free(m_str);
init(str);
}
return *this;
}
String& String::operator = (const String& s)
{
return (*this = s.m_str);
}
int String::length() const
{
return m_length;
}
const char* String::str() const
{
return m_str;
}
bool String::operator == (const char* str) const
{
return strcmp(m_str, str) == 0;
}
bool String::operator == (const String& s) const
{
return (*this == s.m_str);
}
bool String::operator != (const char* str) const
{
return !(*this == str);
}
bool String::operator != (const String& s) const
{
return !(*this == s);
}
bool String::operator > (const char* str) const
{
return strcmp(m_str, STR(str)) > 0;
}
bool String::operator > (const String& s) const
{
return (*this > s.m_str);
}
bool String::operator >= (const char* str) const
{
return strcmp(m_str, STR(str)) >= 0;
}
bool String::operator >= (const String& s) const
{
return (*this >= s.m_str);
}
bool String::operator < (const char* str) const
{
return strcmp(m_str, str) < 0;
}
bool String::operator < (const String& s) const
{
return (*this < s.m_str);
}
bool String::operator <= (const char* str) const
{
return strcmp(m_str, STR(str)) <= 0;
}
bool String::operator <= (const String& s) const
{
return (*this <= s.m_str);
}
String String::operator + (const char* str) const
{
int len = m_length + strlen(STR(str));
String ret;
char* p = reinterpret_cast<char*>(malloc(len + 1));
if (p != NULL)
{
strcpy(p, m_str);
strcat(p, STR(str));
free(ret.m_str);
ret.m_str = p;
ret.m_length = len;
return ret;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "string operator + error, no enough memory");
}
}
String String::operator + (const String& s) const
{
return (*this + s.m_str);
}
String& String::operator += (const char* str)
{
return (*this = *this + str);
}
String& String::operator += (const String& s)
{
return (*this += s.m_str);
}
String::~String()
{
free(m_str);
}
}
2 字符串类功能的进一步实现
接下来主要实现如下函数:

2.1 重载数组访问操作符[]
函数声明:
char& operator [] (int i);
char operator [] (int i) const;
注意事项:
- 当i的取值不合法时,抛出异常:
- 合法范围:(0 <= i) && (i < m_length)
代码实现如下:
char& String::operator [] (int i)
{
if ((0 <= i) && (i < m_length))
{
return m_str[i];
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException, "string operator [] error, out index");
}
}
char String::operator [] (int i) const
{
return (const_cast<String&>(*this))[i];
}
2.2 判断是否以指定字符串开始或结束
函数声明:
bool startWith(const char* s) const;
bool startWith(const String& s) const;
bool endOf(const char* s) const;
bool endOf(const String& s) const;
示意图:

代码实现:
bool String::is_equal(const char* str1, const char* str2, int len) const
{
bool ret = true;
for (int i=0; i<len; i++)
{
if (str1[i] != str2[i])
{
ret = false;
break;
}
}
return ret;
}
bool String::startWith(const char* s) const
{
bool ret = (s != NULL);
if (ret)
{
int len = strlen(s);
ret = (len < m_length) && is_equal(m_str, s, len);
}
return ret;
}
bool String::startWith(const String& s) const
{
return startWith(s.m_str);
}
bool String::endOf(const char* s) const
{
bool ret = (s != NULL);
if (ret)
{
int len = strlen(s);
ret = (len < m_length) && is_equal(m_str + m_length - len, s, len);
}
return ret;
}
bool String::endOf(const String& s) const
{
return endOf(s.m_str);
}
2.3 在指定位置处插入字符串
函数声明:
String& insert(int i, const char* s);
String& insert(int i, const String& s);
示意图:

代码实现:
String& String::insert(int i, const char* s)
{
bool ret = (s != NULL);
if (ret)
{
if ((0 <= i) && (i <= m_length))
{
int len = strlen(s);
char* str = reinterpret_cast<char*>(malloc(m_length + len + 1));
if (str != NULL)
{
strncpy(str, m_str, i);
strncpy(str+i, s, len);
strncpy(str+i+len, m_str+i, m_length-i);
str[m_length+len] = '\0';
free(m_str);
m_str = str;
m_length = m_length + len + 1;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "string insert error, no enough memory");
}
}
}
return *this;
}
String& String::insert(int i, const String& s)
{
return insert(i, s.m_str);
}
2.4 去掉字符串两端的空白字符
函数声明:
String& trim();
示意图:

代码实现:
String& String::trim()
{
if (m_length > 0)
{
int begin = 0, end = m_length - 1;
while (m_str[begin] == ' ') begin++;
while (m_str[end] == ' ') end--;
if (begin == 0)
{
m_str[end + 1] = '\0';
m_length = end + 1;
}
else
{
for (int i=0, j=begin; j<=end; i++, j++)
{
m_str[i] = m_str[j];
}
m_str[end - begin + 1] = '\0';
m_length = end - begin + 1;
}
}
return *this;
}
本文详细介绍了C++中自定义字符串类的设计过程,包括使用字符数组和C语言字符串函数实现基本功能,如构造、赋值、比较等。此外,还讨论了如何进一步扩展功能,如重载数组访问操作符[],判断字符串是否以指定子串开始或结束,插入字符串以及去除两端空白字符的方法。这些实现有助于理解C++类的使用和面向对象编程思想。

被折叠的 条评论
为什么被折叠?



