There are a couple options as I see it: Either use regular expression, or go through the input character by character using some kind of state-machine.
Edit
About that state-machine... Maybe something like this:
// Pre-conditions: "str" is a std::string containing the whole string to be parsed
enum class states
{
GET_LENGTH, // Looking for the embedded string length
GET_LENGTH_OR_STRING, // Get the embedded string, or the length
GET_STRING, // Getting the embedded string
GET_NUMBER_1, // Look for the first number after the string
GET_NUMBER_2, // Look for the second number after the string
};
int len = 0; // Length of the embedded string
std::string tmp; // Temporary string
int n1, n2; // The numbers after the string
states state = GET_LENGTH;
for (auto ci = str.begin(); ci != str.end(); )
{
// Skip whitespace
while (isspace(*ci))
ci++;
switch (state)
{
case GET_LENGTH:
while (isdigit(*ci))
tmp += *ci++;
len = strtol(tmp.c_str(), nullptr, 10);
state = GET_LENGTH_OR_STRING;
break;
case GET_LENGTH_OR_STRING:
if (isdigit(*ci))
state = GET_LENGTH;
else
state = GET_STRING;
break;
case GET_STRING:
tmp = std::string(ci, ci + len);
ci += len;
tmp = "";
state = GET_NUMBER_1;
break;
case GET_NUMBER_1:
while (isdigit(*ci))
tmp += *ci++;
n1 = strtol(tmp.c_str(), nullptr, 10);
break;
case GET_NUMBER_2:
while (isdigit(*ci))
tmp += *ci++;
n2 = strtol(tmp.c_str(), nullptr, 10);
break;
}
}
Disclaimer: This is not tested, just written "as is" directly in the browser.
The code can probably be better, like the states for getting the length and the trailing numbers are basically the same and could be put in separate functions to share it.