3

Context:

I am currently writing a date formatting library in C++. For example. the library takes in a formatting string such as: dddd, mmmm d, dddd yyyy and produces a result Tuesday, December 26, Tuesday 2016 given year: 2016, month: 12, date: 26 (dddd stands for weekday, d stands for date in number, mmmm stands for month, yyyy stands for year).

I would like to achieve this by using boost::regex_replace.

What I have tried:

Javascript


In javascript I can easily achieve this by doing:

var pattern = 'dddd, mmmm d, yyyy';
pattern.replace(/(dddd)|(d)|(mmmm)|(yyyy)/gi, function (dddd, d, mmmm, yyyy){
    if (dddd) {
        return 'Tuesday';
    }

    if (d) {
        return '26'
    }

    if (mmmm) {
        return 'December';
    }

    if (yyyy) {
       return '2016';
    }
    return '';
}

C++


boost::regex regex1("(dddd)");
boost::regex regex2("(d)");
boost::regex regex3("(mmmm)");
boost::regex regex4("(yyyy)");
boost::smatch match;

// dddd
if (boost::regex_search(pattern, match, regex1))
{
    pattern = boost::regex_replace(pattern, regex1, "Tuesday");
}

// d
if (boost::regex_search(pattern, match, regex2))
{
    pattern = boost::regex_replace(pattern, regex2, "26");
}

// mmmm
if (boost::regex_search(pattern, match, regex3))
{
        pattern = boost::regex_replace(pattern, regex3, "December");
}

// yyyy
if (boost::regex_search(pattern, match, regex4))
{
    pattern = boost::regex_replace(pattern, regex4, "2016");
}

However, that gives me a result of "Tues26ay, December 26, Tues26ay 2016". The reason is that: as soon as I replace pattern dddd with Tuesday, the d inside Tuesday becomes a target pattern for regex2 causing it to be replaced with 26.

I am not sure how to fix this problem or I think my C++ way for solving this problem is not correct. Is it possible to have something similar as Javascript in C++ boost::regex?

Any help would be appreciated!

2

2 Answers 2

6

I don't know why you didn't literally 1-on-1 translate:

Live On Coliru

#include <boost/regex.hpp>
#include <iostream>

int main() {
    std::string pattern = "dddd, mmmm d, yyyy";
    pattern = boost::regex_replace(pattern, boost::regex("(dddd)|(d)|(mmmm)|(yyyy)"), [](auto& match)->std::string{
        if (match.str() == "dddd")
            return "Tuesday";

        if (match.str() == "d")
            return "26";

        if (match.str() == "mmmm")
            return "December";

        if (match.str() == "yyyy")
            return "2016";

        return "";
    });

    std::cout << "Result: " << pattern << "\n";
}

Prints

Result: Tuesday, December 26, 2016

Bonus:

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

3 Comments

That's great! Thanks for the alternate versions too! Do you think it's possible to get the match's index so a switch could be used?
You can make it so if you want, but it's not there by default. After all, matches don't need to be exclusive (think "(d(ddd))")
@PatLaugh A variant that passes the highest matched group-index to the callback in c++11 or c++14; here's another solution that uses four arguments to the formatter callback.
1

A simple solution would be to replace the weekday by a control char that's sure not to be elsewhere, then at the end replace that with the proper weekday; I don't have boost, but it works with std::regex.

To add / modify:

boost::regex regex5("(\x01)");
//dddd
pattern = regex_replace(pattern, regex1, "\x01");
//then the fifth check
pattern = regex_replace(pattern, regex5, "Tuesday");

2 Comments

Yes that should work out as expected. Actually while I was waiting for the answer, I came up with similar ideas as yours except that yours is more safe by using control characters as placeholders. I will mark it as an accepted answer. Thank you.
Interestingly, you can use a callback for the replacement formatter just like in javascript. See my answer

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.