字符串类的创建(上)
C语言中,其实是使用字符数组来模拟字符串的,如果一个字符数组以\0为结束符的话,那么这个字符数组就是C语言中合法的字符串了。一个字符数组是不是字符串的标准就是是否以\0来作为结束标志。
在C语言中是找不到一个数据类型来单独描述字符串的,要么就通过字符数组,要么就通过char*指针。
为了兼容C语言,C++在原生类型系统中还是没有包含字符串类型,那么C++中是如何支持字符串类型的呢?它是通过库实现的,比如说,与C++同时发布的stl标准库,stl中就有String这个类,该类就是官方承认的C++里面的字符串类型了。但是这么做还是有问题的,比如说在某个实际的工程开发中,也许是不能使用stl标准库的,使用的是另一种库,比如说使用的是Qt,Qt中也提供了一个字符串类型,叫做QString。还有可能使用的是MFC,它提供了CString类。也就是说,只要使用了C++中的一个库,那么库中必然会提供字符串类型出来。这就是C++世界中字符串类型了,可以说没有统一的字符串类型,都是库提供的字符串类型。
我们现在正写一个库,因此我们也必须在DTLib中实现字符串类。所有厂商设计的字符串类的设计基本上是一样的。
其实就是使用面向对象的技术,对C语言中的字符串函数进行封装。
字符串类的实现:String.h String.cpp
String.h
#ifndef DTSTRING_H
#define DTSTRING_H
#include "Object.h"
namespace DTLib
{
class String : public Object
{
protected:
char* m_str;
int m_length;
void init(const char* s);
public:
String();
String(char c);
String(const char* s);
String(const String& s);
int length() const;
const char* str() const; //用于进行和传统的C语言字符串函数进行互操作的函数
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;
bool operator >=(const char* s) const;
String operator +(const String& s) const;
String operator +(const char* s) const;
String& operator +=(const String& s) ;
String& operator +=(const char* s) ;
String& operator = (const String& s);
String& operator = (const char* s);
String& operator = (char c);
~String();
};
}
#endif // DTSTRING_H
String.cpp
#include "DTString.h"
#include <cstring>
#include <cstdlib>
#include "Exception.h"
namespace DTLib
{
void String::init(const char* s)
{
m_str = strdup(s);
if(m_str)
{
m_length = strlen(m_str);
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"no enough memory to create string object...");
}
}
String ::String()
{
init("");
}
String::String(const char* s)
{
init(s ? s : ""); //为了防止空指针的问题,如果是以空指针来创建一个对象,就将空指针转换成一个字符串
}
String::String(const String& s)
{
init(s.m_str);
}
String::String(const char c)
{
//以一个字符作为参数,来创建一个字符串对象。因为在C语言中是以\0作为字符串的结束标志
char s[] = {c, '\0'};
init(s);
}
int String::length() const
{
return m_length;
}
const char* String::str()const
{
return m_str;
}
bool String::operator ==(const String& s) const
{
return(strcmp(m_str,s.m_str) == 0);
}
bool String::operator ==(const char* s) const
{
return(strcmp(m_str,s ? s :" ") == 0);
}
bool String::operator !=(const String& s) const
{
return !(*this == s);
}
bool String::operator !=(const char* s) const
{
return !(*this == s);
}
bool String::operator >(const String& s) const
{
return (strcmp(m_str,s.m_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.m_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.m_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.m_str) <= 0);
}
bool String::operator <=(const char* s) const
{
return (strcmp(m_str,s ? s : "") <= 0);
}
String String::operator +(const String& s) const
{
return (*this + s.m_str);
}
String String::operator +(const char* s) const
{
String ret;
int len = m_length + strlen(s ? s : "");
char* str = reinterpret_cast<char*>(malloc(len + 1));
if(str)
{
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 enough memory to allocate...");
}
return ret;
}
String& String::operator +=(const String& s)
{
return (*this = *this + s.m_str); //在这里使用了赋值操作符,因此还需要实现赋值操作符的重载
}
String& String::operator +=(const char* s)
{
return (*this = *this + (s ? s : ""));
}
String& String::operator = (const String& s)
{
return (*this = s.m_str);
}
String& String::operator = (const char* s)
{
if(m_str != s)
{
char* str = strdup(s);
if(str)
{
free(m_str);
m_str = str;
m_length = strlen(m_str);
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"no enough memeory to create new value...");
}
}
return *this;
}
String& String::operator = (char c)
{
char s[] = {c, '\0'};
return (*this = s);
}
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= 'J';
cout << s.str() << endl;
cout << s.length() << endl;
cout << (s == 'J') << endl;
cout << (s > 'C') << endl;
s += " jackson is strong ";
cout << s.str() << endl;
cout << s.length() << endl;
cout << (s == "J jackson is strong ") << 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 << "the most smaller is " << min.str() << endl;
cout << "test_2 end..." << endl;
}
int main()
{
test_1();
test_2();
return 0;
}
打印结果符合预期,因此实现的字符串类实现了基本的功能。