1 string 使用.docx
- 文档编号:6166454
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:18
- 大小:28.59KB
1 string 使用.docx
《1 string 使用.docx》由会员分享,可在线阅读,更多相关《1 string 使用.docx(18页珍藏版)》请在冰豆网上搜索。
1string使用
1string使用
其实,string并不是一个单独的容器,只是basic_string模板类的一个typedef而已,相对应的还有wstring,你在string头文件中你会发现下面的代码:
?
ViewCodeCPP
extern"C++"{
typedefbasic_string
typedefbasic_string
}//extern"C++"
由于只是解释string的用法,如果没有特殊的说明,本文并不区分string和basic_string的区别。
string其实相当于一个保存字符的序列容器,因此除了有字符串的一些常用操作以外,还有包含了所有的序列容器的操作。
字符串的常用操作包括:
增加、删除、修改、查找比较、链接、输入、输出等。
详细函数列表参看附录。
不要害怕这么多函数,其实有许多是序列容器带有的,平时不一定用的上。
如果你要想了解所有函数的详细用法,你需要查看basic_string,或者下载STL编程手册。
这里通过实例介绍一些常用函数。
1.1充分使用string操作符
string重载了许多操作符,包括+,+=,<,=,,[],<<,>>等,正式这些操作符,对字符串操作非常方便。
先看看下面这个例子:
?
ViewCodeCPP
#include
#include
usingnamespacestd;
intmain()
{
stringstrinfo="Pleaseinputyourname:
";
cout< cin>>strinfo; if(strinfo=="winter") cout<<"youarewinter! "< elseif(strinfo! ="wende") cout<<"youarenotwende! "< elseif(strinfo<"winter") cout<<"yournameshouldbeaheadofwinter"< else cout<<"yournameshouldbeafterofwinter"< strinfo+=",WelcometoChina! "; cout< cout<<"Yournameis: "< stringstrtmp="Howareyou? "+strinfo; for(inti=0;i cout< return0; } 下面是程序的输出 ? ViewCodeCPP Pleaseinputyourname: Hero youarenotwende! Hero,WelcometoChina! Howareyou? Hero,WelcometoChina! 有了这些操作符,在STL中仿函数都可以直接使用string作为参数,例如less,great,equal_to等,因此在把string作为参数传递的时候,它的使用和int或者float等已经没有什么区别了。 例如,你可以使用: ? ViewCodeCPP map 有了operator+以后,你可以直接连加,例如: ? ViewCodeCPP stringstrinfo="Winter"; stringstrlast="Hello"+strinfo+"! "; stringstrtest="Hello"+strinfo+"Welcome"+"toChina"+"! ";//你还可以这样: 看见其中的特点了吗? 只要你的等式里面有一个string对象,你就可以一直连续”+”,但有一点需要保证的是,在开始的两项中,必须有一项是string对象。 其原理很简单: 系统遇到”+”号,发现有一项是string对象。 系统把另一项转化为一个临时string对象。 执行operator+操作,返回新的临时string对象。 如果又发现”+”号,继续第一步操作。 由于这个等式是由左到右开始检测执行,如果开始两项都是constchar*,程序自己并没有定义两个constchar*的加法,编译的时候肯定就有问题了。 有了操作符以后,assign(),append(),compare(),at()等函数,除非有一些特殊的需求时,一般是用不上。 当然at()函数还有一个功能,那就是检查下标是否合法,如果是使用: ? ViewCodeCPP stringstr="winter";//下面一行有可能会引起程序中断错误 str[100]='! ';//下面会抛出异常: throws: out_of_range cout< 了解了吗? 如果你希望效率高,还是使用[]来访问,如果你希望稳定性好,最好使用at()来访问。 1.2眼花缭乱的stringfind函数 由于查找是使用最为频繁的功能之一,string提供了非常丰富的查找函数。 其列表如下: 函数名描述find查找rfind反向查找find_first_of查找包含子串中的任何字符,返回第一个位置find_first_not_of查找不包含子串中的任何字符,返回第一个位置find_last_of查找包含子串中的任何字符,返回最后一个位置find_last_not_of查找不包含子串中的任何字符,返回最后一个位置以上函数都是被重载了4次,以下是以find_first_of函数为例说明他们的参数,其他函数和其参数一样,也就是说总共有24个函数: ? ViewCodeCPP size_typefind_first_of(constbasic_string&s,size_typepos=0) size_typefind_first_of(constcharT*s,size_typepos,size_typen) size_typefind_first_of(constcharT*s,size_typepos=0) size_typefind_first_of(charTc,size_typepos=0) 所有的查找函数都返回一个size_type类型,这个返回值一般都是所找到字符串的位置,如果没有找到,则返回string: : npos。 有一点需要特别注意,所有和string: : npos的比较一定要用string: : size_type来使用,不要直接使用int或者unsignedint等类型。 其实string: : npos表示的是-1,看看头文件: ? ViewCodeCPP template constbasic_string<_CharT,_Traits,_Alloc>: : size_type basic_string<_CharT,_Traits,_Alloc>: : npos =basic_string<_CharT,_Traits,_Alloc>: : size_type)-1; find和rfind都还比较容易理解,一个是正向匹配,一个是逆向匹配,后面的参数pos都是用来指定起始查找位置。 对于find_first_of和find_last_of就不是那么好理解。 find_first_of是给定一个要查找的字符集,找到这个字符集中任何一个字符所在字符串中第一个位置。 或许看一个例子更容易明白。 有这样一个需求: 过滤一行开头和结尾的所有非英文字符。 看看用string如何实现: ? ViewCodeCPP #include #include usingnamespacestd; intmain() { stringstrinfo="//*---HelloWord! ......------"; stringstrset="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; intfirst=strinfo.find_first_of(strset); if(first==string: : npos) { cout<<"notfindanycharacters"< return-1; } intlast=strinfo.find_last_of(strset); if(last==string: : npos) { cout<<"notfindanycharacters"< return-1; } cout< return0; } 这里把所有的英文字母大小写作为了需要查找的字符集,先查找第一个英文字母的位置,然后查找最后一个英文字母的位置,然后用substr来的到中间的一部分,用于输出结果。 下面就是其结果: ? ViewCodeCPP HelloWord 前面的符号和后面的符号都没有了。 像这种用法可以用来查找分隔符,从而把一个连续的字符串分割成为几部分,达到shell命令中的awk的用法。 特别是当分隔符有多个的时候,可以一次指定。 例如有这样的需求: ? ViewCodeCPP 张三|3456123,湖南 李四,4564234|湖北 王小二,4433253|北京 ... 我们需要以“|”“,”为分隔符,同时又要过滤空格,把每行分成相应的字段。 可以作为你的一个作业来试试,要求代码简洁。 1.3stringinsert,replace,erase 了解了string的操作符,查找函数和substr,其实就已经了解了string的80%的操作了。 insert函数,replace函数和erase函数在使用起来相对简单。 下面以一个例子来说明其应用。 string只是提供了按照位置和区间的replace函数,而不能用一个string字串来替换指定string中的另一个字串。 这里写一个函数来实现这个功能: ? ViewCodeCPP 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.replace(pos,srclen,strdst); pos+=dstlen; } } 看看如何调用: ? ViewCodeCPP #include #include usingnamespacestd; intmain() { stringstrinfo="ThisisWinter,Winterisaprogrammer.DoyouknowWinter? "; cout<<"Orignstringis: \n"< string_replace(strinfo,"Winter","wende"); cout<<"AfterreplaceWinterwithwende,thestringis: \n"< return0; } 其输出结果: ? ViewCodeCPP Orignstringis: ThisisWinter,Winterisaprogrammer.DoyouknowWinter? AfterreplaceWinterwithwende,thestringis: Thisiswende,wendeisaprogrammer.Doyouknowwende? 如果不用replace函数,则可以使用erase和insert来替换,也能实现string_replace函数的功能: ? ViewCodeCPP 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-style字符串 现在看了这么多例子,发现constchar*可以和string直接转换,例如我们在上面的例子中,使用 ? ViewCodeCPP string_replace(strinfo,"Winter","wende");来代用voidstring_replace(string&strBig,conststring&strsrc,conststring&strdst) 在C语言中只有char*和constchar*,为了使用起来方便,string提供了三个函数满足其要求: ? ViewCodeCPP 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()函数干什么? 看看源码: ? ViewCodeCPP 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()得到字符串,每调用一次,下次再使用就会失效,如: ? ViewCodeCPP 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的参数: ? ViewCodeCPP template classAllocator=allocator classbasic_string { //... } char_traits不仅是在basic_string中有用,在basic_istream和basic_ostream中也需要用到。 就像SteveDonovan在过度使用C++模板中提到的,这些确实有些过头了,要不是系统自己定义了相关的一些属性,而且用了个typedef,否则还真不知道如何使用。 但复杂总有复杂道理。 有了char_traits,你可以定义自己的字符串类型。 当然,有了char_traits 如果你希望使用你自己定义的字符,你必须定义包含下列成员的结构: 表达式描述 ? ViewCodeCPP 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附录 ? ViewCodeCPP 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查找包含子串中的任何字符,返回
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- string 使用