程序最美(寻路)

你还在坚持练习你的技术吗?运动员天天训练,音乐家也会演练更难的曲章。你呢?

字符串替换

字符串替换

         C++ string 中有自带的replace替换函数,其替换方式有以下几种:

                                                              (http://www.cplusplus.com/reference/string/string/replace

         这几种方式都是只能针对某一个目标进行替换,不能对字符串中出现多次目标的情形进行全部替换。下面我们给出对字符串中所有目标进行替换的程序。

 

一、两种基本的全部替换方式

         比如给定一目标字符串(以下参考自Vimer):

12212

         我们将其中的“12”替换为“21”,有两种替换方式,分别为:

         1)进行distinct替换,即每次替换后,对替换后面的进行替换,不考虑替换后的字符序

列;

         2)每次替换后,再进行下一步替换时,考虑之前替换的字符序列;

         相应的两种替换方式替换后的结果分别为:

21221

22211

         两种替换方式的程序分别为:

// 字符串的两种替换方式
#include <iostream>
#include <string>
using namespace std;

string& replace_all_distinct(string& str, const string& src, const string& des)
{
    for (string::size_type i = 0; i != string::npos; i += des.size())
    {
        i = str.find(src, i);
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

string& replace_all_notdistinct(string& str, const string& src, const string& des)
{
    for (string::size_type i = 0; ; )
    {
        i = str.find(src); // 从头开始查找
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

int main()
{
    string str("12212");
    cout << replace_all_distinct(str, "12", "21") << endl;
    str = "12212";
    cout << replace_all_notdistinct(str, "12", "21") << endl;
    
    system("PAUSE");
    return 0;
}

 

         注意,第二种方式有可能造成死循环,比如对于12212,如果将12替换为212,那么将永远不会终止,因为对于12替换后的212,还会替换为2212、22212、222212……所以,对于这种替换方式,我们的原则是替换后的字符序列不能包含被替换的字符序列

 

二、一点改进

         接下来,我们做一点改进,就是指定替换的个数,我们设定一个参数,用来记录替换目标字符串的次数(参考自Mike_Zhang),这里我们可以按照从前到后的次序,也可以从后到前。具体程序如下:

// 定量替换&逆向替换
#include <iostream>
#include <string>
using namespace std;

string& replace_all_distinct(string& str, const string& src, const string& des, int n)
{
    int count = 0;
    for (string::size_type i = 0, count = 0; i != string::npos && count < n; i += des.size(), ++count)
    {
        i = str.find(src, i);
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

string& r_replace_all_distinct(string& str, const string& src, const string& des, int n)
{
    int count = 0;
    for (string::size_type i = str.size()-1, count = 0; i != string::npos && count < n; --i, ++count)
    {
        i = str.rfind(src, i);
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

string& replace_all_notdistinct(string& str, const string& src, const string& des, int n)
{
    int count = 0;
    for (string::size_type i = 0, count = 0; count < n; ++count)
    {
        i = str.find(src); // 从头开始查找
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

string& r_replace_all_notdistinct(string& str, const string& src, const string& des, int n)
{
    int count = 0;
    for (string::size_type i = str.size()-1, count = 0; count < n; ++count)
    {
        i = str.rfind(src); // 从尾开始查找
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

int main()
{
    string str("abababababab");
    cout << replace_all_distinct(str, "ab", "xy", 3) << endl;
    str = "aababababab";
    cout << replace_all_notdistinct(str, "ab", "ba", 2) << endl;
    
    str = "abababababab";
    cout << r_replace_all_distinct(str, "ab", "xy", 3) << endl;
    str = "ababababaab";
    cout << r_replace_all_notdistinct(str, "ab", "ba", 2) << endl;
    
    system("PAUSE");
    return 0;
}

 

三、批量替换

         前面我们做的替换是对字符串中所有出现目标序列进行的替换,但是我们只是针对单一的目标序列。这里我们将对多个目标序列进行替换操作。我们默认多个目标序列之间不存在包含、被包含、相等等关系。

         具体实现有以下两种方式:

1)针对每个待替换字符序列,顺序查找并替换。假如查找并替换依次的时间复杂度为

O(1),那么这种方式的时间复杂度为:O(N*M),其中N为待替换字符序列的个数,M为单个待替换序列出现的平均次数。

         2)另一种方式是:顺序扫描一次字符串,查找最早出现那个待替换字符序列的位置,

然后进行替换,这样针对每个出现的位置会查找N*M*N次,替换N*M次,所以时

间复杂度为O(N*M*N)。

         根据以上的分析,我们采用第一种替换方法:

// 逐个替换
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string& replace_all_distinct(string& str, const string& src, const string& des)
{
    for (string::size_type i = 0; i != string::npos; i += des.size())
    {
        i = str.find(src, i);
        if (i != string::npos)
        {
            str.replace(i, src.size(), des);
        }
        else
        {
            break;
        }
    }
    return str;
}

string& n_replace(string& str, const vector<string>& src, const vector<string>& des)
{
    assert(src.size() > 0 && src.size() == des.size());
    for (vector<string>::size_type i = 0; i != src.size(); ++i)
    {
        replace_all_distinct(str, src[i], des[i]);
    }
    return str;
}

int main()
{
    vector<string> src, des;
    src.push_back("+");
    src.push_back("-");
    src.push_back("*");
    src.push_back("/");
    src.push_back("(");
    src.push_back(")");
    
    des.push_back(" + ");
    des.push_back(" - ");
    des.push_back(" * ");
    des.push_back(" / ");
    des.push_back(" ( ");
    des.push_back(" ) ");

    string str("1+2-3*4/5+(1/3)");
    cout << n_replace(str, src, des) << endl;
    
    system("PAUSE");
    return 0;
}

 

四、总结

         以上我们对字符串两种基本的替换方式做了一些总结,并对其进行了一些改进,最后针对字符串做批量替换。

         通过批量替换,我们将运用到后面的针对表达式的空白符预处理,以绕开词法分析。

posted on 2013-07-19 12:14  unixfy  阅读(929)  评论(0编辑  收藏  举报

导航