STL--string用法(2)

 

  •  
    1. 系统遇到"+"号,发现有一项是string 对象。
    2. 系统把另一项转化为一个临时 string 对象。
    3. 执行 operator + 操作,返回新的临时string 对象。
    4. 如果又发现"+"号,继续第一步操作。
  •  

    1 string 使用

    其实,string并不是一个单独的容器,只是basic_string 模板类的一个typedef 而已,相对应的还有wstring, 你在string 头文件中你会发现下面的代码:

     

    extern "C++" {

    typedef basic_string <char> string;

    typedef basic_string <wchar_t> wstring;

    } // extern "C++"

    由于只是解释string的用法,如果没有特殊的说明,本文并不区分string 和 basic_string的区别。

    string 其实相当于一个保存字符的序列容器,因此除了有字符串的一些常用操作以外,还有包含了所有的序列容器的操作。字符串的常用操作包括:增加、删除、修改、查找比较、链接、输入、输出等。详细函数列表参看附录。不要害怕这么多函数,其实有许多是序列容器带有的,平时不一定用的上。

    如果你要想了解所有函数的详细用法,你需要查看basic_string,或者下载STL编程手册。这里通过实例介绍一些常用函数。

    1.1 充分使用string 操作符

    string 重载了许多操作符,包括 +, +=, <, =, , [], <<, >>等,正式这些操作符,对字符串操作非常方便。先看看下面这个例子:tt.cpp(例程2)

     

    #include <string>

    #include <iostream>

    using namespace std;

    int main(){

    string strinfo="Please input your name:";

    cout << strinfo ;

    cin >> strinfo;

    if( strinfo == "winter" )

    cout << "you are winter!"<<endl;

    else if( strinfo != "wende" )

    cout << "you are not wende!"<<endl;

    else if( strinfo < "winter")

    cout << "your name should be ahead of winter"<<endl;

    else

    cout << "your name should be after of winter"<<endl;

    strinfo += " , Welcome to China!";

    cout << strinfo<<endl;

    cout <<"Your name is :"<<endl;

    string strtmp = "How are you? " + strinfo;

    for(int i = 0 ; i < strtmp.size(); i ++)

    cout<<strtmp[i];

    return 0;

    }

    下面是程序的输出

     

    -bash-2.05b$ make tt

    c++  -O -pipe -march=pentiumpro  tt.cpp  -o tt

    -bash-2.05b$ ./tt

    Please input your name:Hero

    you are not wende!

    Hero , Welcome to China!

    How are you? Hero , Welcome to China!

    有了这些操作符,在STL中仿函数都可以直接使用string作为参数,例如 less, great, equal_to 等,因此在把string作为参数传递的时候,它的使用和int 或者float等已经没有什么区别了。例如,你可以使用:

     

    map<string, int> mymap;

    //以上默认使用了 less<string>

    有了 operator + 以后,你可以直接连加,例如:

     

    string strinfo="Winter";

    string strlast="Hello " + strinfo + "!";

    //你还可以这样:

    string strtest="Hello " + strinfo + " Welcome" + " to China" + " !";

    看见其中的特点了吗?只要你的等式里面有一个 string 对象,你就可以一直连续"+",但有一点需要保证的是,在开始的两项中,必须有一项是 string 对象。其原理很简单:

    由于这个等式是由左到右开始检测执行,如果开始两项都是const char* ,程序自己并没有定义两个const char* 的加法,编译的时候肯定就有问题了。

    有了操作符以后,assign(), append(), compare(), at()等函数,除非有一些特殊的需求时,一般是用不上。当然at()函数还有一个功能,那就是检查下标是否合法,如果是使用:

     

    string str="winter";

    //下面一行有可能会引起程序中断错误

    str[100]='!';

    //下面会抛出异常:throws: out_of_range

    cout<<str.at(100)<<endl;

    了解了吗?如果你希望效率高,还是使用[]来访问,如果你希望稳定性好,最好使用at()来访问。

    1.2 眼花缭乱的string find 函数

    由于查找是使用最为频繁的功能之一,string 提供了非常丰富的查找函数。其列表如下:

    函数名

    描述

    find

    查找

    rfind

    反向查找

    find_first_of

    查找包含子串中的任何字符,返回第一个位置

    find_first_not_of

    查找不包含子串中的任何字符,返回第一个位置

    find_last_of

    查找包含子串中的任何字符,返回最后一个位置

    find_last_not_of

    查找不包含子串中的任何字符,返回最后一个位置

    以上函数都是被重载了4次,以下是以find_first_of 函数为例说明他们的参数,其他函数和其参数一样,也就是说总共有24个函数 :

     

    size_type find_first_of(const basic_string& s, size_type pos = 0)

    size_type find_first_of(const charT* s, size_type pos, size_type n)

    size_type find_first_of(const charT* s, size_type pos = 0)

    size_type find_first_of(charT c, size_type pos = 0)

    所有的查找函数都返回一个size_type类型,这个返回值一般都是所找到字符串的位置,如果没有找到,则返回string::npos。有一点需要特别注意,所有和string::npos的比较一定要用string::size_type来使用,不要直接使用int 或者unsigned int等类型。其实string::npos表示的是-1, 看看头文件:

     

    template <class _CharT, class _Traits, class _Alloc>

    const basic_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 如何实现:

     

    #include <string>

    #include <iostream>

    using namespace std;

    int main(){

    string strinfo="   //*---Hello Word!......------";

    string strset="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    int first = strinfo.find_first_of(strset);

    if(first == string::npos) {

    cout<<"not find any characters"<<endl;

    return -1;

    }

    int last = strinfo.find_last_of(strset);

    if(last == string::npos) {

    cout<<"not find any characters"<<endl;

    return -1;

    }

    cout << strinfo.substr(first, last - first + 1)<<endl;

    return 0;

    }

    这里把所有的英文字母大小写作为了需要查找的字符集,先查找第一个英文字母的位置,然后查找最后一个英文字母的位置,然后用substr 来的到中间的一部分,用于输出结果。下面就是其结果:

     

    Hello Word

    前面的符号和后面的符号都没有了。像这种用法可以用来查找分隔符,从而把一个连续的字符串分割成为几部分,达到 shell 命令中的 awk 的用法。特别是当分隔符有多个的时候,可以一次指定。例如有这样的需求:

     

    张三|3456123, 湖南

    李四,4564234| 湖北

    王小二, 4433253|北京

    ...

    我们需要以 "|" ","为分隔符,同时又要过滤空格,把每行分成相应的字段。可以作为你的一个家庭作业来试试,要求代码简洁

    1.3 string insert, replace, erase

    了解了string 的操作符,查找函数和substr,其实就已经了解了string的80%的操作了。insert函数, replace函数和erase函数在使用起来相对简单。下面以一个例子来说明其应用。

    string只是提供了按照位置和区间的replace函数,而不能用一个string字串来替换指定string中的另一个字串。这里写一个函数来实现这个功能:

     

    void string_replace(string & strBig, const string & strsrc, const string &strdst) {

    string::size_type pos=0;

    string::size_type srclen=strsrc.size();

    string::size_type dstlen=strdst.size();

    while( (pos=strBig.find(strsrc, pos)) != string::npos){

    strBig.replace(pos, srclen, strdst);

    pos += dstlen;

    }

    }

    看看如何调用:

     

    #include <string>

    #include <iostream>

    using namespace std;

    int main() {

    string strinfo="This is Winter, Winter is a programmer. Do you know Winter?";

    cout<<"Orign string is :/n"<<strinfo<<endl;

    string_replace(strinfo, "Winter", "wende");

    cout<<"After replace Winter with wende, the string is :/n"<<strinfo<<endl;

    return 0;

    }

    其输出结果:

     

    Orign string is :

    This is Winter, Winter is a programmer. Do you know Winter?

    After replace Winter with wende, the string is :

    This is wende, wende is a programmer. Do you know wende?

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

     

    void string_replace(string & strBig, const string & strsrc, const string &strdst) {

    string::size_type pos=0;

    string::size_type srclen=strsrc.size();

    string::size_type dstlen=strdst.size();

    while( (pos=strBig.find(strsrc, pos)) != string::npos){

    strBig.erase(pos, srclen);

    strBig.insert(pos, strdst);

    pos += dstlen;

    }

    }

    当然,这种方法没有使用replace来得直接。

     

    源文档 <http://blog.chinaunix.net/u2/87718/showart_1834935.html>

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值