Проверка строки на соответствие подстрок
У меня есть длинная последовательность сегментов, разделенных разделителем, скажем "-". Это имеет форму:
I-am-logged-into-StackOverFlow-I-am-using-StackOverFlow-
I-am-reading-a-book-A-I-have-written-a-book-B-
Пользователь указывает сегменты, которые я должен сравнить.
Скажем, для строки - 1, выше: он вводит 5 и 9. Оба содержат StackOverFlow, поэтому я возвращаю true.
Для строки - 2, сегменты 6, 12. Но. это разные книги А, Б. Итак, я вернул false.
Я пытался сделать это с помощью std:: regex.
Для всех индексов, не введенных пользователем, я заполняю эти части временной строки с помощью
([^ -] +) -, то есть строка из одного или нескольких символов, не содержащая -, но заканчивающаяся этим.
Для двух индексов пользовательских входов я сталкиваюсь с проблемой. Если я пойду с группами захвата и укажу ([^-]+-) в первом индексе и использую \ 1 (или любую n-ую группу захвата) для второго индекса, результаты будут противоречивыми. Книга соответствует ANewBook, что не то, что ожидается. В некоторых случаях a- соответствует not-.
Затем я сопоставляю приведенные выше предложения с этой временной строкой.
Как проверить на равенство - символы от начала до конца и длину подстрок при заданных индексах?
Кроме того, я нахожу этот вопрос похожим, но некоторые результаты там не соответствуют. Построение регулярного выражения
PS: Учитывая тот факт, что легко сделать регулярное выражение, а не извлекать сегменты по заданным индексам строки и сравнивать их, я бы предпочел первое. Количество строк может исчисляться сотнями.
Лучшие решения приветствуются.
2 ответа
Возможное решение (конечно, не единственное) может состоять в том, чтобы просто использовать std::find и извлечь две подстроки для сравнения
(предупреждение: следующий код не был тщательно протестирован и может содержать ошибки, он предназначен в качестве концепции для дальнейшего уточнения в соответствии с вашими потребностями)
bool match_positions(const std::string& str, int p1, int p2) {
int wordNo = 1;
size_t beg = 0, pos;
std::string first, second;
while ((pos = str.find('-', beg)) != std::string::npos ||
(first.empty() && second.empty()) ) {
if (wordNo == p1)
first = str.substr(beg, pos - beg);
if (wordNo == p2)
second = str.substr(beg, pos - beg);
beg = pos + 1;
++wordNo;
}
if (first.empty() || second.empty())
return false;
else
if (!first.compare(second))
return true;
else
return false;
}
Поскольку это (как я понял) проблема "найти подстроку-на-н-делитере", я бы не стал использовать регулярные выражения и оставить их для более сложных задач сопоставления с образцом.
Я согласен с Марко А. Регулярные выражения для этой работы излишни. Бегущий вариант с istringstream
:
#include<iostream>
#include<string>
#include<sstream>
#include<limits>
bool equalSubStr(const std::string& str, int i1, int i2, char sep) {
std::istringstream ss(str);
std::string sub1, sub2;
int i=1;
if( i1 > i2 )
std::swap(i1,i2);
auto advance = [&ss,sep](int &i, int iLim) {
for(; i!=iLim; i++) {
if(!ss.ignore(std::numeric_limits<std::streamsize>::max(),sep))
return false;
}
return true;
};
if( ( advance(i,i1)
&& std::getline(ss,sub1,sep)
&& advance(++i,i2)
&& std::getline(ss,sub2,sep) ) )
return sub1 == sub2;
return false;
}
int main()
{
std::string str1="I-am-logged-into-StackOverFlow-I-am-using-StackOverFlow-";
int i1=5;
int i2=9;
if( equalSubStr(str1,5,9,'-') )
std::cout << "\nSubstrings 5 and 9 are equal.";
if( equalSubStr(str1,1,6,'-') )
std::cout << "\nSubstrings 1 and 6 are equal.";
if( !equalSubStr(str1,2,3,'-') )
std::cout << "\nSubstrings 2 and 3 are not equal.";
return 0;
}
/*
Local Variables:
compile-command: "g++ --std=c++11 test.cc -o ./test.exe && ./test.exe"
End:
*/