Real positional string formatting?
-
14-11-2019 - |
Question
(Note: I know of Boost.Format, I'm looking for a better way to do the following.)
First a use-case example: In some countries, you name a person by calling his / her surname first and the forename last, while in other countries it's the exact opposite.
Now, for my code, I currently solve this with Boost.Format in the following fashion:
#include <boost/format.hpp>
#include <iostream>
#include <stdlib.h>
#include <utility>
int main(){
using namespace boost;
int pos1 = 2, pos2 = 1;
char const* surname = "Surname", *forename = "Forename";
// decision on ordering here
bool some_condition = false;
if(some_condition)
std::swap(pos1,pos2);
char buf[64];
sprintf(buf,"Hello %c%d%c %c%d%c",'%',pos1,'%','%',pos2,'%');
// buf == "Hello %[pos1]% %[pos2]%"; with [posN] = value of posN
std::cout << format(buf) % surname % forename;
}
Now, I would rather have it like this, i.e., everything in the format
line:
std::cout << format("Hello %%1%% %%2%%") % pos1 % pos2 % surname % forename;
But sadly, that doesn't work, as I get a nice parsing exception.
Is there any library to have real positional formatting? Or even a way to achieve this with Boost.Format that I don't know of?
OTHER TIPS
This is the Message Formatting part of Boost.Locale which is similar to GNU gettext.
In it you would write:
cout << format(translate("Hello {1} {2}!")) % forename % surname << endl;
And then a translator would translate the string using message catalogs:
msgid "Hello {1} {2}!"
msgstr "こんにちは {2}-さん!"
I'd simply swap the values that you interpolating
std::swap(surname, forename)
That'll do the job. If you don't want to mess with them, have references:
const std::string& param1(bSwapThem? forename : surname);
const std::string& param2(bSwapThem? surname : forename);
KISS
Sounds like something that should be in the system locale but it doesn't look like it's currently supported.
What about the simple way?
if(some_condition)
std::cout << surname << " " << forename;
else
std::cout << forename << " " << surname;
I would have used ?:
char const* surname = "Surname", *forename = "Forename";
bool swapFlag = (some_condition) ? true : false;
std::cout << "Hello " << (swapFlag ? surname : forename) << " " << (!swapFlag ? surname : forename) << std::endl;
You can do this by applying format recursively:
cout << format(str(format("%%%1%%% %%%2%%%") % pos1 % pos2)) % surname % forname;
However, I would recommend using something like GNU gettext instead.