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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.