return0;
}其输出结果:
Orignstringis:
ThisisWinter,Winterisaprogrammer.DoyouknowWinter?
AfterreplaceWinterwithwende,thestringis:
Thisiswende,wendeisaprogrammer.Doyouknowwende?
如果不用replace函数,则可以使用erase和
insert来替换,也能实现string_replace函数的功能:
voidstring_replace(string&strBig,conststring&strsrc,conststring&strdst){
string:
:
size_typepos=0;
string:
:
size_typesrclen=strsrc.size();
string:
:
size_typedstlen=strdst.size();
while((pos=strBig.find(strsrc,pos))!
=string:
:
npos){
strBig.erase(pos,srclen);
strBig.insert(pos,strdst);
pos+=dstlen;
}
}当然,这种方法没有使用replace来得直接。
2string和C风格字符串
现在看了这么多例子,发现constchar*可以和string直接转换,例如我们在上面的例子中,使用
string_replace(strinfo,"Winter","wende");来代用
voidstring_replace(string&strBig,conststring&strsrc,conststring&strdst)在C语言中只有
char*和constchar*,为了使用起来方便,string提供了三个函数满足其要求:
constcharT*c_str()const
constcharT*data()const
size_typecopy(charT*buf,size_typen,size_typepos=0)const其中:
c_str直接返回一个以\0结尾的字符串。
data直接以数组方式返回string的内容,其大小为size()的返回值,结尾并没有\0字符。
copy把string的内容拷贝到buf空间中。
你或许会问,c_str()的功能包含data(),那还需要data()函数干什么?
看看源码:
constcharT*c_str()const
{if(length()==0)return"";terminate();returndata();}原来c_str()的流程是:
先调用
terminate(),然后在返回data()。
因此如果你对效率要求比较高,而且你的处理又不一定需要以\0的方式结束,
你最好选择data()。
但是对于一般的C函数中,需要以constchar*为输入参数,你就要使用c_str()函数。
对于c_str()data()函数,返回的数组都是由string本身拥有,千万不可修改其内容。
其原因是许多string实现
的时候采用了引用机制,也就是说,有可能几个string使用同一个字符存储空间。
而且你不能使用sizeof
(string)来查看其大小。
详细的解释和实现查看EffectiveSTL的条款15:
小心string实现的多样性。
另外在你的程序中,只在需要时才使用c_str()或者data()得到字符串,每调用一次,下次再使用就会失效,如:
stringstrinfo("thisisWinter");
...
//最好的方式是:
foo(strinfo.c_str());
//也可以这么用:
constchar*pstr=strinfo.c_str();
foo(pstr);
//不要再使用了pstr了,下面的操作已经使pstr无效了。
strinfo+="Hello!
";
foo(pstr);//错误!
会遇到什么错误?
当你幸运的时候pstr可能只是指向"thisisWinterHello!
"的字符串,如
果不幸运,就会导致程序出现其他问题,总会有一些不可遇见的错误。
总之不会是你预期的那个结果。
3string和CharactorTraits
了解了string的用法,该详细看看string的真相了。
前面提到string只是basic_string的一个typedef。
看看
basic_string的参数:
template,
classAllocator=allocator>
classbasic_string
{
//...
}char_traits不仅是在basic_string中有用,在basic_istream和basic_ostream中也需要用到。
就像SteveDonovan在过度使用C++模板中提到的,这些确实有些过头了,要不是系统自己定义了相关的一些属性
,而且用了个typedef,否则还真不知道如何使用。
但复杂总有复杂道理。
有了char_traits,你可以定义自己的字符串类型。
当然,有了char_traits和
char_traits你的需求使用已经足够了,为了更好的理解string,咱们来看看char_traits都有哪
些要求。
如果你希望使用你自己定义的字符,你必须定义包含下列成员的结构:
表达式描述
char_type字符类型
int_typeint类型
pos_type位置类型
off_type表示位置之间距离的类型
state_type表示状态的类型
assign(c1,c2)把字符c2赋值给c1
eq(c1,c2)判断c1,c2是否相等
lt(c1,c2)判断c1是否小于c2
length(str)判断str的长度
compare(s1,s2,n)比较s1和s2的前n个字符
copy(s1,s2,n)把s2的前n个字符拷贝到s1中
move(s1,s2,n)把s2中的前n个字符移动到s1中
assign(s,n,c)把s中的前n个字符赋值为c
find(s,n,c)在s的前n个字符内查找c
eof()返回end-of-file
to_int_type(c)将c转换成int_type
to_char_type(i)将i转换成char_type
not_eof(i)判断i是否为EOF
eq_int_type(i1,i2)判断i1和i2是否相等
想看看实际的例子,你可以看看sgiSTL的char_traits结构源码.
现在默认的string版本中,并不支持忽略大小写的比较函数和查找函数,如果你想练练手,你可以试试改写一个
char_traits,然后生成一个case_string类,也可以在string上做继承,然后派生一个新的类,例如:
ext_string,提供一些常用的功能,例如:
定义分隔符。
给定分隔符,把string分为几个字段。
提供替换功能。
例如,用winter,替换字符串中的wende
大小写处理。
例如,忽略大小写比较,转换等
整形转换。
例如把"123"字符串转换为123数字。
这些都是常用的功能,如果你有兴趣可以试试。
其实有人已经实现了,看看ExtendedSTLstring。
如果你想偷懒
,下载一个头文件就可以用,有了它确实方便了很多。
要是有人能提供一个支持正则表达式的string,我会非常
乐意用。
4string建议
使用string的方便性就不用再说了,这里要重点强调的是string的安全性。
string并不是万能的,如果你在一个大工程中需要频繁处理字符串,而且有可能是多线程,那么你一定要慎重(当
然,在多线程下你使用任何STL容器都要慎重)。
string的实现和效率并不一定是你想象的那样,如果你对大量的字符串操作,而且特别关心其效率,那么你有两
个选择,首先,你可以看看你使用的STL版本中string实现的源码;另一选择是你自己写一个只提供你需要的功能
的类。
string的c_str()函数是用来得到C语言风格的字符串,其返回的指针不能修改其空间。
而且在下一次使用时重新
调用获得新的指针。
string的data()函数返回的字符串指针不会以'\0'结束,千万不可忽视。
尽量去使用操作符,这样可以让程序更加易懂(特别是那些脚本程序员也可以看懂)
5小结
难怪有人说:
string使用方便功能强,我们一直用它!
6附录
string函数列表函数名描述
begin得到指向字符串开头的Iterator
end得到指向字符串结尾的Iterator
rbegin得到指向反向字符串开头的Iterator
rend得到指向反向字符串结尾的Iterator
size得到字符串的大小
length和size函数功能相同
max_size字符串可能的最大大小
capacity在不重新分配内存的情况下,字符串可能的大小
empty判断是否为空
operator[]取第几个元素,相当于数组
c_str取得C风格的constchar*字符串
data取得字符串内容地址
operator=赋值操作符
reserve预留空间
swap交换函数
insert插入字符
append追加字符
push_back追加字符
operator+=+=操作符
erase删除字符串
clear清空字符容器中所有内容
resize重新分配空间
assign和赋值操作符一样
replace替代
copy字符串到空间
find查找
rfind反向查找
find_first_of查找包含子串中的任何字符,返回第一个位置
find_first_not_of查找不包含子串中的任何字符,返回第一个位置
find_last_of查找包含子串中的任何字符,返回最后一个位置
find_last_not_of查找不包含子串中的任何字符,返回最后一个位置
substr得到字串
compare比较字符串
operator+字符串链接
operator==判断是否相等