Use format strings containing% 1,% 2, etc. Instead of% d,% s, etc. - Linux, C ++

As a continuation of this question (replacing a message compiler in Linux gcc), I have the following problem:

When using MC.exe on Windows to compile and generate messages in C ++ code, I call FormatMessage, which retrieves the message and uses the parameter va_list *Argumentsto send a variety of message arguments. For example:
Messages.mc file:

MessageId=1
Severity=Error
SymbolicName=MULTIPLE_MESSAGE_OCCURED
Language=English
message %1 occured %2 times.
.

C ++ Code:

void GetMsg(unsigned int errCode, wstring& message,unsigned int paramNumber, ...)
{   
    HLOCAL msg;
    DWORD ret;
    LANGID lang = GetUserDefaultLangID();
    try
    {
        va_list argList;
        va_start( argList, paramNumber );
        const TCHAR* dll = L"MyDll.dll";
        _hModule = GetModuleHandle(dll);
        ret =::FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_IGNORE_INSERTS,
            _hModule,
            errCode,
            lang,
            (LPTSTR) &msg,
            0,
            &argList );
        if ( 0 != ret )
        {
            unsigned int count = 0 ;
            message = msg;
            if (paramNumber>0)
            {
                wstring::const_iterator iter;
                for (iter = message.begin();iter!=message.end();iter++)
                {
                    wchar_t xx = *iter;
                    if (xx ==L'%')
                        count++;
                }
            }
            if ((count == paramNumber) && (count >0))
            {

                ::LocalFree( msg );
                ret =::FormatMessage(
                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_HMODULE,
                    _hModule,
                    errCode,
                    GetUserDefaultLangID(),
                    (LPTSTR) &msg,
                    0,
                    &argList );
            }
            else if (count != paramNumber)
            {
                wstringstream tmp;
                wstring messNumber;
                tmp << (errCode & 0xFFFF);
                tmp >> messNumber;
                message = message +L"("+ messNumber + L"). Bad Format String. ";
            }
        }
        ::LocalFree( msg );
    }
    catch (...)
    {
        message << L"last error: " << GetLastError();
    }
    va_end( argList );
}

Caller Code:

wstring message;
GetMsg(MULTIPLE_MESSAGE_OCCURED, message,2, "Error message", 5);

Now I wrote a simple script to create a .msg file from a .mc file, and then I use gencat to create a directory from it.

But is there a way to use formatted strings since they contain% 1,% 2, etc., and NOT a common (% d,% s ...) format?

, \arguments...

?

.

+3
3

, , printf:

printf("%2$s, %1$d", salary, name);

++ C boost::format:

std::cout << boost::format("%2%, %1%") % salary % name;

, Linux, "" : gettext, boost.locale library.

:

wstring message;
GetMsg(MULTIPLE_MESSAGE_OCCURED, message,2, "Error message", 5);

:

/Gettext:

snprintf(msg,sizeof(msg),gettext("This is the message to %1$s about %2$s"),who,what);

++/Gettext:

using boost::format;
std::ostringstream ss;
ss << format(gettext("This is the message to %1% about %2%")) % who % what;

++ boost.locale:

using boost::locale::format;
using boost::locale::translate;
std::ostringstream ss;
ss << format(translate("This is the message to {1} about {2}")) % who % what;
+3

FormatMessage() printf; % 1 - . , , printf "% s."

, ; "% 1" "% 1 $s", "% 2! u!" "% 2 $u", "% 3! 4.5e!" "% 3 $4.5e" .. ! $, , "% ".

0

The problem with positional parameters like% 1 $ anytype is that it should appear in the format string for anytype% 2 $ to work. Wed printf("Today, %1$s received %2$d dollars in salary\n", name, salary);versus printf("Today, I received %2$d dollars in salary\n", name, salary);(arrow). Thus, this does not always work, for example, when the user can provide a format string and decides to omit the field. In this case, a named parameter approach is preferred. For example, libHX provides one where you can use "%(SALARY) %(NAME)".

0
source

Source: https://habr.com/ru/post/1782159/


All Articles