【问题标题】:Replace a pattern in C++ 98替换 C++ 98 中的模式
【发布时间】:2015-08-20 05:03:54
【问题描述】:

我需要在特定模式的字符串中进行就地替换 示例:

输入:

temp.temp2.​​.temp3....temp4......temp5

输出:

temp.temp2.​​temp3.temp4.temp5

所以基本上如果是单点,就保持原样,但如果连续点多,就用单点代替。

我尝试迭代字符串并根据比较复制到另一个字符串对象中,现在它看起来真的很难看。 我想知道使用 C++ STL 有什么更好的方法吗?

【问题讨论】:

    标签: c++ string std c++98


    【解决方案1】:

    如果您需要坚持使用 C++98,可以使用 boost 正则表达式。

    #include <boost/regex.hpp>
    #include <iostream>
    
    int main()
    {
        std::string str = "....";
        boost::regex re("\\.{2,}");
        std::cout << regex_replace(str, re, ".") << std::cout;
    }
    

    如果你不能使用boost,我想到的最简单的解决方案是这样的:

    #include <iostream>
    #include <sstream>
    
    using namespace std;
    
    string replaceConsecutiveDots(const string& str) {
        std::stringstream ss;
        bool previousCharIsDot = false;
        for (string::const_iterator it = str.begin(); it!=str.end(); ++it) {
            char c = *it;
            if (c != '.' || !previousCharIsDot) {
                ss << c;
            }
            previousCharIsDot = c == '.';
        }
        return ss.str();
    }
    
    int main() {
        string str = "temp.temp2..temp3....temp4......temp5";
        cout << replaceConsecutiveDots(str) << endl;
    }
    

    【讨论】:

    • 是的,当 lambda 不可用时,我喜欢 boost regex,但不幸的是,由于一些遗留代码问题,必须坚持使用经典的 stl 和 std::string 对象。或者我可以使用 posix 正则表达式,但这不会解决这个特定问题
    • 我添加了另一个没有提升的解决方案。查看我的编辑。
    【解决方案2】:

    这是一项微不足道的任务。

    std::string convert(const std::string& src) {
        std::string dst;
        for (std::string::size_type i = 0; i < src.size(); ++i) {
            if (src[i] == '.' && dst.size() && dst[dst.size() - 1] == '.') continue;
            dst.push_back(src[i]);
        }
        return dst;
    }
    

    使用 C++11,您可以将丑陋的 dst[dst.size() - 1] 替换为 dst.back()

    【讨论】:

    • 至少reserve 提前一些字节,想想这个字符串必须进行的 O(N) 分配让我的胃颤抖..
    • @DavidHaim 这不是O(N) 分配。如果是这样,push_back 的摊销恒定时间将是不可能的。无论如何,你可以提前reserve这个空间,在一定程度上提高效率。
    【解决方案3】:

    算法不应该长或丑。它应该是简单而干净的。

    伪代码

    from pos 0 to string.length -1
      do 
      if string[pos] is '.'
        if string[pos+1] is '.' 
           do 
            erase string[pos+1] while string[pos+1] is '.'  
    

    真正的 C++ 示例:

    void cleanStringDots(string& str){
        for (int i=0;i<str.size()-1;i++){
          if (str[i] == '.' && str[i+1] == '.'){
               size_t count = 1;
               for (int j = i+2; j<str.size() && str[j] =='.';j++){
                   if (str[j]=='.') {
                      count++; 
                      }  
                 }
                 str.erase(i+1,count);
            }
        }    
    }
    
    int main(){
      string str = "temp.temp2..temp3....temp4......temp5";
      cleanStringDots(str);
      cout<<str;
    }
    

    可以在这里运行:http://coliru.stacked-crooked.com/a/aa6923d4049a1fdd

    【讨论】:

    • 是的,它与我所做的非常接近,但感谢并为此 +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    相关资源
    最近更新 更多