Reputation: 359
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.
Upvotes: 2
Views: 395
Reputation: 69864
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
Upvotes: 1
Reputation: 1536
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++
Upvotes: 2
Reputation: 1698
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";
Upvotes: 1