zoukankan      html  css  js  c++  java
  • 字符串替换

    字符串替换

             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;
    }

    四、总结

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

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

  • 相关阅读:
    【收集】各种hack
    CSS测试实录一:display的块状元素和行内元素的试验
    【转载加工】:after伪类+content内容生成经典应用举例
    CSS测试实录二:float和标准流
    onreadyStateChange&nbsp;&nbsp;DOMContentLoaded
    Extensions
    Accessing of Rows in Silverlight DataGrid
    Linux应用程序的装载和执行
    top状态细分,进程状态
    定时器的使用和原理浅析,alarm/sleep函数
  • 原文地址:https://www.cnblogs.com/unixfy/p/3200305.html
Copyright © 2011-2022 走看看