问题
When you build an app on Windows using TCHAR
support, %s
in _tprintf()
means char *
string for Ansi builds and wchar_t *
for Unicode builds while %S
means the reverse.
But are there any format specifiers that always mean char *
string no matter if it's an Ansi or Unicode build? Since even on Windows UTF-16 is not really used for files or networking it turns out to still be fairly often that you'll want to deal with byte-based strings regardless of the native character type you compile your app as.
回答1:
The h
modifier forces both %s
and %S
to char*
, and the l
modifier forces both to wchar_t*
, ie: %hs
, %hS
, %ls
, and %lS
.
回答2:
This might also solve your problem:
_TCHAR *message;
_tprintf(_T("\n>>>>>> %d") TEXT(" message is:%s\n"),4,message);
回答3:
You can easily write something like this:
#ifdef _UNICODE
#define PF_ASCIISTR "%S"L
#define PF_UNICODESTR "%s"L
#else
#define PF_ASCIISTR "%s"
#define PF_UNICODESTR "%S"
#endif
and then you use the PF_ASCIISTR
or the PF_UNICODESTR
macros in your format string, exploiting the C automatic string literals concatenation:
_tprintf(_T("There are %d ") PF_ASCIISTR _T(" over the table"), 10, "pens");
回答4:
I found, that '_vsntprintf_s' uses '%s' for type TCHAR and works for both, GCC and MSVC. So you could wrap it like:
int myprintf(const TCHAR* lpszFormat, va_list argptr) {
int len = _vsctprintf(lpszFormat, argptr); // -1:err
if (len<=0) {return len;}
auto* pT = new TCHAR[2 + size_t(len)];
_vsntprintf_s(pT, (2+len)*sizeof(TCHAR), 1+len, lpszFormat, argptr);
int rv = printf("%ls", pT);
delete[] pT;
return rv;
}
int myprintf(const TCHAR* lpszFormat, ...) {
va_list argptr;
va_start(argptr, lpszFormat);
int rv = myprintf(lpszFormat, argptr);
va_end(argptr);
return rv;
}
int main(int, char**) { return myprintf(_T("%s"), _T("Test")); }
来源:https://stackoverflow.com/questions/5669173/is-there-a-format-specifier-that-always-means-char-string-with-tprintf