string类是C++中常用的一个针对字符串管理所设计的的字符串类
一.string的一些常用的接口
1.常见的string类构造接口
string() //构造一个空的string类对象
string(const char* s) //以C格式的字符串,来构造出一个string类对象
string(size_t n,char c) //用n个字符c来构造一个string类对象
string(const string& s) //拷贝构造
string(const string& s,pos n) //从对象s的位置n起拷贝构造出新的string类对象
用法示例
int main()
{
string s1; //构造出空的string类对象s1
string s2("hello "); //用C格式字符串构造出string类对象s2
string s3("world"); //同上
string s4(11, 't'); //用11个字符t构造string类对象s4
string s5(s3); //用s3拷贝构造s5
string s6(s3, 0);
//因为没有包<string>,因此需要用->对象.c_str()的方法将string转化为char*的方式进行输出
cout<<s3<<endl;//报错
cout << (s1 = s2).c_str() << endl;
cout << s3.c_str() << endl;
//包了string头文件之后,即可正常输出
cout << s6 << endl;//输出world
//...
return 0;
}
2.string类对象的容量操作函数
size_t size()const //返回字符串有效长度
size_t length()const //同上 //size与length原理相同
size_t capacity()const //返回对象空间大小
bool empty()const //判空,空返回true即(1),非空返回false(0)
void clear() //清空有效字符//但不改变其空间大小
void resize(size_t n,char c)//将对象的有效字符串个数改为n个,剩余的用字符c填充
void resize(size_t n) //同上,但剩余个数使用0进行填充
void reserve(size_t n) //为对象预留空间
注意:
1.resize在改变对象有效个数时,如果是将有效元素个数增大,有可能导致对象底层容量(即capacity)的增大,但若将有效元素减少,则不会不会引起容量的变化。
2.reserve为对象预留空间时,不会改变对象的有效个数。当其参数大于原空间时会扩容至参数大小,但因为考虑到内存对齐,其实际可能比参数要大上一点,如果是一点一点的增加对象的有效个数所导致的增容,reserve大概会按1.5倍的方式进行增容;当参数小于原空间大小时,则不会改变对象容量大小。
3.访问操作
char& operator[](size_t pos) //返回对象pos位置处的字符,非const对象调用
const char& operator[](size_t pos)const//同上,const对象调用
用法示例
//一般会用在遍历字符串中
int main()
{
//创建一个非const的对象,即可读,也可写
string s("hello world");
//与size()配合,使其支持类似于数组的访问
for(int i=0;i<s.size();++i)
{
s[i]+=1;
cout<<s[i]<<' ';
}
cout<<endl;
//范围for遍历
//底层会被替换为迭代器
for (auto ch : s)
{
cout << ch << ' ';
}
cout << endl;
//迭代器遍历
//string::reverse_iterator //反向迭代器
//string::const_reverse_iterator //反向const迭代器
string::iterator it = s.begin();
while (it != s.end())
{
*it-=1;
cout << *it << ' ';
++it;
}
cout << endl;
return 0;
}
4.修改操作
void push_back(char c) //尾插字符c
string& append(const char* s) //追加一个字符串s
string& operator+=(const string& str) //追加一个string类对象str
string& operator+=(const char* str) //追加一个字符串
string& operator+=(char c) //追加字符c
const char*c_str()const //返回C格式的字符串
size_t find(char c,size_t pos=0) //从pos位置开始找字符c,不给pos默认从开始找,返回c的位置
size_t rfind(char c,size_t pos=npos) //从pos位置开始往前找字符c,并返回其位置,npos为字符串最后一个位置,也就是说其默认从最后一个开始找
string substr(size_t pos=0,size_t n=npos)const //从pos位置开始,往后截取n个字符,然后返回//默认从pos位置开始往后截取完字符串为止
string erase(size_t begin,size_t end) //删除字符串[begin,end]位置之间的元素,并返回删除之后的字符串
注意:
1.对string对象进行操作时,最好将其空间用resere()预留好,以防止增容带来的不必要开销。
2.对string对象追加字符串或字符时,推荐使用+=,可读性高,功能齐全。
//find(),substr()的用例示范
int main()
{
// 取出s中的域名
string s("http://www.cplusplus.com/reference/string/string/find/");
cout << s << endl;
//找到://中:的位置
size_t start = s.find("://");
//跳过://
start += 3;
//从start开始向后找第一个/的位置
size_t finish = s.find('/', start);
//从start开始截取finish个字符,构成一个新串
string address = s.substr(start, finish - start);
cout << address << endl;//输出:www.cplusplus.com
}
5.string类的非成员函数
operator>> //输入运算符重载
operator<< //输出运算符重载
getline //获取一行字符串,遇到空格不结束,换行结束
relational operators //大小比较
二.string的简单实现
实现前首先要了解,string类对象中存储的是指针,在指针指向的数组中存储字符,要保证字符的结尾必须有’\0’的存在。
以下对其构造,拷贝构造,赋值运算符重载和析构函数的简单实现。
class my_string
{
public:
//构造
String(const char* str = "")//""里边存了一个'\0'
//不在初始化的时候就开空间,是为了保证String(nullptr)的正常
//否则strlen(nullptr)就直接报错了
{
if (str == nullptr)
{
str = "";
}
_str = new char[strlen(str) + 1];
//上俩句保证让String(nullptr),也能构造出一个空对象
strcpy(_str, str);
}
//拷贝构造
String(const String& s)
:_str(new char[strlen(s._str)+1])
{
strcpy(_str, s._str);
}
//赋值运算符重载
String& operator=(const String& s)
{
if (this != &s)//防止自己给自己赋值
{
char* pStr = new char[strlen(s._str) + 1];
strcpy(pStr, s._str);
delete[] _str;
_str = pStr;
}
return *this;
}
//析构
~String()
{
if (_str)//不空在做如下操作//空就不做处理即可
{
delete[] _str;
_str = nullptr;
}
}
private:
char* _str;
}
测试:
int main()
{
String s("hello world");
String s1(s);//验证拷贝构造是否解决了浅拷贝问题
String s2;//验证构造函数,是否能构建出空的字符串对象
String s3=s1;//验证赋值运算符重载
return 0;
}