Real positional string formatting?
(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?
In my opinion, Boost.Spirit.Karma is the definitive modern output formatting library.
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.
精彩评论