[英]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.