c++ - 使用包含 %1、%2 等而不是 %d、%s 等的格式字符串 - Linux、C++

标签 c++ gcc formatting variadic-functions

作为 this 的后续行动问题(Message compiler replacement in Linux gcc),我有以下问题:

当在 Windows 上使用 MC.exe 编译和生成消息时,我在 C++ 代码中调用 FormatMessage,它检索消息并使用 va_list *Arguments 参数发送各种消息参数。 例如:
messages.mc 文件:

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

C++代码:

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 );
}

调用方代码:

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

现在,我编写了一个简单的脚本来从 .mc 文件生成一个 .msg 文件,然后我使用 gencat 从它生成一个目录。

但是有没有办法使用格式化字符串,因为它们包含 %1、%2 等,而不是一般的(%d、%s...)格式?

请注意,对于每个可能的消息和每个可能的类型\参数顺序,解决方案必须足够通用...

有可能吗?

谢谢。

最佳答案

首先像printf这样的函数支持定位格式:

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

对于 C++,除了 C 解决方案之外还有一个 boost::format 库:

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

此外,如果您要将软件转移到 Linux,我建议使用“不同”的本地化方法:使用 gettext 或 boost.locale 库。

而不是这个:

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

使用:

C/gettext:

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

C++/gettext:

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

使用 boost.locale 的 C++:

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

关于c++ - 使用包含 %1、%2 等而不是 %d、%s 等的格式字符串 - Linux、C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4533534/

相关文章:

c++ - 如何将队列元素插入 vector 中?

c++ - 了解 Valgrind 输出

c++ - 克隆抽象基类(不干涉派生)

c++ - GCC:为什么编译 .hpp 文件会给出与 .cpp 文件不同的结果?

xml - 如何使用 gVim 格式化未格式化的 XML 文档?

c++ - 将 Windows 身份验证与 cpprestsdk 一起使用?

c++ - 涉及 `crti.o` 和 `crt1.o` 的奇怪链接器错误

c - 如何使用 -Werror 忽略 gcc 的 "useless storage class"?

NetBeans 格式化设置文件

html - 无法弄清楚如何修复 CSS 宽度