string的构造与遍历
构造函数与析构函数
-
构造函数
string(const char* str = "")//常量字符串默认结尾\0 :_str(new char[strlen(str) + 1]) , _size(strlen(str)) , _capacity(_size) { strcpy(_str, str); } //string() //无参构造 // :_size(0) // , _capacity(0) // , _str(new char[1]) //{ // _str[0] = '\0'; //}带默认参数的构造函数中,const char*用于指向常量字符,接收以\0结尾的字符串。当调用时不提供参数时,str取值由默认参数 "" 替代,空字符串在内存中占一个字符'\0';若默认参数采用nullptr则会导致返回的是空指针,一不符合构造函数中的strlen调用,二不符合创建空字符串的概念;也就是一个默认构造的字符串对象 应该表示内容为空的字符串,而不是"未初始化的指针状态"。
-
析构函数
~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]; }迭代器
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; }iterator:被定义为char*,即指向字符的可变指针。它既可以读取字符,也可以通过解引用修改字符。const_iterator:被定义为const char*,即指向常量字符的指针。它只能读取字符,不能通过它修改字符内容string的增删查改
push_back,append,+=
void reserve(size_t n)//异地扩容 { if (n > _capacity) { char* tmp = new char[n + 1]; strcpy(tmp, _str); delete[] _str; _str = tmp; _capacity = n; } } 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) { //至少扩容到_size + len 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
void insert(size_t pos, size_t n, char ch)
{
assert(pos <= _size);
if (_size + n > _capacity)
{
reserve(_size + n);
}
//移动元素
size_t end = _size;
//此处无法处理pos为0的情况,
//while (end >= pos)
//{
// _str[end + n] = _str[end];
// --end;
//}
//解决方案1,强转int
//int end = _size;
//while (end >= (int)pos)
//{
// _str[end + n] = _str[end];
// --end;
//}
//2 使用npos
while (end >= pos&& end != npos)
{
_str[end + n] = _str[end];
--end;
}
for (size_t i = 0; i < n; i++)
{
_str[pos + i] = ch;
}
_size += n;
}
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size;
while (end >= pos && end != npos)
{
_str[end + len] = _str[end];
--end;
}
for (size_t i = 0; i < len; i++)
{
_str[pos + i] = str[i];
}
_size += len;
}
erase
void erase(size_t pos, size_t len = npos)
{
assert(pos <= _size);
if (len = npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
_str[_size] = '\0';
}
else
{
size_t end = pos + len;
while (end <= _size)
{
_str[pos] = _str[end++];
}
_size -= len;
}
}
find
size_t find(char ch, size_t pos = 0)
{
assert(pos < _size);
for (size_t i = 0; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
return npos;
}
size_t find(const char* str, size_t pos = 0)
{
assert(pos < _size);
const char* ptr = strstr(_str, str);
if (ptr) return ptr - _str;
else return npos;
return npos;
}
substr
string substr(size_t pos = 0, size_t len = npos)
{
assert(pos < _size);
size_t n = len;
if (len == npos || pos + len > _size)
{
n = _size - pos;
}
string tmp;
tmp.reserve(n);
for (size_t i = pos; i < pos + n; i++)
{
tmp += _str[i];
}
return tmp;//默认浅拷贝,需自定义拷贝构造
}
string(const string& s)
: _str(s._str)
, _size(s._size)
, _capacity(s._capacity)
{}
流插入和流提取
ostream& operator<<(ostream& out, const string& s)
{
for (size_t i = 0; i < s.size(); i++)
{
out << s[i];
}
return out;
}
istream& operator>>(istream& in, string& s)
{
char ch = in.get();
//in >> ch; 遇到空格和\n截至
char buff[128] = { '\0' };
int i = 0;
while (ch != ' ' || ch != '\n')
{
buff[i++] = ch;
if (i == 127)
{
buff[i] = '\0';
s += buff;
i = 0;
}
}
if (i != 0)
{
buff[i] = '\0';
s += buff;
}
return in;
}