【问题标题】:std::string replace "&" with "&" [duplicate]std::string 用“&”替换“&”[重复]
【发布时间】:2016-06-03 02:09:11
【问题描述】:

我必须在字符串中用& 替换所有出现的&。 但是如果&后面跟着;,即如果&&engrave;等,我必须跳过它。它是不被修改的。

我已经写了following code,它似乎运行良好,但我认为我进行了太多比较 - 有更好的方法吗?我可以使用 boost 或 c++11。

#include <string>
#include <iostream>

int main()
{
    std::string str = "An R&D string with one more R&amp;D here and S&D or T&engrave; Some More T&D and &amp;&engrave; and R&&D";
    std::cout<<"original string is : "<<str<<std::endl;
    int index = 0;
    while(1)
    {
        std::string::size_type n = str.find("&",index);
        if(n == std::string::npos)
            break;
        std::string sub = str.substr(n+1, 10);
        std::string::size_type m = sub.find("&");
        std::string::size_type b = sub.find(";");
        if(m != std::string::npos && m<b)
        {
            auto temp = sub.substr(0,m-1);
            sub = temp;
        }
        if(sub.find(";") == std::string::npos)
        {
            str.replace(n, 1, "&amp;");
        }
         index = n+1;
    }
    std::cout<<"changed string is : "<<str<<std::endl;
}

【问题讨论】:

  • 给定的逻辑显然无法替换 & 给定以下字符串“龙与地下城,以及分号,比如这个:;”。这是您的预期结果吗?
  • 对于提升,有boost::spirit::xml::encode
  • 你可能想使用正则表达式
  • "Dungeons &amp; colons ;" 怎么样 - 这里的预期结果是什么?
  • @IgorTandetnik 预期的输出是"Dungeons &amp;amp; colons ;"我错误地解释了这个问题。

标签: c++ c++11


【解决方案1】:

我认为这看起来像是 std::sregex_token_iterator 擅长的事情(尽管它可能不是最快的解决方案)。所以我想出了这个似乎可以完成这项工作的方法:

#include <regex>
#include <string>
#include <iostream>

int main()
{
    std::string str = "An R&D string with one more R&amp;D here and S&D or T&engrave; Some More T&D and &amp;&engrave; and R&&D";

    std::cout << str << '\n';

    // match HTML style entities aka &amp;
    std::regex e(R"(&\S+;)");

    // iterate through matches (0) and non-matches (-1)
    std::sregex_token_iterator itr(str.begin(), str.end(), e, {-1, 0});
    std::sregex_token_iterator end;

    for(; itr != end; ++itr)
    {
        std::string s = *itr;

        // replace the "&" in non-matching portions of the string
        if(!std::regex_match(s, e))
            s = std::regex_replace(s, std::regex("&"), "&amp;");

        std::cout << s;
    }
}

【讨论】:

  • 非常感谢.. 成功了:)
【解决方案2】:

主要的低效率在这里:

std::string sub = str.substr(n+1, 10);

任何时候你创建一个新的子串,都是非常低效的。次要的低效率是您正在使用 std::string::replace(),它必须移动字符串的尾部。在一般情况下,这会导致 O(N*N) 行为。

您的问题也有些定义不清。我认为这个规范可以改进为:

  • 将 & 替换为 &
  • 除非 & 后跟一系列以 ; 结尾的字母

以下代码相当有效:

std::string replace(const std::string& str) {
    std::string result;
    for (int i = 0; i < str.size(); i++) {
        char c = str[i];
        if (c != '&') {
            result += c;
            continue;
        }
        bool replace = false;
        bool haveAlpha = false;
        for (int j = i + 1; true; j++) {
            if (j >= str.size()) {
                replace = true;
                break;
            }
            char c2 = str[j];
            if (isalpha(c2)) {
                haveAlpha = true;
                continue;
            } else if (c2 == ';') {
                replace = !haveAlpha;
                break;
            } else {
                replace = true;
                break;
            }
        }
        if (replace) {
            result.append("&amp;");
        } else {
            result += c;
        }
    }
    return result;
}

int main()
{
    std::string str = "An R&D string with one more R&amp;D here and S&D or T&engrave; Some More T&D and &amp;&engrave; and R&&D";
    std::cout << "original string is : " << str << std::endl;
    std::cout << "replaced string is : " << replace(str) << std::endl;
    return 0;
}

它输出正确的东西,但当然 stackoverflow 想要解释所有这些漂亮的转义 :-) 你只需要运行它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    • 2013-05-11
    • 2012-12-02
    • 2013-09-10
    • 2012-10-31
    相关资源
    最近更新 更多