Почему моя функция извлечения строк, использующая обратную ссылку в регулярном выражении, не работает должным образом?

#c #regex #string

#c #регулярное выражение #строка

Вопрос:

Функция Извлечения

 string extractStr(string str, string regExpStr) {  regex regexp(regExpStr);  smatch m;  regex_search(str, m, regexp);  string result = "";  for (string x : m)  result = result   x;  return result; }  

Основной Код

 #include lt;iostreamgt; #include lt;regexgt;  using namespace std;  string extractStr(string, string);  int main(void) {  string test = "(1 1)*(n n)";  cout lt;lt; extractStr(test, "n\ n") lt;lt; endl;  cout lt;lt; extractStr(test, "(\d)\ \1") lt;lt; endl;  cout lt;lt; extractStr(test, "([a-zA-Z])[ -/*]\1") lt;lt; endl;  cout lt;lt; extractStr(test, "([a-zA-Z])[ -/*]([a-zA-Z])") lt;lt; endl;  return 0; }  

Вывод

 String = (1 1)*(n n) n n = n n (d) 1 = 1 11 ([a-zA-Z])[ -/*]1 = n nn ([a-zA-Z])[ -/*]([a-zA-Z]) = n nnn  

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

Комментарии:

1. Ожидаемый результат?

2. for (string x : m) не будет перебирать разные совпадения, но о группах текущего совпадения so m[0] (всего совпадения), и m[1] .. m[n] (группа из ( .. ) ).

Ответ №1:

Регулярные выражения в C работают не совсем так, как «обычные» регулярные выражения. Особенно, если позже вы будете искать несколько групп. У меня также есть несколько советов по C здесь (постоянство и ссылки).

 #include lt;cassertgt; #include lt;iostreamgt; #include lt;sstreamgt; #include lt;regexgt; #include lt;stringgt;   // using namespace std; don't do this! // https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice  // pass strings by const reference // 1. const, you promise not to change them in this function // 2. by reference, you avoid making copies  std::string extractStr(const std::stringamp; str, const std::stringamp; regExpStr) {  std::regex regexp(regExpStr);  std::smatch m;  std::ostringstream os; // streams are more efficient for building up strings   auto begin = str.cbegin();  bool comma = false;   // C   matches regexes in parts so work you need to loop  while (std::regex_search(begin, str.end(), m, regexp))  {  if (comma) os lt;lt; ", ";  os lt;lt; m[0];  comma = true;  begin = m.suffix().first;  }   return os.str(); }  // small helper function to produce nicer output for your tests. void test(const std::stringamp; input, const std::stringamp; regex, const std::stringamp; expected) {    auto output = extractStr(input, regex);  if (output == expected)  {  std::cout lt;lt; "test succeeded : output = " lt;lt; output lt;lt; "n";  }  else  {  std::cout lt;lt; "test failed : output = " lt;lt; output lt;lt; ", expected : " lt;lt; expected lt;lt; "n";  } }  int main(void) {  std::string input = "(1 1)*(n n)";    test(input, "n\ n", "n n");  test(input, "(\d)\ \1", "1 1");  test(input, "([a-zA-Z])[ -/*]\1", "n n");    return 0; }