查询这些接口的网址:点击蓝色字体即可进入请点击
begin
返回字符串第一个字符的迭代器
end
返回一个迭代器,该迭代器为字符串最后一个字符的后一个。 通常用
begin
和end
形成一个区间来遍历一个字符串。
cpp string s("ml is cool");
for (std::string::iterator it = s.begin(); it != s.end(); ++it)
cout << *it;
cout << endl;
size
返回字符串的长度。
cpp string s("ml is cool");
cout << s.size() << endl;
输出的结果为10
capacity
获取储存字符串的容量。
cpp string a("ml is cool");
cout << a.capacity() << endl;
输出的结果为15
。
npos
公共的静态的全局成员。
resize
改变字符串的大小到n
,如果n小于size,删除n后面的字符,即在n号位置的字符变成\0
,容量不变。如果大于size,
容量改变,比原来字符串多的字符都变成c
,如果没有指定给的字符,就用\0
进行填充。
cpp string a("ml is cool");
string b("ml is cool");
string c("ml is cool");
a.resize(3);
b.resize(20);
c.resize(20,'h');
reserve
改变容量成n,如果n小于容量(capacity),这是不被允许的。如果n大于capacity,就把容量扩大到n。
empty
判断字符串是否为空。
find
查找字符或者字符串所在的位置,查找到就返回它们的第一次出现的位置,否则返回npos
nops
为-1
,-1
给size_t
的时候会变成一个非常大的值。(整型提升)
rfind
从字符串pos
位置的字符开始向前进行查找,当pos
的值为npos
或者为size_t()-1
时就是对整个字符串进行查找。第(3)
个是从[pos,pos+n)
进行查找。
cpp string str("ml is cool");
cout << str.find("is") << endl;
cout << str.rfind('i',5) << endl;
find_first_of
和find
差不多,只不过它是从字符串的pos
位置开始向后查找,只要发现和str
中的任意一个字符相同,则就返回该字符的位置。
cpp string s("ml is cool");
cout << s.find_first_of("abc", 1) << endl;
输出的结果为6。
substr
生成新的string
对象,子串是从pos
的位置向后获取len
个字符,即[pos,pos+len)
,len
的类型为无符号的整型size_t
,所以当值很大的时候,是到字符串的结尾。当然负数转为size_t
的时候也会变的很大。
cpp string s("ml is cool");
string str;
str = s.substr(0,2);
cout << str << endl;
insert
该接口为插入一段字符。14,都是从
pos
位置开始插入一个字符或者字符串。57,对于迭代器iterator
的参数,需要传迭代器参数。
erase
从某个位置开始删除,删除len
个字符,对于第2个函数,删除迭代器的位置的字符,第三个函数,表示从迭代器的开始位置删到结束位置。
cpp string str("ml is cool");
cout << str << endl;
str.erase(3, 2);
cout << str << endl;
push_back
在字符串的尾部插入一个字符。
cpp string a("ml is cool");
a.push_back('s');
cout << a << endl;
输出结果:ml is cools
append
把字符串追加到原来字符串的结尾。当然不同的函数重载有不同的,追加方式。可以说这个函数不用都可以,毕竟有+=,push_back
。
cpp string a("ml is cool");
string b("nbnbnbnb");
a.append("hhhhhhhhhh");
cout << a << endl;
a.append("###########", 3);
cout << a << endl;
a.append(3,'h');
cout << a << endl;
a.append(b);
cout << a << endl;
operator+
实现两个字符串的拼接。把后一个字符串连接到前一个字符串上。
cpp string s1("ml ");
string s2("is cool");
string s3;
s3 = s1 + s2;
cout << s3 << endl;
operator+=
+=
运算的重载本质就是在原来字符串的后面加上一组新串,或者字符。
cpp string a("ml");
string b(" cool");
a += ' ';
cout << a << endl;
a += "is";
cout << a << endl;
a += b;
cout << a << endl;
看结果:
c_str
把string
类型的字符串,转换成c语言类型的字符串(就是以\0
)
cpp string a("ml is cool");
a += '\0';
a += "hhhhhhhhh";
cout << a.c_str() << endl;
clear
清空字符串,字符串长度为0,但容量不变,即不是否开辟的空间。
cpp string a("ml is cool");
a.clear();
下面函数不是string
类里面的。
getline
如何获取一行字符串呢?仅仅靠
cin
,是不行的。这里提供一个函数getline
,它不是在string
这个类里面的函数,而是std
标准库里面的。 下面看它的使用:
对于(1),第一个参数为输入流(cin
从键盘上输入),第二个参数为string
对象,而第三个参数为以什么结束的字符。
当没有第三个参数的时候,结束以\n
为结束的。
cpp string str;
getline(cin, str);
cout << str << endl;
对于一个
string
类的实现,它的成员变量主要有:字符的指针,字符串的实际的大小,开辟该字符的容量。
cppchar* _str;
size_t _size;//字符的实际大小
size_t _capacity;//容量
构造函数 对于一个字符串我们怎么初始化呢? 要分为几种情况: 1.用户没有传入任何字符 2.用户传入字符串
为了解决上述的情况,我们可以提供全缺省的构造函数。 缺省参数为
""
,空字符串,里面只包含\0
。_size
大小为传入参数字符串的长度_capacity
的大小就是_size
的大小,当然,也可以开一定的空间。_str
开的空间要比_size
要大一个,因为要储存\0
。
cpp string(const char* str = "")
{
_size = strlen(str);
_str = new char[_size + 1];
_capacity = _size;
strcpy(_str, str);
}
拷贝构造 注意要深拷贝,不能直接把
str._str
的地址给_str
,如果这样会使析构两次,非法释放空间。
cpp string(const string& str)
{
_size = str._size;
_capacity = str._capacity;
_str = new char[_size + 1];
strcpy(_str, str._str);
}
析构函数 释放开辟的空间,大小和容量归
0
。
cpp ~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
赋值运算符重载 主要注意的是,要把原来
_str
指向的字符串释放(判断给自己赋值这种情况),然后重新开辟一段空间,然后赋值过去。
cpp string& operator=(const string& str)
{
if (_str == str._str)
return *this;
delete[] _str;
_size = str._size;
_capacity = str._capacity;
_str = new char[_size + 1];
strcpy(_str, str._str);
return *this;
}
+=运算符重载 这里实现两种
+=
,一种是+=一个字符,另一种是+=字符串 在+=的时候要判断容量(需要有扩容的处理)
cpp string& operator+=(const char ch)
{
if (_size == _capacity)
{
size_t n= _capacity == 0 ? 4 : _capacity * 2;
reserve(n);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
return *this;
}
string& operator+=(const char* str)
{
size_t len = strlen(str);
if (_size + len >= _capacity)
{
size_t n = _capacity == 0 ? len : (_size + len) * 2;
reserve(n);
}
strcpy(_str + _size, str);
_size += len;
return *this;
}
npos
静态的不可修改的公共成员static const size_t npos = -1;
查看字符串的长度
cpp size_t size()const
{
return _size;
}
查看储存字符串的容量
cpp size_t capacity()const
{
return _capacity;
}
查看字符串是否为空
cpp bool empty()const
{
return _size;
}
清空字符串 只把字符串变成空串,容量不变。
cpp void clear()
{
_size = 0;
_str[_size] = '\0';
}
[]
操作符的重载 要判断一下pos
的位置是否正确。
cpp char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos)const
{
assert(pos < _size);
return _str[pos];
}
改变容量的大小 当n小于
_capacity
不做处理,当n大于它时扩充容量。注意数据的保存。
cpp void reserve(size_t n)
{
if (n > _capacity)
{
_capacity = n;
char* temp = new char[_capacity+1];
strcpy(temp, _str);
delete[] _str;
_str = temp;
}
}
改变字符串的长度
cpp void resize(size_t n, char ch='\0')
{
if (n <= _size)
{
_str[n] = '\0';
_size = n;
}
else
{
reserve(n);
memset(_str + _size, ch, n - _size);
_size = n;
}
}
尾插 在字符串的最后插入一个字符。要注意空间的容量是否够用。不够用的话就需要扩容。这里我就复用我之前写的+=运算符的重载。(还是偷懒舒服)
cpp string& push_back(char ch)
{
*this += ch;
return *this;
}
append模拟实现 这里只模拟插入一个字符串,我们会发现这不就是
**+=**
的实现嘛。
cpp string& append(const char* str)
{
size_t len = strlen(str);
if (_size + len == _capacity)
{
size_t n = _capacity == 0 ? len : (_size + len) * 2;
reserve(n);//该函数已经把_capacity的值扩充到了n
}
strcpy(_str + _size, str);
return *this;
}
c_str,转换成c语言样式的字符串,注意只是只读,所以用const。
cpp const char* c_str()const
{
return _str;
}
查找 从某个位置开始进行查找字符串或者查找某个字符,返回第一个匹配的位置的下标,对于查找的位置要注意是否合法,当然对于查找字符串的时候,用
strstr
查找到的时候会返回匹配的字符串的首个字符的地址。对于它的位置,我们用指针相减即可获得该匹配的位置。
cpp size_t find(char ch, size_t pos)const
{
assert(pos < _size);
for (size_t i = pos; i < _size; ++i)
{
if (_str[i] == ch)
return i;
}
return npos;
}
size_t find(const char* str, size_t pos)const
{
assert(pos < _size);
char* p = strstr(_str+pos, str);
if (p == nullptr)
return npos;
else
{
return p - _str;
}
}
任意位置插入字符或者字符串 判断插入的位置是否正确,是否需要扩容。
cpp string& insert(size_t pos, char ch)
{
assert(pos < _size);
if (_size == _capacity)
{
reserve(_capacity + 1);
}
size_t p = _size;
while (p > pos)
{
_str[p] = _str[p - 1];
--p;
}
//strcpy(_str + pos + 1, _str + pos);
_str[pos] = ch;
++_size;
_str[_size] = '\0';
return *this;
}
string& insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len >= _capacity)
{
size_t newlen = _capacity == 0 ? len : (_size + len) * 2;
reserve(newlen);
}
size_t p = _size;
while (p >= pos)//注意边界问题
{
_str[p + len] = _str[p];
--p;
}
strncpy(_str + pos, str,len);//不能用strcpy因为会拷贝\0。
_size += len;
_str[_size] = '\0';
return *this;
}
删除某个位置的字符 首先要判断删除位置是否合法,删除之后要修改
size
的大小。删除的时候我们从后往前覆盖。
cpp string& erase(size_t pos = 0, size_t len = npos)
{
assert(pos < _size);
if (len == npos || len >= _size - pos)
{
_size = pos;
_str[_size] = '\0';
return *this;
}
strcpy(_str + pos, _str + len);
return *this;
}
首字符,末字符的迭代器
string
类的迭代器其实就是指针。
cpp typedef char* iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
流插入,流提取重载
cpp ostream& operator<<(ostream& os, const string& str)
{
for (size_t i = 0; i < str.size(); ++i)
{
os << str[i];
}
return os;
}
istream& operator>>(istream& oi, string& str)
{
char ch;
ch = oi.get();
while (ch != ' ' && ch != '\n')
{
str += ch;
ch = oi.get();
}
str += '\0';
return oi;
}
这里的流插入用到了
get
该函数是为了获得一个字符。