2

I have a "custom" string that has the following format. Example:

std::string MyString = "RndOrder%5d - RndCustomer%8s - RndHex%8x";

I would like to replace/parse the string:

  • the %5d (%NUM_d) would be replaced with a random 5-digit decimal

  • the %8s (%NUM_s) would be replaced with a random 8-chars

  • the %8x (%NUM_x) would be replaced with a random 8-digit hexadecimal

Is there any function that helps me parse those "special marks"? Not sure if I would have to parse the string char by char and check for every possible combination.

Krish Munot
  • 1,093
  • 2
  • 18
  • 29
raff
  • 339
  • 2
  • 12

3 Answers3

2

If the format can be variant (not always the fixed 3 arguments: %5d, %8s and %8x) and you want to be flexible in that manner, you should write your own implementation for that.

Assuming that count defined after % is a general digit (not only 5 or 8) you could try using the std::regex_search or std::regex_match to find the actual mnemonics you are looking for. For example your expression could look like %\d+[dsx]

Then you should parse it to find the COUNT and type and substitute with a random number acquired with the desired generator. To parse you could try updating the above expression to %(\d+)([dsx]) and capturing groups.

A sample parse implementation for your case could look like this:

std::string text = "RndOrder%5d - RndCustomer%8s - RndHex%8x";
auto reg = std::regex("%(\\d+)([sdx])");
std::smatch match;
while (std::regex_search(text, match, reg))
{
    const auto& full = match.str(); // in 1st iter contains "%5d"
    const auto& count = match.str(1); // in 1st iter contains "5"
    const auto& type = match.str(2); // in 1st iter contains "d"
    // further processing: type conversion, number generation, string replacement

    text = match.suffix().str();
}

For implementation example with search and group capturing you can also check out another question: Retrieving a regex search in C++

Community
  • 1
  • 1
Dusteh
  • 1,496
  • 16
  • 21
1

Ok, assuming that you're actually asking about string parsing here (and not random number/data generation)... have a look at this:

int iRandom1 = 12345;       // 5-digit decimal
int iRandom3 = 0x12345678;  // 8-digit hexadecimal
char cRandom2[9] = "RandomXY\0";  // Don't forget to NULL-terminate!
std::string sFormat = "RndOrder%5d - RndCustomer%8s - RndHex%8x";

char cResultBuffer[500];  // Make sure this buffer is big enough!

std::sprintf( cResultBuffer, sFormat.c_str(), iRandom1, cRandom2, iRandom3 );
std::string MyString = cResultBuffer;  // MyString = "RndOrder12345 - RndCustomerRandomXY - RndHex12345678";
Robin
  • 1,658
  • 15
  • 26
  • Where is string parsing in this answer? How did you detect formats of the arguments and number of digits/chars in generated values? – Qwertiy Dec 05 '16 at 12:21
  • Thanks! But that's for a fixed "format". I would like to accept other "sFormat" strings, like "rnd_id_%6d" – raff Dec 05 '16 at 12:32
1

It's a candidate for std::snprintf (c++14), but take care to request the correct buffer size in one call, allocate a buffer and then format the string into the buffer:

#include <iostream>
#include <cstring>
#include <string>

template<class...Args>
std::string replace(const char* format, Args const&... args)
{
    // determine number of characters in output
    auto len = std::snprintf(nullptr, 0, format, args...);

    // allocate buffer space
    auto result = std::string(std::size_t(len), ' ');

    // write string into buffer. Note the +1 is allowing for the implicit trailing
    // zero in a std::string
    std::snprintf(&result[0], len + 1, format, args...);

    return result;
};

int main() {
    auto s = replace("RndOrder%5d - RndCustomer%8s - RndHex%8x", 5, "foo", 257);
    std::cout << s << std::endl;
}

expected output:

RndOrder    5 - RndCustomer     foo - RndHex     101
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142