Reputation: 15
I have a long sequence of segments separated by a delimiter say '-'. It is of the form:
I-am-logged-into-StackOverFlow-I-am-using-StackOverFlow-
I-am-reading-a-book-A-I-have-written-a-book-B-
The user specifies the segments that I have to compare.
Say, for string - 1, above: He inputs 5 and 9. Both contain StackOverFlow, so I return true.
For string - 2, segments 6, 12. But. they are different books A,B. So, I return false.
I have tried to do this using std::regex.
For all indices not entered by the user, I fill in those portions of a temporary string with
([^-]+)-, i.e. a string of one or more characters not containing a -, but ending with that.
For the two indices the user inputs,I face a problem. If I go with capturing groups and specify ([^-]+-) in the first index and use a \1 (or any nth capturing group) for the second index, the results are inconsistent. Book matches ANewBook which is not what is expected. In some cases, a- matches with not-.
Then I match the sentences above, with this temp string.
How do I check for equality - the characters from start to end, and the length of the substrings at the given indices?
Also, I find this question similar, but some of the results there are not consistent. Constructing a regular expression
PS: Considering the fact that it is easy to do a regex rather than extracting the segments at the given indices of a string and comparing the same, I would prefer the former. The number of string may run into hundreds.
Better solutions appreciated.
Upvotes: 1
Views: 266
Reputation: 5198
I agree with Marco A. Regular expressions are overkill for this job.
A running variant with 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:
*/
Upvotes: 0
Reputation: 43662
A possible solution (surely not the only one) could be to just use std::find and extract two substrings for comparison
(warning: the following code hasn't been extensively tested and might contain errors, it is intended as a concept idea for further refinement to suit your needs)
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;
}
Since this is (as I understood it) a "find-the-substring-at-nth-delimiter" problem, I wouldn't go for regex and leave those for more complex pattern matching tasks.
Upvotes: 1