Last active
April 21, 2016 21:50
-
-
Save elbeno/66e8c7905e1a1c0516a62933a44f7a5c to your computer and use it in GitHub Desktop.
Algorithms for dealing with delimited strings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <iostream> | |
#include <iterator> | |
#include <string> | |
#include <utility> | |
using namespace std; | |
template <typename FwdIt1, typename FwdIt2, typename T> | |
std::pair<FwdIt1, FwdIt1> find_delimited( | |
FwdIt1 first, FwdIt1 last, | |
FwdIt2 s_first, FwdIt2 s_last, const T& delimiter) | |
{ | |
// is the pattern at the beginning? | |
auto p = std::mismatch(s_first, s_last, first, last); | |
if (p.first == s_last) { | |
if (p.second == last || *p.second == delimiter) { | |
return { first, p.second }; | |
} | |
} | |
// does the pattern occur between two delimiters? | |
auto i = std::find(p.second, last, delimiter); | |
while (i != last) { | |
p = std::mismatch(s_first, s_last, std::next(i), last); | |
if (p.first == s_last) { | |
if (p.second == last || *p.second == delimiter) { | |
return { i, p.second }; | |
} | |
} | |
i = std::find(p.second, last, delimiter); | |
} | |
// not found | |
return { last, last }; | |
} | |
template <typename FwdIt1, typename FwdIt2, typename T> | |
std::pair<FwdIt1, FwdIt1> bring_to_front_delimited( | |
FwdIt1 front, FwdIt1 first, FwdIt1 last, | |
FwdIt2 s_first, FwdIt2 s_last, const T& delimiter) | |
{ | |
// find the pattern | |
auto p = find_delimited(first, last, s_first, s_last, delimiter); | |
// do we have a delimiter at the front? if so, one rotate is sufficient | |
bool b = front != last && *front == delimiter; | |
// rotate it to the front | |
auto r = std::rotate(front, p.first, p.second); | |
// if it's preceded by a delimiter, rotate the delimiter to the end | |
if (!b && front != last && *front == delimiter) { | |
r = std::rotate(front, std::next(front), r); | |
} | |
// return the point after it (possibly the next front) and where it came from | |
// (the next first to start searching at) | |
return { r, p.second }; | |
} | |
int main(void) | |
{ | |
string s = "foo,alpha,bravo,charlie,foo,delta,,echo,foo,foo,foxtrot,golf,foo"; | |
string to_find = "foo"; | |
auto p = bring_to_front_delimited(s.begin(), s.begin(), s.end(), | |
to_find.cbegin(), to_find.cend(), ','); | |
while (p.second != s.end()) | |
{ | |
p = bring_to_front_delimited(p.first, p.second, s.end(), | |
to_find.cbegin(), to_find.cend(), ','); | |
} | |
std::cout << s << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment