У меня есть несколько проблем с моим алгоритмом, пытаясь получить позиции совпадений регулярных выражений в строке. Пожалуйста, найдите код здесь - https://godbolt.org/z/aj8Gq4Moh
std::vector<int> mval;
int closed_val = 0;
int open_val = 0;
std::string da_line = "} } }";
std::smatch m;
std::regex_search(da_line, m, std::regex("([\\}]+)"));
for (auto mv : m) std::cout << mv << std::endl;
std::cout << m.size() << std::endl;
closed_val = da_line.find(m[0]);
mval.push_back(closed_val);
try {
if (m.size() >= 1) {
std::string db_line;
for (int j = 1; j < m.size(); j++) {
std::cout << da_line << std::endl;
db_line = da_line.substr(da_line.find(m[j]) + 1, da_line.size() - 1);
std::cout << db_line << std::endl;
int f = db_line.find(m[j]);
if (f == -1 || f > db_line.size() - 1)
continue;
std::cout << f << std::endl;
open_val = closed_val + f + 1;
for (auto mv : m) std::cout << mv << std::endl;
std::cout << db_line.find(m[j + 1]) << std::endl;
mval.push_back(open_val);
closed_val = open_val;
da_line = db_line;
}
}
}
catch (std::exception& error) {
std::cerr << "error : " << error.what() << std::endl;
}
for (auto mv : mval) std::cout << mv << ":";
std::cout << std::endl;
Выход:
}
}
2
} } }
} }
1
}
}
0
0:2:
У вас базовое непонимание функции std::regex_search
. Он будет искать только 1 совпадение (или ничего). Пожалуйста, прочитайте еще раз здесь.
Также std::match_results
работает совершенно по-другому. Но в описании std::regex_search есть действительно хорошее объяснение.
Пожалуйста, обрати внимание:
Если для вашего регулярного выражения можно найти совпадение, в основном для '}', m.size()
будет 2, и только m[0]
будет релевантным.
std::match_results
будет содержать более одного результата, только если есть более 1 подсовпадения. Например, с регулярным выражением "a|b" у вас может быть 2 элемента.
Вы должны следовать части «Примечания» в описании функции.
Чтобы проверить все совпадения в целевой последовательности, std::regex_search может вызываться в цикле, каждый раз перезапускаясь с m[0].second предыдущего вызова. std::regex_iterator предлагает простой интерфейс для этой итерации.
И, в принципе, для вашего конкретного желания найти позиции '}' в строке вам вообще не понадобится std::regex_search
. .find()
в цикле было бы вполне достаточно.
Но я понимаю, что вы хотите использовать более общий подход "regex".
На данный момент я не вижу хорошего решения. Однако для вашего примера будет работать следующее:
#include <iostream>
#include <string>
#include <regex>
int main() {
// We want to search in this string
std::string line{ " abx aby abz" };
// regex for search a }
const std::regex re{ R"(ab?)" };
// Here we will store the running position
std::size_t position{};
// Search all occurences of regex in the given string
for (std::smatch sm; std::regex_search(line, sm, re); line = sm.suffix()) {
// Search the character and add to current position
position += line.find(sm[0]);
// Show result
std::cout << position << ' ';
// Take length of regex into account
position += std::string(sm[0]).size();
}
}
Отличный пример! Спасибо за подсказку Гурнет.
Чтобы найти все совпадения во входных данных, вы обычно хотите использовать regex_iterator
(в данном случае конкретно sregex_iterator
), что-то в следующем порядке:
#include <regex>
#include <iostream>
#include <string>
int main() {
std::string s = "} } }";
std::regex pattern("([\\}]+)");
auto begin = std::sregex_iterator {s.begin(), s.end(), pattern};
auto end = std::sregex_iterator();
for (std::sregex_iterator i = begin; i != end; ++i)
{
std::cout << "Found match at position: " << i->position() << "\n";
}
}
Результат:
Found match at position: 0
Found match at position: 2
Found match at position: 4
Отличный пример, спасибо за совет, Джерри.
Пожалуйста, отредактируйте свой пост и вырежьте и вставьте код сюда.