目录
1. 什么是STL
2. STL库的六大组件
3. 标准库中的string类
3.3 对比size和capacity接口函数
size代表字符串有效长度
capacity代表字符串的实际长度
3.4 reserve,resize函数的使用
3.5 string类的访问和遍历
4. string的修改操作
5. insert和earse函数
6. 深浅拷贝问题
7. 代码总结
总结:
以上就是今天要讲的内容,提供了非常全面的代码和讲解以及重要的深浅拷贝的问题,感谢各位观看,我们下期再见
1. 什么是STL
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
2. STL库的六大组件
3. 标准库中的string类
- string是表示字符串的字符串类
3.1 string类对象的常见构造
3.2 string类对象的容量操作
3.3 对比size和capacity接口函数
-
size代表字符串有效长度
-
capacity代表字符串的实际长度
3.4 reserve,resize函数的使用
- reserve此函数只改变capacity不改变size
resize函数:
- 此函数既能改变size也能改变capacity
- 在不初始化的情况下直接将size扩为n
- 将size扩为n并且用n个字符c初始化
3.5 string类的访问和遍历
而这里就需要我们迭代器iterator
本质就是一个指针
- 函数begin返回第一个位置的迭代器
- 函数end返回size位置的迭代器
这里我们补充一下这里的operator[]只能是下标访问,因为string就像是一个数组
rbegin和rend就是一个反向迭代器,从字符串的最后一个字母开始返回,直到返回到第一个字母为止
4. string的修改操作
operator+=这个接口函数就是+=一个字符或者字符串,并且返回
c_str函数返回字符串从\0结尾的字符串
但是c++中的字符串不一定以\0结尾
5. insert和earse函数
- insert函数可以在pos位置插入
- 一个字符或者一个字符串或者
- 一个string类,甚至还可以指定插入
- erase函数可以删除从pos位置
- 往后len个字符,若erase函数全用
- 缺省参数,则从0位置删除npos个
- 也就是将字符全部删除完
6. 深浅拷贝问题
这里面我们必须涉及一个问题就是深浅拷贝的问题
- 深拷贝:本质,就是防止内存公共用一个内存
- 浅拷贝:公用一个内存块;一个数据修改会影响另一个数据
说明:上述string类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝。
7. 代码总结
namespace bit
{
class string
{
public:
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
const_iterator begin() const
{
return _str;
}
const_iterator end() const
{
return _str + _size;
}
string(const char* str = "")
:_size(strlen(str))
, _capacity(_size)
{
_str = new char[_capacity + 1];
strcpy(_str, str);
}
// 传统写法
// s2(s1)
//string(const string& s)
//{
// _str = new char[s._capacity+1];
// strcpy(_str, s._str);
// _size = s._size;
// _capacity = s._capacity;
//}
s2 = s3
//string& operator=(const string& s)
//{
// if (this != &s)
// {
// char* tmp = new char[s._capacity + 1];
// strcpy(tmp, s._str);
// delete[] _str;
// _str = tmp;
// _size = s._size;
// _capacity = s._capacity;
// }
// return *this;
//}
void swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
// s2(s1)
string(const string& s)
:_str(nullptr)
,_size(0)
,_capacity(0)
{
string tmp(s._str);
swap(tmp);
}
// s2 = s3
//string& operator=(const string& s)
//{
// if (this != &s)
// {
// string tmp(s);
// //this->swap(tmp);
// swap(tmp);
// }
// return *this;
//}
// s2 = s3
string& operator=(string tmp)
{
swap(tmp);
return *this;
}
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos) const
{
assert(pos < _size);
return _str[pos];
}
size_t capacity() const
{
return _capacity;
}
size_t size() const
{
return _size;
}
const char* c_str() const
{
return _str;
}
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
void resize(size_t n, char ch = '\0')
{
if (n <= _size)
{
_str[n] = '\0';
_size = n;
}
else
{
reserve(n);
while (_size < n)
{
_str[_size] = ch;
++_size;
}
_str[_size] = '\0';
}
}
size_t find(char ch, size_t pos = 0)
{
for (size_t i = pos; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
return npos;
}
size_t find(const char* sub, size_t pos = 0)
{
const char* p = strstr(_str + pos, sub);
if (p)
{
return p - _str;
}
else
{
return npos;
}
}
string substr(size_t pos, size_t len = npos)
{
string s;
size_t end = pos + len;
if (len == npos || pos + len >= _size) // 有多少取多少
{
len = _size - pos;
end = _size;
}
s.reserve(len);
for (size_t i = pos; i < end; i++)
{
s += _str[i];
}
return s;
}
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
void append(const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
strcpy(_str + _size, str);
_size += len;
}
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
string& operator+=(const char* str)
{
append(str);
return *this;
}
// insert(0, 'x')
void insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
// 17:17
size_t end = _size + 1;
while (end > pos)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
_size++;
}
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
// 挪动数据
int end = _size;
while (end >= (int)pos)
{
_str[end + len] = _str[end];
--end;
}
strncpy(_str + pos, str, len);
_size += len;
}
void erase(size_t pos, size_t len = npos)
{
assert(pos < _size);
if (len == npos || pos +len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
size_t begin = pos + len;
while (begin <= _size)
{
_str[begin-len] = _str[begin];
++begin;
}
_size -= len;
}
}
bool operator<(const string& s) const
{
return strcmp(_str, s._str) < 0;
}
bool operator==(const string& s) const
{
return strcmp(_str, s._str) == 0;
}
bool operator<=(const string& s) const
{
return *this < s || *this == s;
}
bool operator>(const string& s) const
{
return !(*this <= s);
}
bool operator>=(const string& s) const
{
return !(*this < s);
}
bool operator!=(const string& s) const
{
return !(*this == s);
}
void clear()
{
_str[0] = '\0';
_size = 0;
}
private:
char* _str;
size_t _size;
size_t _capacity;
//const static size_t npos = -1; // 特例
//const static double npos = 1.1; // 不支持
public:
const static size_t npos;
};
const size_t string::npos = -1;
ostream& operator<<(ostream& out, const string& s)
{
for (auto ch : s)
out << ch;
return out;
}
istream& operator>>(istream& in, string& s)
{
s.clear();
//s.reserve(128);
char buff[129];
size_t i = 0;
char ch;
ch = in.get();
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
if (i == 128)
{
buff[i] = '\0';
s += buff;
i = 0;
}
//s += ch;
ch = in.get();
}
if (i != 0)
{
buff[i] = '\0';
s += buff;
}
return in;
}
}