(接上....)



























find 和 rfind 都还比较容易理解,一个是正向匹配,一个是逆向匹配,后面的参数pos都是用来指定起始查找位置。对于find_first_of 和find_last_of 就不是那么好理解。
find_first_of 是给定一个要查找的字符集,找到这个字符集中任何一个字符所在字符串中第一个位置。
find() 和 find_first_of()的区别是 find_first_of 是查找所给字符串的任意字符的第一次出现。
参数 p,4,2 的意思是从 s 的第4号位置开始,查找 p 的前两个字符。
所以 s.find(p,4,2); 就是在 s="a123bd1efg" 的 "b" 开始查找 "12"
s.find_first_of(p,4,2); 就是在s= "a123bd1efg" 的 "b" 开始查找 "1" 或者 "2" (2表示p最前面的2个字符中,找到其中任意一个即可)
1.3 string insert, replace, erase
了解了string 的操作符,查找函数和substr,其实就已经了解了string的80%的操作了。insert函数, replace函数和erase函数在使用起来相对简单。下面以一个例子来说明其应用。
string只是提供了按照位置和区间的replace函数,而不能用一个string字串来替换指定string中的另一个字串。这里写一个函数来实现这个功能:













看看如何调用:













其输出结果:



如果不用replace函数,则可以使用erase和insert来替换,也能实现string_replace函数的功能:














2 string 和 C风格字符串
现在看了这么多例子,发现const char* 可以和string 直接转换,例如我们在上面的例子中,使用
string_replace(strinfo, "Winter", "wende");
来代用
void string_replace(string & strBig, const string & strsrc, const string &strdst)
在C语言中只有char* 和 const char*,为了使用起来方便,string提供了三个函数满足其要求:其中:const charT* c_str() const const charT* data() const size_type copy(charT* buf, size_type n, size_type pos = 0) const你或许会问,c_str()的功能包含data(),那还需要data()函数干什么?看看源码:
- c_str 直接返回一个以/0结尾的字符串。
- data 直接以数组方式返回string的内容,其大小为size()的返回值,结尾并没有/0字符。
- copy 把string的内容拷贝到buf空间中。
原来c_str()的流程是:先调用terminate(),然后在返回data()。因此如果你对效率要求比较高,而且你的处理又不一定需要以/0的方式结束,你最好选择data()。但是对于一般的C函数中,需要以const char*为输入参数,你就要使用c_str()函数。const charT* c_str () const{ if (length () == 0) return ""; terminate (); return data (); }对于c_str() data()函数,返回的数组都是由string本身拥有,千万不可修改其内容。其原因是许多string实现的时候采用了引用机制,也就是说,有可能几个string使用同一个字符存储空间。而且你不能使用sizeof(string)来查看其大小。详细的解释和实现查看Effective STL的条款15:小心string实现的多样性。
另外在你的程序中,只在需要时才使用c_str()或者data()得到字符串,每调用一次,下次再使用就会失效,如:
string strinfo( " this is Winter " );...
// 最好的方式是:foo(strinfo.c_str());
// 也可以这么用:
const char * pstr = strinfo.c_str();foo(pstr);
// 不要再使用了pstr了, 下面的操作已经使pstr无效了。
strinfo += " Hello! " ;foo(pstr); // 错误!
3 string 和 Charactor Traits
了解了string的用法,该详细看看string的真相了。前面提到string 只是basic_string的一个typedef。看看basic_string 的参数:template <class charT, class traits = char_traits<charT>,class Allocator = allocator<charT> >class basic_string{ //...}
就像Steve Donovan在过度使用C++模板中提到的,这些确实有些过头了,要不是系统自己定义了相关的一些属性,而且用了个typedef,否则还真不知道如何使用。
但复杂总有复杂道理。有了char_traits,你可以定义自己的字符串类型。当然,有了char_traits < char > 和char_traits < wchar_t > 你的需求使用已经足够了,为了更好的理解string ,咱们来看看char_traits都有哪些要求。
如果你希望使用你自己定义的字符,你必须定义包含下列成员的结构:
表达式 | 描述 |
---|---|
char_type | 字符类型 |
int_type | int 类型 |
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是否相等 |
现在默认的string版本中,并不支持忽略大小写的比较函数和查找函数,如果你想练练手,你可以试试改写一个char_traits , 然后生成一个case_string类, 也可以在string 上做继承,然后派生一个新的类,例如:ext_string,提供一些常用的功能,例如:
- 定义分隔符。给定分隔符,把string分为几个字段。
- 提供替换功能。例如,用winter, 替换字符串中的wende
- 大小写处理。例如,忽略大小写比较,转换等
- 整形转换。例如把"123"字符串转换为123数字。
4 string 建议
使用string 的方便性就不用再说了,这里要重点强调的是string的安全性。
- string并不是万能的,如果你在一个大工程中需要频繁处理字符串,而且有可能是多线程,那么你一定要慎重(当然,在多线程下你使用任何STL容器都要慎重)。
- string的实现和效率并不一定是你想象的那样,如果你对大量的字符串操作,而且特别关心其效率,那么你有两个选择,首先,你可以看看你使用的STL版本中string实现的源码;另一选择是你自己写一个只提供你需要的功能的类。
- string的c_str()函数是用来得到C语言风格的字符串,其返回的指针不能修改其空间。而且在下一次使用时重新调用获得新的指针。
- string的data()函数返回的字符串指针不会以'/0'结束,千万不可忽视。
- 尽量去使用操作符,这样可以让程序更加易懂(特别是那些脚本程序员也可以看懂)
5 小结
难怪有人说:
string 使用方便功能强,我们一直用它!
6 附录
函数名 | 描述 |
begin | 得到指向字符串开头的Iterator |
end | 得到指向字符串结尾的Iterator |
rbegin | 得到指向反向字符串开头的Iterator |
rend | 得到指向反向字符串结尾的Iterator |
size | 得到字符串的大小 |
length | 和size函数功能相同 |
max_size | 字符串可能的最大大小 |
capacity | 在不重新分配内存的情况下,字符串可能的大小 |
empty | 判断是否为空 |
operator[] | 取第几个元素,相当于数组 |
c_str | 取得C风格的const char* 字符串 |
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== | 判断是否相等 |
operator!= | 判断是否不等于 |
operator< | 判断是否小于 |
operator>> | 从输入流中读入字符串 |
operator<< | 字符串写入输出流 |
getline | 从输入流中读入一行 |
Example:查找文件中的单词的出现的次数

































































