我们来模拟实现一下string类的常用接口啊,不是常用类的就不模拟实现了哦,没有见过,估计也半天想不出来啊。
- 我们看一下string类的常见接口吧
函数名称 | 功能说明
string() | 构造string类空字符串
string(const char* s) | 构造字符串
string(size_t n char c) | string类包含n个字符串
string(const string&s) | 用s中前n个字符构造新的string类对象
void TestString() {
string s1; // 构造空的string类对象s1
string s2("hello bit"); // 用C格式字符串构造string类对象s2
string s3(10, 'a'); // 用10个字符'a'构造string类对象s3
string s4(s2); // 拷贝构造s4
string s5 (s3, 5); //用s3中前5个字符构造string对象s5
函数名称 |功能说明
size_t size() | const 返回字符串有效字符长度
size_t length() | const 返回字符串有效字符长度
size_t capacity ( ) | const 返回空间总大小
bool empty ( ) const | 检测字符串释放为空串,是返回true,否则返回false
void clear() | 清空有效字符
void resize ( size_t n, char c ) | 将有效字符的个数该成n个,多出的空间用字符c填充
void resize ( size_t n ) | 将有效字符的个数改成n个,多出的空间用0填充
void reserve ( size_t res_arg=0 ) | 为字符串预留空间
// size/length/clear/resize
void TestString1() {
// 注意:string类对象支持直接用cin和cout进行输入和输出
string s("hello, bit!!!");
cout<<s.length();
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s <<endl;
// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
s.clear();
cout << s.size() << endl;
cout << s.capacity() << endl;
// 将s中有效字符个数增加到10个,多出位置用'a'进行填充
// “aaaaaaaaaa”
s.resize(10, 'a');
cout << s.size() << endl;
cout << s.capacity() << endl;
// 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充
// "aaaaaaaaaa\0\0\0\0\0"
// 注意此时s中有效字符个数已经增加到15个
s.resize(15);
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
// 将s中有效字符个数缩小到5个 s.resize(5); cout << s.size() << endl;
cout << s.capacity() << endl;
下面一些操作修改字符串接口就不显示了,这些大意多看看一些基本书籍应该都有一些描述,我只把接口列出来啊
| 函数名称 | 功能说明 |
char& operator[] ( size_t pos ) | 返回pos位置的字符,const string类对象调用
const char& operator[] | ( size_t pos ) const
返回pos位置的字符,非const string类对象调 用
void push_back(char c) | 在字符串后尾插字符c |
string& append (const char* s); | 在字符串后追加一个字符串 |
string& operator+=(const string& str)
| 在字符串后追加字符串str
string& operator+=(const char* s) | 在字符串后追加C个数字符串
string& operator+=(char c) | 在字符串后追加字符c
const char* c_str( )const | 返回C格式字符串
size_t find (char c, size_t pos = 0)const
| 从字符串pos位置开始往后找字符c,返回该字符在 字符串中的位置
size_t rfind(char c, size_t pos = npos)
| 从字符串pos位置开始往前找字符c,返回该字符在 字符串中的位置
string substr(size_t pos = 0, size_t n = npos)const
| 在str中从pos位置开始,截取n个字符,然后将其 返回
好了来演示一下代码吧!
namespace HWang
{
class String
{
public:
typedef char* Iterator;
public:
String(const char* str = "")
{
if (nullptr == str)
{
assert(false);
return;
}
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
String(const String& s)
:_str(new char[s._capacity + 1])
, _size(s._size)
, _capacity(s._capacity){
strcpy(_str, s._str);
}
String& operator = (const String& s)
{
if (this != &s)
{
char* pstr = new char[s._capacity + 1];
strcpy(pstr, s._str);
delete[]_str;
_str = pstr;
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
~String()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
Iterator Begin()
{
return _str;
}
Iterator End()
{
return _str + _size;
}
void PushBack(char c)
{
if (_size == _capacity)
Reserve(_capacity * 2);
_str[_size++] = c;
_str[_size] = '\0';
}
void Append(size_t n, char c)
{
for (size_t i = 0; i < n; ++i)
PushBack(c);
}
String& operator+=(char c)
{
PushBack(c);
return *this;
}
void Append(const char* str);
String& operator+=(const char* str);
void Clear()
{
_size = 0;
_str[_size] = '\n';
}
void Swap(String& s)
{
swap(_str, s._str);
swap(_size, s._size);
swap(_capacity, s._capacity);
}
const char* C_str()const
{
return _str;
}
size_t Size()const
{
return _size;
}
size_t Capacity()const
{
return _capacity;
}
bool Empty() const
{
return 0 == _size;
}
void Resize(size_t newSize, char c = char())
{
if (newSize > _size){
if (newSize > _capacity)
{
Reserve(newSize);
}
memset(_str + _size, c, newSize - _size);
}
_size = newSize;
_str[newSize] = '\0';
}
void Reserve(size_t newCapacity)
{
if (newCapacity > _capacity)
{
char* str = new char[newCapacity + 1];
strcpy(str, _str);
_str = str;
_capacity = newCapacity;
}
}
char& operator[](size_t index)
{
assert(index < _size);
return _str[index];
}
int Find(char c, size_t pos = 0)
{
for (size_t i = pos; i < _size; ++i)
{
if (c == _str[i])
return i;
}
return npos;
}
int rFind(char c)
{
for (int i = _size - 1; i > = 0; --i)
{
if (c == _str[i])
return i;
}
return npos;
}
String StrSub(size_t pos, size_t size)
{
int len = strlen(_str + pos);
if (size > len)
size = len;
return String(_str + pos, size);
}
private:
friend ostream& operator<<(ostream& _cout, const bit::String& s);
private:
char* _str;
size_t _capacity;
size_t _size;
const int String::npos = -1;
};
}
ostream& bit::operator<< (ostream& _cout, const bit::String& s){
cout << s._str;
return _cout;
}
void TestHwangString1() {
bit::String s1;
bit::String s2("hello bit");
bit::String s3(s2);
s1 = s3;
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
}
void TestHWangString2() {
bit::String s1("hello");
s1.PushBack(' ');
s1.PushBack('b');
s1.Append(1, 'i');
s1 += 't';
cout << s1 << endl;
cout << s1.Size() << endl;
cout << s1.Capacity() << endl;
// 利用迭代器打印string中的元素
auto it = s1.Begin();
while (it != s1.End())
{
cout << *it++;
}
cout << endl;
bit::String s2("hello world!!!");
s1.Swap(s2);
cout << s1 << endl;
cout << s2 << endl;
}
void TestHWangString3() {
bit::String s("hello");
cout << s << endl;
cout << s.Size() << endl;
cout << s.Capacity() << endl;
s.Resize(10, 'a');
cout << s << endl;
cout << s.Size() << endl;
cout << s.Capacity() << endl;
s.Resize(20);
cout << s << endl;
cout << s.Size() << endl;
cout << s.Capacity() << endl;
s.Resize(5);
cout << s << endl;
cout << s.Size() << endl;
cout << s.Capacity() << endl;
s.Reserve(50);
cout << s << endl;
cout << s.Size() << endl;
cout << s.Capacity() << endl;
}
int main()
{
TestHwangString1();
TestHwangString2();
TestHwangString3();
}
我们的基本思想是把string换算成我们的c语言字符串,先就算出来string类的size大小,然后在根据实际情况完成string类空间容量的分配,超过空间模拟vs或者c++的增容方式重新增容,没有超过则不用。计算寻找字符串中某一个位置,或者修改某一个位置时候,就需要用到c++里面的operator赋值运算符的重载主要思想也就围绕这两点吧,其他的我们一时间想不起来,一个也就这些,string模拟实现相比之下逻辑方面其实不是很绕,稍微想一下主要知道这个接口怎么用,应该用简简单单方法都可以实现的。