什么是string?
string是表示字符串的字符串类
该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
string在底层实际是:basic_string 模板类的别名,typedef basic_stringstring;
不能操作多字节或者变长字符的序列。
在使用string类时必须包含头文件 以及using namespace std;
接下来主要讲一些 string 类里所包含的一些常用的方法和函数 例如 构造 赋值 删除 插入、连接字符 获取字符 查询等等
定义 | 功能 |
---|---|
string() | 默认构造函数。 |
string(const char *s) | 使用 字符串创建一个 string 对象。 |
string(const string &s) | 拷贝构造函数,使用现有字符串创建一个新字符串。 |
实例:
定义 | 功能 |
---|---|
= | 赋值运算符重载,可以使用string对象赋值,常量字符串赋值以及字符赋值 |
+= | 将右侧字符串的副本附加到左侧的 string 对象 |
+ | 返回将两个字符串连接在一起所形成的字符串 |
[] | 可以让string对象像数组那样使用下标法访问字符串 |
<< | 可以使用cout输出流正常打印string对象的内容 |
关系运算符 | 用来判断两个string对象的字符串的关系 |
getline | 获取一行字符串,使用cin读取字符串时,通常以空格或者换行符作分割符号,这样导致有的字符串中有空格读不到会当分隔符,使用getline函数可以读取一行字符串,以换行符作为分隔符 |
实例1:
迭代器类成员函数 | 功能 |
---|---|
begin | 返回指向 string 中第一个字符的迭代器 |
end | 返回指向 string 中最后一个字符的下一个位置的迭代器(即’\0’位置) |
rbegin | 返回指向 string 中最后一个字符的反向迭代器 |
rend | 返回指向 string 中第一个字符前一个位置的反向迭代器(即-1位置) |
crbegin | 返回指向常量字符串中最后一个字符的反向迭代器(常量字符串使用) |
crend | 返回指向常量字符串第一个字符前一个位置的反向迭代器(即-1位置) |
实例:
成员函数 | 功能 |
---|---|
capacity() | 返回 string 被分配的容量的大小 |
size() | 返回 string 中字符串的长度 |
clear() | 删除 string 中存储的所有字符 |
empty() | 如果 string 为空则返回 true,否则返回 false |
append() | 将str字符串追加到string末尾位置 |
push_back() | 在string后面尾插一个字符 |
find() | 返回在 string 中找到的 str 字符串的第一个位置。如果没有找到 str,则返回 string 类的静态成员 string::npos(很大的一个数) |
rfind() | 返回string中最后一个匹配的字符的位置,如果没有找到 str,则返回 string 类的静态成员 string::npos(很大的一个数) |
reserve() | 调整空间大小,扩容使用,不建议使用减容 |
resize() | 开空间+初始化内容 |
namespace tzc{
public:
//默认构造 + 构造
//使用缺省参数,无参时构造空字符串, 开空间时多给'\0'开一个空间,capacity不包括'\0'
string(const char* str="")
:_size(strlen(str))
{
//空串初始capacity值为3
_capacity = _size==0?3:_size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
//拷贝构造 深拷贝
string(const string& s)
:_size(s._size)
, _capacity(s._capacity)
{
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
}
//析构函数 new出的空间需使用delete释放
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
}
//[]重载
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
//重载一个可供const对象使用的
const char& operator[](size_t pos) const
{
assert(pos < _size);
return _str[pos];
}
//size函数
size_t size() const
{
return _size;
}
//capacity函数
size_t capacity()const
{
return _capacity;
}
//clear函数
void clear()
{
//清除string中的内容
_str[0] = '\0'; //将第一个位置设置为 \0
_size = 0; //将string的大小改为0
}
//c_str函数
const char* c_str()
{
return _str;
}
//在写运算符重载时我们可以复用写好的运算符重载减少冗余代码
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);
}
//在string类中
typedef char* iterator;
typedef const char* const_iterator;
//使用指针方式模拟实现迭代器
//普通迭代器
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
//const迭代器
iterator begin() const
{
return _str;
}
iterator end() const
{
return _str + _size;
}
//进行插入操作的时候都需要检查他的容量是否够用,如果不够需要扩容
//尾插
void push_back(char ch)
{
//扩容
if (_size + 1 > _capacity)
{
reserve(_capacity * 2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
//push_back 和append可以复用insert
//追加
void append(const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
//扩容
reserve(_size + len);
}
strcpy(_str + _size, str);
//strcat(_str, str); //不推荐,自己找 \0
_size += len;
_str[_size] = '\0';
}
//
string& operator+=(const char ch)
{
push_back(ch);
return *this;
}
string& operator+=(const char* str)
{
append(str);
return *this;
}
//可以在指定位置插入字符
string& insert(size_t pos, char ch)
{
if (_size + 1 > _capacity)
{
reserve(2 * _capacity);
}
size_t end = _size+1; //end指向\0
while (end > pos)
{
_str[end] = _str[end-1];
--end;
}
_str[pos] = ch;
++_size;
return *this;
}
//指定位置插入字符串
string& insert(size_t pos,const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (len + _size > _capacity)reserve(len + _size);
size_t end = len + _size;
while (end >= pos + len)
{
_str[end] = _str[end - len];
--end;
}
strncpy(_str + pos, str, len);
_size += len;
return *this;
}
//删除从pos位置开始的len个字符,如果len未传值,则默认从pos位置后面全部删除
string& erase(size_t pos,size_t len=npos)
{
//断言检查pos不得超过字符串的长度
assert(pos < _size);
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
return *this;
}
//从pos位置开始查找指定字符,pos默认为0,也可以指定从什么位置开始查找,如果查找到返回字符所在位置,
size_t find(char ch,size_t pos=0)
{
assert(pos < _size);
for (size_t i = pos; i < _size; i++)
{
if (_str[i] == ch)
{
return i;
}
}
}
//从指定位置查找字符串,查找到返回字符串位置
size_t find(const char* str, size_t pos = 0)
{
assert(pos < _size);
char* ret=strstr(_str + pos, str);
if (ret == nullptr)
{
return npos;
}
else
{
return ret - _str;
}
}
//如果传入的n小于原来的size,则进行缩容(删除数据,申请的空间大小不变)
void resize(size_t n,char ch='\0')
{
//开空间+初始化
if (n <= _size)
{
//删除数据 缩容,保留前n个
_size = n;
_str[n] = '\0';
}
else
{
//如果传入的n比字符串容量大,则需要申请更大的空间
if (n > _capacity)
{
reserve(n);
}
while (_size < n)
{
//将申请的空间赋值为传入的ch
_str[_size] = ch;
_size++;
}
_str[_size] = '\0';
}
}
void reserve(size_t n)
{
//开空间
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
//类外函数,避免传入的this占用第一个参数
ostream& operator<<(ostream& out, const string& s)
{
for (auto ch : s)
{
cout << ch;
}
return out;
}
istream& operator>>(istream& in, string& s)
{
//getline函数实现同理
s.clear(); //覆盖原来的数据
char ch = in.get();
while (ch != ' ' && ch != '\n')
{
s += ch;
ch=in.get();
}
return in;
}