string底层是一个是字符数组
为了跟库里的string区别,所以定义一个命名空间将类string包含
一、构造
1.构造函数
注意:将char*传给const char*是范围缩小,因此只能1:1构造一个
strlen遇到nullptr解引用会报错,因此缺省参数只能设置为" "
string(const char* str = "")
:_size(strlen(str))
{
if (_size == 0)
{
_capacity = 3;
}
else
{
_capacity = _size;
}
_str = new char[_capacity + 1];
strcpy(_str, str);
}
2.拷贝构造
深拷贝:重新开辟一个空间
浅拷贝(值拷贝):拷贝一个指针,指向同一片空间
string(const string& s)
:_size(s._size)
,_capacity(s._capacity)
{
_str = new char[_capacity + 1];
strcpy(_str, s._str);
}
3.析构
内置类型,调用默认成员函数,自定义类型调用默认构造
~string()
{
if (_str != NULL)
{
delete[] _str;
_str = NULL;
}
_size = 0;
_capacity = 0;
}
4.赋值
赋值运算符也是默认成员函数,如果不写会进行浅拷贝/值拷贝
string& operator=(const string& s)
{
_size = s._size;
_capacity = s._capacity;
delete[] _str;
_str = new char[_capacity+1];
strcpy(_str, s._str);
return *this;
}
二、迭代器
使用typedef 将用iterator代替char*
1.begin
iterator begin()
{
return _str;
}
2.end
iterator end()
{
return _str + _size;
}
三、修改
1.push_back
void push_back(char c)
{
if (_size + 1 > _capacity)
{
reserve(_size + 1);
char* tmp = new char[_capacity + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
}
_str[_size] = c;
_size++;
_str[_size] = '\0';
}
2.+=
复用尾插
string& operator+=(char c)
{
push_back(c);
return *this;
}
3.append
通过reserve类似扩容的操作,扩大了字符串长度的空间,并且在原字符串‘\0’的位置上拷贝str字符串
void append(const char* str)
{
size_t len = strlen(str);
if (len + _size > _capacity)
{
reserve(len + _size);
char* tmp = new char[_capacity + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
}
strcpy(_str + _size, str);
_size += len;
}
4.clear
void clear()
{
_size = 0;
_str[0] = '\0';
}
5.swap
void swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
void swap(string& s)
{
bit::swap<char*>(_str, s._str);
bit::swap<size_t>(_size, s._size);
bit::swap<size_t>(_capacity, s._capacity);
}
6.c_str
const char* c_str()const
{
const char* tmp = _str;
return tmp;
}
四、容量
1.size
size_t size()const
{
return _size;
}
2.capacity
size_t capacity()const
{
return _capacity;
}
3.empty
bool empty()const
{
if (_size == 0)
{
return true;
}
else
{
return false;
}
}
4.resize
分三种情况
n<_size 删除数据
_size<n<_capacity 剩余空间初始化
n>_capacity 扩容+初始化
void resize(size_t n, char c = '\0')
{
if (n <= _size)
{
_size = n;
_str[n] = '\0';
}
else
{
reserve(n);
size_t i = _size;
while (i < n)
{
_str[i] = c;
i++;
}
_size = n;
_str[_size] = '\0';
}
}
5.reserve
为防止new失败,所以使用临时变量tmp指向new出来的空间,若new成功,释放旧空间,并将—_str指向新的空间
void reserve(size_t n)
{
if (n > _capacity)
{
_capacity = n;
char* tmp = new char[_capacity + 1];
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
}
}
五、访问
1.[ ]
char& operator[](size_t index)
{
return _str[index];
}
const char& operator[](size_t index)const
{
return _str[index];
}
2."<,<=,>,>=,==,!="
通过strcmp,比较字符串从头开始字符的ASCII值,再通过复用来实现剩下的
const只能调用const,非const既可以调用非const,也可以调用const
bool operator<(const string& s)
{
return (*this >= s);
}
bool operator<=(const string& s)
{
return !(*this > s);
}
bool operator>(const string& s)
{
return (strcmp(_str, s._str) > 0);
}
bool operator>=(const string& s)
{
return (*this == s || *this > s);
}
bool operator==(const string& s)
{
return strcmp(_str, s._str) == 0;
}
bool operator!=(const string& s)
{
return !(*this==s);
}
3.find
size_t find(char c, size_t pos = 0)const
{
while (pos < _size)
{
if (_str[pos] == c)
{
return pos;
}
pos++;
}
return npos;
}
size_t find(const char* s, size_t pos = 0)const
{
const char* p = strstr(_str, s);
if (p != nullptr)
{
return _str - p;
}
return npos;
}
4.insert
注意size_t类型变量没有负数
string& insert(size_t pos, char c)
{
if (_size + 1 > _capacity)
{
reserve(_size + 1);
char* tmp = new char[_capacity + 1];
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
}
size_t end = _size;
while (end >= pos)
{
_str[end + 1] = _str[end];;
end--;
}
_str[pos] = c;
_size++;
_str[_size] = '\0';
return *this;
}
string& insert(size_t pos, const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
char* tmp = new char[_capacity + 1];
strcpy(tmp, _str);
delete[]_str;
_str = tmp;
}
size_t end = _size;
while (end >= pos)
{
_str[end + len] = _str[end];
end--;
}
strncpy(_str + pos, str, len);
_size += len;
return *this;
}
5.erase
pos位置开始删除len个数据
string& erase(size_t pos, size_t len)
{
if (len == npos && len + pos > _size)
{
_str[pos] = '\0';
}
else
{
while (pos+len<_size)
{
_str[pos] = _str[pos + len];
pos++;
}
_size -= len;
_str[_size] = '\0';
}
return *this;
}
6.流插入<<
ostream& operator<<(ostream& _cout, const bit::string& s)
{
for (int i = 0; i < s._size; i++)
{
_cout << s[i] << "";
}
_cout << endl;
return _cout;
}
7.流提取>>
输入多个值,C++规定 空格/换行是值与值之间的区分
istream& operator>>(istream& _cin, bit::string& s)
{
s.clear();
char ch = _cin.get();
char buf[128];
int index = 0;
while (ch != ' ' && ch != '\n')
{
buf[index++] = ch;
if (index == 127)
{
buf[index] = '\0';
s += buf;
index = 0;
}
ch = _cin.get();
}
if (index != 0)
{
s += buf;
}
return _cin;
}