C ++ регулярное выражение заменить целое слово - PullRequest
0 голосов
/ 28 сентября 2018

У меня есть небольшая игра, в которой мне иногда нужно заменить какую-то группу персонажей именем игрока в предложениях.

Например, у меня может быть такое предложение:

"[Player]! С тобой все в порядке? Произошла авиакатастрофа, она горит!"

И мне нужно заменить "[Player]" на какое-то имя, содержащееся вstd :: string.

Я искал около 20 минут в других SO-вопросах и в справочнике по CPP, и я действительно не могу понять, как использовать регулярное выражение.

Я хотел быхотел бы знать, как я могу заменить все экземпляры строки "[Player]" в std :: string.

Ответы [ 4 ]

0 голосов
/ 28 сентября 2018

Regex предназначен для более сложных шаблонов.Например, учтите, что вместо простого сопоставления [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!

Посмотреть это в прямом эфире на Coliru

0 голосов
/ 28 сентября 2018

Как уже упоминали некоторые люди, поиск и замена могут быть более полезны для этого сценария, вы можете сделать что-то вроде этого.

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);
0 голосов
/ 28 сентября 2018

Лично я бы не использовал регулярные выражения для этого.Достаточно простого поиска и замены.

Это (примерно) используемые мной функции:

// 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!
0 голосов
/ 28 сентября 2018

Просто найдите и замените, например, 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");
...