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.

7
  • 1
    No, there isn't. Not in C++. Commented Dec 5, 2016 at 11:44
  • 2
    Sure, there is in C++. Look up Boost.Spirit. Commented Dec 5, 2016 at 11:46
  • 1
    Or string::substr, which gets you part of the way there at least. Commented Dec 5, 2016 at 11:47
  • 4
    Not sure I understand. What's wrong with printf for this case? Commented Dec 5, 2016 at 11:49
  • 3
    You can use std::sprintf. Commented Dec 5, 2016 at 11:54

3 Answers 3

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++

Sign up to request clarification or add additional context in comments.

3 Comments

[dsx], not [d,s,x]. Also it would be right to add +: \d+.
Thanks a lot! That helped me!
I'm glad I could help. In that case you could accept the answer
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";

2 Comments

Where is string parsing in this answer? How did you detect formats of the arguments and number of digits/chars in generated values?
Thanks! But that's for a fixed "format". I would like to accept other "sFormat" strings, like "rnd_id_%6d"
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.