string类(3)
push_back
这是尾插一个字符。
append
这是尾插字符串。可以看出来设计得很复杂。
实践中比较常用的是:
string s("hello world");
s.push_back(' ');
s.push_back('x');
s.append("zzzzzzzz");
用得更多的是:
operator +=
实践中,string的尾插我们用+=就可以了。底层空间不够了会扩容。
assign
赋值,把之前的覆盖掉。空间不够底层也会扩容。
和operator=有一些重叠。
用得也比较少。
insert
这个接口设计也比较冗余。很多接口的实用性并没有那么强。
真正用得多的就两个:
可以看到没有提供头插。所以头插就得用insert。
但是头插或者中间插入要谨慎,因为实现效率比较低。一个是空间不够要扩容,另一个是需要把插入位置之后的数据整体后移。
也可以只插入一个字符,只要用的是双引号不是单引号就行。
或者这样写(体现出混乱):
这个是先创建char对象,然后再插入,有两种方式:第一种不得不写第二个参数为1;第二种前一个是迭代器。
insert要谨慎使用,不到万不得已不要轻易用。
向前兼容,所以冗余。
erase
第一个用得最多。
还可以这样尾删:
还可以 这样尾删:
string s("hello world");
s.erase(s.size()-1,1);
cout << s << endl;
总结:
//头删
s.erase(0,1);
s.erase(s.begin());
//尾删
s.erase(--s.end());
s.erase(s.size()-1,1);
sequence (1):
string& erase (size_t pos = 0, size_t len = npos);
所以可以利用npos,全删了:
s.erase(6);
string一般只尾插,不删除,不在中间插入。可以用不同的策略提高效率。
replace
可以替换成string、string的一部分,char*、char *的一部分;可以从一个迭代器到另一个迭代器间替换,也可以从pos开始的len个字符替换。
底层是怎么做的呢?应该字符替换成两个字符,得向后挪动,空间不够还得扩容。如果是多个字符替换成更少的字符,不需要扩容但是要往前挪动数据。
这东西效率也不高。
怎么把所有的空格替换成百分号呢?
但是每次都是从头到尾找空格,没必要。
character (4)
size_t find (char c, size_t pos = 0) const;
while (pos != string::npos)
{
s.replace(pos,1, "%%");
pos = s.find( ' ',pos+2);//pos+2
}
但是如果要大量这样字符串替换,这个代码是非常不好的。因为不止一次扩容。
这时候我们就可以考虑用空间换时间。
最后可以复制拷贝:
s=tmp;
其实用swap会更高效:
s.swap(tmp);
这个交换在底层会把它俩的_str,_size,_capacity进行交换:
class string
{
char* _str;
size_t _size;
size_t _capacity;
};
这个效率很高,如果我们再reserve一下,效率就更高了 :
string tmp;
tmo.reserve(s.size());
for(auto ch : s)
{
……
}
所以insert erase replace都要警惕其成为性能杀手。replace只在平替效率高。
关于尾删,C++11还提供了个pop_back,但是用erase尾删也可以。
c_str
功能就是返回它底层那个指向堆上空间的字符串指针。
意义是什么呢?兼容C语言。
功能就是return一个C形式的字符串。
适用于一些需要C的接口:
string file;
cin >> file;
FILE* fout = fopen(file.c_str(), "r");
char ch = fgetc(fout);
while(ch!= EOF)
{
cout<<ch;
ch=fgetc(fout);
}
fclose(fout);
data接口和c_str类似。
get_allocator先不用管。
copy就是拷贝一个子串过来,用得少。
find系列
我们前面已经看过find,可以找字符或者串。
rfind是倒着找。什么情况需要倒着找?比如想要获取一个文件的后缀。
但如果我们的s是"test.cpp.zip",我们只能取到cpp.zip,但我们想要的是zip。
所以我们用rfind比较合理。
find_first_of
和"abcd"中的任意一个相等就返回,替换为’*'。
所以这个接口名字比较不符合功能。
find_last_of
倒着找
find__first_not_of
然后来看看string的几个非成员函数
operator+
为什么这个+要设计成非成员函数?
因为它想要支持把string+字符串反过来,也就是字符串+string:
不过,这个+用得不是很多。
relational operators (string)
这个不多说了。
本文到此结束=_=