标准库中的string类
字符串是代表字符序列的对象。
标准字符串类通过类似于标准字节容器的接口为此类对象提供支持,但增加了专门设计用于单字节字符字符串的功能。
该字符串类是的一个实例的basic_string类模板使用字符(即字节)作为其性格类型,其默认char_traits和分配器类型(见basic_string的更多信息的模板)。
请注意,此类处理字节独立于所使用的编码:如果用于处理多字节或可变长度字符(如UTF-8)的序列,则此类的所有成员(如length或size)以及它的迭代器仍将以字节为单位(而不是实际的编码字符)进行操作。
即
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>
string; - 不能操作多字节或者变长字符的序列。
在使用string类时,必须包含#include头文件以及using namespace std;
string类常用接口说明
a. string类对象的常见构造
void TestString()
{
string s1; // 构造空的string类对象s1
string s2("hello"); // 用C格式字符串构造string类对象s2
string s3(s2); // 用s2拷贝构造s3
}
b. string类对象的容量操作
//size(返回字符串的有效长度)
string s1;
s1.size() //s1有效长度为0
string s2("hello");
s2.size() //s2有效长度为5
//length
//length与size功能相同,底层实现也几乎相同
//capacity
//capacity返回空间大小(即该对象所占内存大小)
//empty
//empty检测字符串是否为空串,是返回true否则false
//clear
//clear清空有效字符,使用该功能后该字符的size变为了0
//reserve
//reserve预设空间大小,因开空间是一个较为复杂的操作,有时为了提高效率,我们
//可以提前预测空间大小,用reserve提前一次开设完成,避免多次增容.
//resize
//resize设置有效字符的长度,并将增加的内容置为某个字符
//假设s空间足够
s.resize(15,'c'); //若15大于原size,则将size置为15,并将新增的size置为
//字符c
s.resize(15); //将增加的size置为默认的'\0'
注意:
- size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用size()。 - clear()只是将string中有效字符清空,不改变底层空间大小。
- resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字
符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的
元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
小,如果是将元素个数减少,底层空间总大小不变。 - reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
string的底层空间总大小时,reserver不会改变容量大小。
c. string类对象的访问及遍历操作
//operator[]
//返回pos位置的字符,const string类对象调用
//begin
//获取字符串开始位置的迭代器
//end
//获取字符串最后一个字符的下一个位置的迭代器
//rbegin,rend
//与begin,end功能相同,只不过他是以字符串的尾部作为字符串的开始位置的
string s("hello");
s[0]; //'h' operator[],不会进行下标检查,无异常机制
s.at(i) //访问下标为i的元素,会做下标检查,安全的异常机制,建议使用。
s.begin() //返回s开始位置的地址,即'h的地址'
s.end() //返回'0'的下一个位置的地址,即'\0'的地址
d. string类对象的修改操作
//push_back
//尾插一个字符
//append
//尾插一个字符串
//pop_back() C++11
//尾删一个字符
//operator+=
//字符串后追加一个字符串或字符
//c_str
//返回c风格的字符串
//find
//从某个位置开始找某个字符的第一次出现的位置并返回,从前往后找
//rfind
//与find功能相同,从后往前找
//substr
//从某个位置开始截取n个字符返回
/*
assign 为字符串分配一个新的值,替换它的内容
string& assign (const string& str);
string& assign (const string& str, size_t subpos, size_t sublen);
string& assign (const char* s);
string& assign (const char* s, size_t n);
string& assign (size_t n, char c);
string& assign (InputIterator first, InputIterator last);
*/
string s("abcdefg");
s.push_back('h'); //abcdefgh
s.append("ijk"); //abcdefghijk
s+="lm"; //abcdefghijklm
s.find('b'); //返回b的下标
s.substr(3,5); //截取def
s.substr(3); //截取defghijklm
//assign
string s2("abcdefg");
string s1("0123456789");
s1.assign(s2); //abcdefg
s1.assign(s2,1,3); //bcd 从下标1开始到3
s1.assign("0123456"); //0123456
s1.assign("0123456",4); //0123
s1.assign(5,'a'); //aaaaa
s1.assign(s2.begin(),s2.end()); //abcdefg 通过迭代器构造
//insert //插入
/*
string& insert (size_t pos, const string& str);
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
string& insert (size_t pos, const char* s);
string& insert (size_t pos, const char* s, size_t n);
string& insert (size_t pos, size_t n, char c);
//返回的都是第一个插入字符的迭代器
iterator insert (const_iterator p, size_t n, char c);
iterator insert (const_iterator p, char c);
iterator insert (iterator p, InputIterator first, InputIterator last);
string& insert (const_iterator p, initializer_list<char> il);
*/
string s3("0123456789");
string s4("abcdefg");
//() 里面的为新插入的
s3.insert(3,s4); //012(abcdefg)3456789
s3.insert(3,s4,1,3); //012(bcd)abcdefg3456789
s3.insert(3,"???"); //012(???)bcdabcdefg3456789
s3.insert(3,"abcdefg",3); //012(abc)???bcdabcdefg3456789
s3.insert(3,2,'#'); //012(##)abc???bcdabcdefg3456789
s3.insert(s3.begin(),2,'##');//(##)012##abc???bcdabcdefg3456789
s3.insert(s3.begin(),'*'); //(*)##012##abc???bcdabcdefg3456789
s3.insert(s3.begin(),s4.begin(),s4.begin()+2);
//(abc)*##012##abc???bcdabcdefg3456789
//erase 删除
/*
string& erase (size_t pos = 0, size_t len = npos);
iterator erase (iterator p);
iterator erase (iterator first, iterator last);
*/
string s5("0123456789");
s5.erase(0,3); //0456789
s5.erase(s5.begin()); //456789
s5.erase(s5.begin()+1,s5.end()); //4
//string substr (size_t pos = 0, size_t len = npos) const;
//默认从0开始截取到末尾
string s6("0123456789");
string temp=s6.substr(2,3); //234
//compare 比较
///规则 :按照字典序先后顺序比较,优先比较字符,后比较长度,从左到右依次比较字符,若前N个字符相等则比较长度
//返回值:
0:相等
<0:比较字符串中不匹配的第一个字符的值较低,或者所有比较字符都匹配,但比较字符串较短。
>0:比较的字符串中不匹配的第一个字符的值较大,或者所有比较的字符都匹配,但比较的字符串较长。
/*
int compare (const string& str) const noexcept;
int compare (size_t pos, size_t len, const string& str) const;
int compare (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen) const;
int compare (const char* s) const;
int compare (size_t pos, size_t len, const char* s) const;
int compare (size_t pos, size_t len, const char* s, size_t n) const;
*/
string s7("0123456abc");
string s8("abc");
s7.compare(s8); //s7第一个字符较小,返回-1
s7.compare(7,3,s8); //相等返回0
s7.compare("()"); //s7第一个字符较大 返回1
//copy
//size_t copy (char* s, size_t len, size_t pos = 0) const;
//从对象字符串的pos位置起的len个字符拷贝到 s中,不会再末尾添加‘\0’
//返回拷贝的长度
char buf[10];
string s9("0123456789");
int length=s9.copy(buf,3,3);
buf[length]='\0'; //buf=345
注意:
- 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般
情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。 - 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。
e. string类非成员函数
operator+ 尽量少用,因为传值返回,导致深拷贝效率低
operator>> 输入运算符重载
operator<< 输出运算符重载
getline 获取一行字符串(默认回车结束),第三个参数可指定结束标志
relational operators 大小比较