Замените каждый элемент по-разному, regex c ++ - PullRequest
0 голосов
/ 25 октября 2019

У меня длинная строка, и мне нужно преобразовать цифры в слова (например, с 5 по 5). Могу ли я сделать это с помощью регулярного выражения? Я попытался использовать regex_replace, но это изменило все числа на те, которые были найдены первыми (например, он преобразовал «5 10 1 0» в «пять пять пять пять», но мне нужно «пять десять один ноль»).

Это была моя попытка:

    string text ="a lot of text";
    regex pattern("(\\d)+");
    smatch result;

    int x; string buffer;

    while (regex_search(text, result, pattern))
    {
        buffer = result[0];
        x = atoi(buffer.c_str());

        switch (x)
        {
        case 0: text = regex_replace(text, pattern, numbers[0]); break;
        case 1: text = regex_replace(text, pattern, numbers[1]); break;
        case 2: text = regex_replace(text, pattern, numbers[2]); break;
        case 3: text = regex_replace(text, pattern, numbers[3]); break;
        case 4: text = regex_replace(text, pattern, numbers[4]); break;
        case 5: text = regex_replace(text, pattern, numbers[5]); break;
        case 6: text = regex_replace(text, pattern, numbers[6]); break;
        case 7: text = regex_replace(text, pattern, numbers[7]); break;
        case 8: text = regex_replace(text, pattern, numbers[8]); break;
        case 9: text = regex_replace(text, pattern, numbers[9]); break;
        case 10: text = regex_replace(text, pattern, numbers[10]); break;
        }
        text = result.suffix().str();
    }

Ответы [ 3 ]

1 голос
/ 25 октября 2019

std::regex_replace заменяет все вхождения регулярного выражения, поэтому при первом вызове он заменяет все цифры первым соответствием.

Вместо этого вам нужно перебрать совпадения и добавить правильную замену кoutput.

Примерно так:

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

int main() {
    std::string text = "before 5 10 1 11 after";
    std::string numbers[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
    std::regex pattern("\\d+");

    std::string result;

    std::smatch match;
    auto begin = text.cbegin();
    while (std::regex_search(begin, text.cend(), match, pattern)) {
        result += match.prefix(); // copy the substring before the match
        int x = std::stoi(match[0]);
        if (x >= 0 && x <= 10) {
            result += numbers[x];
        } else {
            result += match[0]; // a number but out-of-range - copy it as-is
        }
        begin += match.position() + match.length();
    }
    result += match.suffix(); // copy the substring after the last match
    if (result.empty()) {
        result = text; // special case - nothing matched
    }

    std::cout << result << std::endl;

}

В отличие от других решений, это итерирует ввод только один раз, поэтому он будет намного быстрее, особенно для длинных строк.

1 голос
/ 25 октября 2019

Причина, по которой вы получаете «пять пять пять», состоит в том, что 5 - первое совпадение в поиске регулярных выражений, но, поскольку ваш шаблон \ d + (каждая цифра), он заменит все совпадения на «пять»

Таким образом, вы можете просто сделать regex_replace для каждой цифры, которую хотите заменить

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

using namespace std;


int main(int, char**) {

    auto numbers = array{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};

    string text = "6 18 2 3 4 5 2 0 0 1 4 10 19 9 1nin1ja xd3 10";

    for (size_t i = 0; i < numbers.size(); ++i) {
        regex pattern("\\b" + std::to_string(i) + "\\b");
        text = regex_replace(text, pattern, numbers[i]);
    }

    cout << text << endl; //six 18 two three four five two zero zero one four ten 19 nine 1nin1ja xd3 ten

    return 0;
}
0 голосов
/ 25 октября 2019

Следующий код сделает то, что вы просите. Это не очень эффективно, потому что он находит число дважды (один раз с std::regex_search, один раз с std::string::find), но он заменит цифры 0 - 10 словами ноль - десять.

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

int main()
{
  std::vector<std::string> numbers {
    "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; 
  std::string text = "These numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 are text now";
  std::string tmp_text = text;
  std::regex pattern("(\\d)+");
  std::smatch result;
  int n;
  std::string buffer;
  std::size_t pos;

  while (std::regex_search(tmp_text, result, pattern))
  {
    buffer = result[0];
    n = atoi(buffer.c_str());

    switch (n)
    {
    case 0:
      pos = text.find('0');
      text.replace(pos, 1, numbers[0]);
      break;
    case 1:
      pos = text.find('1');
      text.replace(pos, 1, numbers[1]);
      break;
    case 2:
      pos = text.find('2');
      text.replace(pos, 1, numbers[2]);
      break;
    case 3:
      pos = text.find('3');
      text.replace(pos, 1, numbers[3]);
      break;
    case 4:
      pos = text.find('4');
      text.replace(pos, 1, numbers[4]);
      break;
    case 5:
      pos = text.find('5');
      text.replace(pos, 1, numbers[5]);
      break;
    case 6:
      pos = text.find('6');
      text.replace(pos, 1, numbers[6]);
      break;
    case 7:
      pos = text.find('7');
      text.replace(pos, 1, numbers[7]);
      break;
    case 8:
      pos = text.find('8');
      text.replace(pos, 1, numbers[8]);
      break;
    case 9:
      pos = text.find('9');
      text.replace(pos, 1, numbers[9]);
      break;
    case 10:
      pos = text.find("10");
      text.replace(pos, 2, numbers[10]);
      break;
    }
    tmp_text = result.suffix().str();
  }

  std::cout << text << std ::endl;
}

// output:
// These numbers: zero, one, two, three, four, five, six, seven, eight, nine, ten are text now
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...