电子商务网站建设的好处有哪些,百度seo怎么查排名,白云做网站,第一接单网平台目录
引言
成员变量
1.基本框架
成员函数
1.构造函数和析构函数
2.拷贝构造函数
3.容量操作函数
3.1 有效长度和容量大小
3.2 容量操作
3.3 访问操作
(1)operator[]函数
(2)iterator迭代器
3.4 修改操作
(1)push_back()和append()
(2)operator函数 引言
在 C—…目录
引言
成员变量
1.基本框架
成员函数
1.构造函数和析构函数
2.拷贝构造函数
3.容量操作函数
3.1 有效长度和容量大小
3.2 容量操作
3.3 访问操作
(1)operator[]函数
(2)iterator迭代器
3.4 修改操作
(1)push_back()和append()
(2)operator函数 引言
在 C——string的了解和使用 中我们学习了string的一些基础用法。接下来我们可以试着模拟实现string。
在C中std::string是一个功能强大且广泛使用的类用于处理字符串。然而了解其内部实现原理对于深入理解C和编写高效代码至关重要。通过模拟实现一个简单的string类我们可以更好地理解字符串的存储、管理以及操作。这不仅有助于我们更好地使用std::string还能让我们在遇到特定需求时能够自定义字符串类来满足这些需求。
成员变量
1.基本框架
为了与STL库中的string区分开来我们要使用命名空间namespace进行封装。 char* _str指向字符数组的指针用于存储字符串的实际内容。 size_t _size表示字符串中有效字符的数量。 size_t _capacity表示字符数组的容量即可以存储的最大字符数量包括结尾的空字符\0。 namespace My_string
{class string {public:// ...private:char* _str;size_t _size;size_t _capacity;};
}
成员函数
老规矩我们在 string.h 中声明函数在 string.cpp 中实现函数的功能。
1.构造函数和析构函数
构造函数接受一个C风格字符串作为参数计算其长度分配足够的内存来存储该字符串及其结尾的空字符并复制字符串内容。
析构函数释放分配给字符串的内存并将指针设置为nullptr以避免悬挂指针问题。同时将_size和_capacity设置为0表示对象已销毁。
string.h
namespace My_string
{class string {public:string(const char* str);//构造函数~string(); //析构函数private:char* _str;size_t _size;size_t _capacity;};
}
string.cpp
#includestring.h
namespace My_string
{// 构造函数string::string(const char* str){_size strlen(str);_capacity _size;_str new char[_capacity 1]; // 1用于储存\0strcpy(_str, str);}// 析构函数string::~string(){delete[] _str;_str nullptr;_size _capacity 0;}
}
我们可以测试一下 通过调试观察一下
调用构造函数 调用析构函数 2.拷贝构造函数
拷贝构造函数接受一个string对象作为参数分配足够的内存来存储原对象的字符串内容并复制该内容。
这里提供了三种实现方式包括直接复制、使用临时对象进行深拷贝以及使用swap函数进行资源转移。
string.h:
string(const string str); //拷贝构造函数
string.cpp:
// 拷贝构造函数(1)
string::string(const string str)
{_str new char[str._capacity 1]; //额外多给一个空间用于存放/0strcpy(_str, str._str); //拷贝数据_capacity str._capacity; //设置容量_size str._size; //设置有效数据个数
}
我们在这里也有其他的方法可以实现拷贝构造
// 拷贝构造函数(2)
string::string(const string str)
{string tmp(str._str);std::swap(tmp._str, _str);std::swap(tmp._size, _size);std::swap(tmp._capacity, _capacity);
}
以上代码还可以接着简化
string::string(const string str)
{string tmp(str._str);swap(tmp); // 这里的swap我们接下来会定义
}
3.容量操作函数
3.1 有效长度和容量大小
我们先写这两个函数
size()和capacity()分别返回字符串的有效长度和字符数组的容量。
string.h: size_t size() const; // size()函数size_t capacity() const; // capacity()函数
string.cpp:
// size()函数
size_t string::size() const
{return _size;
}// capacity()函数
size_t string::capacity() const
{return _capacity;
}
3.2 容量操作
c_str()返回一个指向以空字符结尾的字符数组的指针该数组包含与string对象相同的字符序列。这允许将string对象与接受C风格字符串的函数一起使用。
empty()检查字符串是否为空即长度为0。
erase()删除字符串中指定位置的字符或子字符串。
string.h
const char* c_str() const; // c_str()函数
bool empty() const; // empty()函数
void erase(size_t pos 0, size_t len npos); // erase()函数
string.cpp:
// c_str()函数
const char* string::c_str() const
{return _str;
}
// empty()函数
bool string::empty() const
{return _size 0;
}
// erase()函数
void string::erase(size_t pos,size_t len)
{assert(pos _size); if (len npos || len _size - pos){_str[pos] \0; // 位置pos置为\0_size pos; // 有效元素个数为pos个}else // len小于后面的字符个数{// 将后面的字符拷贝到pos位置strcpy(_str pos, _str pos len);_size - len; // 更新有效元素}
}
接下来再来实现扩容函数reserve()和resize()
reserve()增加字符数组的容量以确保可以存储至少n个字符。如果当前容量不足则分配新的内存并复制现有内容。
resize()改变字符串的大小。如果新大小大于当前大小则添加新字符默认为\0如果新大小小于当前大小则删除多余的字符。
string.h:
// 预留空间
void reserve(size_t n);
// resize()函数
void resize(size_t n, char ch \0);
string.cpp:
// 预留空间
void string::reserve(size_t n)
{if (n _capacity){char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;}
}
// resize()函数
void string::resize(size_t n, char ch)
{if (n _size){if (n _capacity){reserve(n);}// 使用 memset 函数将字符 ch // 填充到新添加的空间中memset(_str _size, ch, n - _size);}_size n;_str[n] \0;
}
3.3 访问操作
(1)operator[]函数
operator[]函数的功能返回pos位置的字符
string.h:
// 非const版本
char operator[](size_t pos); //operator[]函数
// const版本
const char operator[](size_t pos)const;
string.cpp:
// operator[]函数
char string::operator[](size_t pos)
{assert(pos _size);return _str[pos];
}
// const版本
const char string::operator[](size_t pos)const
{assert(pos _size);return _str[pos];
}
来个简单的代码测试一下 (2)iterator迭代器
迭代器提供begin()和end()函数来返回指向字符串开头和结尾的迭代器。这里简化了迭代器的实现将其视为指向字符数组的指针。然而在实际应用中迭代器通常是一个更复杂的类提供了更多的功能和安全性检查。
string.h:
//const版本的iterator
const_iterator begin() const; //提供const_iterator begin()函数
const_iterator end() const; //提供const_iterator end()函数//非const版本的iterator
iterator begin(); //提供iterator begin()函数
iterator end(); //提供iterator end()函数
string.cpp:
string::iterator string::begin()
{return _str;
}
string::iterator string::end()
{return _str _size;
}
string::const_iterator string::begin() const
{return _str;
}
string::const_iterator string::end() const
{return _str _size;
}
还是老样子我们使用一个简单的函数测试一下
void test3()
{My_string::string str(hello);for (auto i : str){cout i ;}cout endl;My_string::string::iterator it1 str.begin();while (it1 ! str.end()){cout *it1 ;it1;}cout endl;My_string::string::iterator it2 str.end();if (it2 ! str.begin()) { // 检查避免直接解引用 end() --it2; // 先移动到一个有效的位置 while (it2 ! str.begin()){std::cout *it2 ;--it2;}std::cout *it2 ; // 输出最后一个字符begin() 之前的字符 }std::cout std::endl;
}
输出结果为 3.4 修改操作
(1)push_back()和append()
string.h:
// 尾插一个字符
void push_back(char ch);
// 尾插一个字符串
void append(const char* str);
string.cpp:
//尾插一个字符
void string::push_back(char ch)
{if (_capacity _size){size_t newcapacity _capacity 0 ? 4 : 2 * _capacity;reserve(newcapacity);}_str[_size] ch;_str[_size 1] \0;_size;
}//尾插一个字符串
void string::append(const char* str)
{size_t len strlen(str);if (_size len _capacity) {reserve(_size len);}strcpy(_str_size, str);_size len;
}
(2)operator函数
我们可以借助上面两个函数实现operator函数。
string.h:
//operator函数可以构成重载,函数名相同,参数不同
string operator(char ch); // 字符相加
string operator (const char* str); // 字符串相加string.cpp:
string string::operator(char ch)
{// 调用push_back()函数push_back(ch); return *this;
}
string string::operator(const char* str)
{append(str);return *this;
}
来测试一下 operator函数返回的是对象本身。
内置类型的运算符返回值的副本。
自定义类型的运算符通常返回对象的引用即*this以支持链式操作和避免复制。
———————————————————————————————————————————
以上为string模拟实现的第一篇
求点赞收藏评论关注
感谢各位大佬
第二篇链接C——string的模拟实现下