Allow user to pass delimiter character by doubling it in C ++
I have a C ++ function that accepts strings in the following format:
<WORD>: [VALUE]; <ANOTHER WORD>: [VALUE]; ...
This is the function:
std::wstring ExtractSubStringFromString(const std::wstring String, const std::wstring SubString) {
std::wstring S = std::wstring(String), SS = std::wstring(SubString), NS;
size_t ColonCount = NULL, SeparatorCount = NULL; WCHAR Separator = L';';
ColonCount = std::count(S.begin(), S.end(), L':');
SeparatorCount = std::count(S.begin(), S.end(), Separator);
if ((SS.find(Separator) != std::wstring::npos) || (SeparatorCount > ColonCount))
{
// SEPARATOR NEED TO BE ESCAPED, BUT DON'T KNOW TO DO THIS.
}
if (S.find(SS) != std::wstring::npos)
{
NS = S.substr(S.find(SS) + SS.length() + 1);
if (NS.find(Separator) != std::wstring::npos) { NS = NS.substr(NULL, NS.find(Separator)); }
if (NS[NS.length() - 1] == L']') { NS.pop_back(); }
return NS;
}
return L"";
}
The above function outputs correctly MANGO
if I use it like:
ExtractSubStringFromString(L"[VALUE: MANGO; DATA: NOTHING]", L"VALUE")
However, if I have two output delimiters on the next line, I tried to double as ;;
, but I still get MANGO
instead of ;MANGO;
:
ExtractSubStringFromString(L"[VALUE: ;;MANGO;;; DATA: NOTHING]", L"VALUE")
Here the assignor of the values ββis a colon and the separator is a semicolon. I want to allow users to pass colons and semicolons to my function, doubling extra. Just as we avoid double quotes, single quotes, and more in many scripting and programming languages, and in parameters in many program commands.
I thought hard, but couldn't even think how to do it. Can anyone help me with this situation?
Thanks in advance.
source to share
You have to search the string for ;;
and replace it with either a temporary placeholder char
or string
which can later be specified and replaced with a value.
So basically:
1) Search by string and replace all instances ;;
with \tempFill
- It is best to choose a combination of characters that are unlikely to be in the original string.
2) Parsing the string
3) Replace all instances \tempFill
with;
Note. It would be wise to run an assertion on your line to make sure yours \tempFill
(or whatever you choose to be filler) is not on the original line to prevent a bug / malfunction / error. You can use the type character \n
and make sure there isn't in the original string.
Disclaimer: I can almost guarantee there are cleaner, more efficient ways to do this, but this is the easiest way to do it.
source to share
First, since the substring doesn't need to be delimited, I assume it doesn't need to pre-process the escaped delimiter filtering.
Then on the main string, the easiest way IMHO is to filter out the escaped delimiters when looking for them in the string. Pseudocode (assuming the attached one has []
been removed):
last_index = begin_of_string
index_of_current_substring = begin_of_string
loop: search a separator starting at last index - if not found exit loop
ok: found one at ix
if char at ix+1 is a separator (meaning with have an escaped separator
remove character at ix from string by copying all characters after it one step to the left
last_index = ix+1
continue loop
else this is a true separator
search a column in [ index_of_current_substring, ix [
if not found: error incorrect string
say found at c
compare key_string with string[index_of_current_substring, c [
if equal - ok we found the key
value is string[ c+2 (skip a space after the colum), ix [
return value - search is finished
else - it is not our key, just continue searching
index_of_current_substring = ix+1
last_index = index_of_current_substring
continue loop
Now it is easy to convert it to C ++
source to share