簡體   English   中英

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

[英]Use format strings that contain %1, %2 etc. instead of %d, %s etc. - Linux, C++

作為這個問題的后續(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;

FormatMessage()函數使用printf樣式的格式說明符; 他們在%1或其他之后進入感嘆號。 沒有格式說明符的占位符相當於printf“%s”。

你需要做的是稍微改變格式字符串; 將“%1”更改為“%1 $ s”,“%2!u!” 到“%2 $ u”,“%3!4.5e!” 到“%3 $ 4.5e”等等。 基本上只是改變了! 格式說明符周圍的字符在它之前的單個$中,並且可以處理裸“%number”的可能性。

像%1 $ anytype這樣的位置參數的問題是它必須出現在%2 $ anytype的格式字符串中才能工作。 參看 printf("Today, %1$s received %2$d dollars in salary\\n", name, salary); printf("Today, I received %2$d dollars in salary\\n", name, salary); (繁榮)。 所以它並不總是有效,比如用戶可以自由提供格式字符串,並決定省略字段。 在這種情況下,命名參數方法似乎更可取。 例如,libHX提供了可以使用"%(SALARY) %(NAME)"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM