C++正则表达式替换整个单词

C++ regex replace whole word

我有一个小游戏要做,有时我需要用句子中玩家的名字替换一些角色。

例如,我可以这样写一句话:

"[Player]! Are you okay? A plane crash happened, it's on fire!"

我需要用 std::string 中包含的某个名称替换“[Player]”。

我在其他 SO 问题和 CPP 参考资料中找了大约 20 分钟,但我真的无法理解如何使用正则表达式。

我想知道如何替换 std::string 中“[Player]”字符串的所有实例。

只需查找和替换,例如boost::replace_all()

#include <boost/algorithm/string.hpp>

std::string target(""[Player]! Are you okay? A plane crash happened, it's on fire!"");
boost::replace_all(target, "[Player]", "NiNite");

正如一些人提到的,查找和替换对于这种情况可能更有用,您可以这样做。

std::string name = "Bill";
std::string strToFind = "[Player]";
std::string str = "[Player]! Are you okay? A plane crash happened, it's on fire!";
str.replace(str.find(strToFind), strToFind.length(), name);

就我个人而言,我不会为此使用正则表达式。一个简单的搜索和替换就足够了。

这些是(大致)我使用的功能:

// change the string in-place
std::string& replace_all_mute(std::string& s,
    const std::string& from, const std::string& to)
{
    if(!from.empty())
        for(std::size_t pos = 0; (pos = s.find(from, pos) + 1); pos += to.size())
            s.replace(--pos, from.size(), to);
    return s;
}

// return a copy of the string
std::string replace_all_copy(std::string s,
    const std::string& from, const std::string& to)
{
    return replace_all_mute(s, from, to);
}

int main()
{
    std::string s = "[Player]! Are you okay? A plane crash happened, it's on fire!";

    replace_all_mute(s, "[Player]", "Uncle Bob");

    std::cout << s << '\n';
}

输出:

Uncle Bob! Are you okay? A plane crash happened, it's on fire!

正则表达式适用于更复杂的模式。考虑一下,例如,您想要匹配方括号之间的任何内容,而不是简单地匹配 [Player]。这将是正则表达式的一个很好的用途。

以下是执行此操作的示例。不幸的是,<regex> 的接口不够灵活,无法启用动态替换,所以我们必须自己实现实际替换。

#include <iostream>
#include <regex>

int main() {
    // Anything stored here can be replaced in the string.
    std::map<std::string, std::string> vars {
        {"Player1", "Bill"},
        {"Player2", "Ted"}
    };

    // Matches anything between brackets.
    std::regex r(R"(\[([^\]]+?)\])");

    std::string str = "[Player1], [Player1]! Are you okay? [Player2] said that a plane crash happened!";

    // We need to keep track of where we are, or else we would need to search from the start of
    // the string everytime, which is very wasteful.
    // std::regex_iterator won't help, because the replacement may be smaller
    // than the match, and it would cause strings like "[Player1][Player1]" to not match properly.
    auto pos=str.cbegin();
    do {
        // First, we try to get a match. If there's no more matches, exit.
        std::smatch m;
        regex_search(pos, str.cend(), m, r);
        if (m.empty()) break;

        // The interface of std::match_results is terrible. Let's get what we need and
        // place it in apropriately named variables.
        auto var_name = m[1].str();
        auto start = m[0].first;
        auto end = m[0].second;

        auto value = vars[var_name];

        // This does the actual replacement
        str.replace(start, end, value);

        // We update our position. The new search will start right at the end of the replacement.
        pos = m[0].first + value.size();
    } while(true);

    std::cout << str;
}

输出:

Bill, Bill! Are you okay? Ted said that a plane crash happened!

See it live on Coliru