2009-10-23 18 views
8

私たちは、可変長引数を持つ関数に文字列*フォーマット_TCHAR *文字列を渡す必要があり、チャーの数:C++の可変長引数を使用する場合、どのように_TCHAR *をchar *に変換するのですか?

inline void FooBar(const _TCHAR *szFmt, const char *cArgs, ...) { 
    //... 
} 

だから、そうのように呼び出すことができます。

char *foo = "foo"; 
char *bar = "bar"; 
LogToFileA(_T("Test %s %s"), foo, bar); 

明らかに、単純な修正はcharの代わりに_TCHARを使用することですが、残念なことにその贅沢はありません。

私たちは、私たちは、文字列の書式を設定することができますなど、va_startマクロでこれを使用する必要があります。それは私たちに、このエラーを与えるため

va_list args; 
_TCHAR szBuf[BUFFER_MED_SIZE]; 

va_start(args, cArgs); 
_vstprintf_s(szBuf, BUFFER_MED_SIZE, szFmt, args); 
va_end(args); 

残念ながら、我々はこれを使用することはできません。

Unhandled exception at 0x6a0d7f4f (msvcr90d.dll) in foobar.exe: 
0xC0000005: Access violation reading location 0x2d86fead. 

私は考えています私たちはchar *を_TCHAR *に変換する必要がありますが、どうですか?

+0

あなたが代わりのchar *のwchar文字を使用しての贅沢*を持っている場合、私はうーん、残念ながらない –

+0

あなたの問題を解決するだろうと思う - 現在のシステムは –

+0

*のchar *と_TCHARのミッシュ - マッシュですそれはあまりにも悪い...効率は問題ですか?そうでない場合は、私の答えを見て、それは私のために働いた –

答えて

3

%sの代わりに%hsまたは%hSを使用してください。これはprintf関数のANSIとUnicodeのバージョン()の両方でのchar *のように変換されるためにパラメータを強制されます - スタイル機能、すなわち:

inline void LogToFile(const _TCHAR *szFmt, ...) 
{ 
    va_list args; 
    TCHAR szBuf[BUFFER_MED_SIZE]; 

    va_start(args, szFmt); 
    _vstprintf_s(szBuf, BUFFER_MED_SIZE, szFmt, args); 
    va_end(args); 
} 

{ 
    char *foo = "foo"; 
    char *bar = "bar"; 
    LogToFile(_T("Test %hs %hs"), foo, bar); 
} 
+0

非常に良い答えです。 –

2

通常、それは次のようになります。

char *foo = "foo"; 
char *bar = "bar"; 
#ifdef UNICODE 
LogToFileW(L"Test %S %S", foo, bar); // big S 
#else 
LogToFileA("Test %s %s", foo, bar); 
#endif 

あなたの質問は完全に明確ではありません。あなたの関数がどのように実装され、どのように使用していますか?

+1

%sおよび%Sの代わりに%hsまたは%hSを使用してください。それはAnsiとUnicodeの両方でchar *を強制します。その後、UNICODEのチェックを取り除くことができます。 –

0

これは私がTCHARをcharに変換するために以前使っていたものですが、私が実際に最適化を求めていないにもかかわらず助けてくれると思っています。しかし、これは最速の方法ではありません。

TCHAR tmp[255]; 
::GetWindowText(hwnd, tmp, 255); 
std::wstring s = tmp; 

//convert from wchar to char 
const wchar_t* wstr = s.c_str(); 
size_t wlen = wcslen(wstr) + 1; 
char newchar[100]; 
size_t convertedChars = 0; 
wcstombs_s(&convertedChars, newchar, wlen, wstr, _TRUNCATE); 
1

をここに私の解決策だった - 私は、改善のための提案を歓迎します!

inline void FooBar(const _TCHAR *szFmt, const char *cArgs, ...) { 

    va_list args; 
    _TCHAR szBuf[BUFFER_MED_SIZE]; 

    // Count the number of arguments in the format string. 
    const _TCHAR *at = _tcschr(szFmt, '%'); 
    int argCount = 0; 
    while(at) { 
     argCount++; 
     at = _tcschr(at + 1, '%'); 
    } 

    CA2W *ca2wArr[100]; 
    LPWSTR szArgs[100]; 
    va_start(args, cArgs); 
    for (int i = 1; i < argCount + 1; i++) { 
     CA2W *ca2w = new CA2W(cArgs); 
     szArgs[i] = ca2w->m_psz; 
     ca2wArr[i] = ca2w; 
     cArgs = va_arg(args, const char *); 
    } 
    va_end(args); 

    // Use the new array we just created (skips over first element). 
    va_start(args, szArgs[0]); 
    _vstprintf_s(szBuf, BUFFER_MED_SIZE, szFmt, args); 
    va_end(args); 

    // Free up memory used by CA2W objects. 
    for (int i = 1; i < argCount + 1; i++) { 
     delete ca2wArr[i]; 
    } 

    // ... snip ... - code that uses szBuf 
} 
+0

ループをカウントする引数は "%%"リテラルを使用できません。また、va_arg()を使用すると、32ビットを超えるパラメータは使用できません。さらに、_vstprintf_s()はすでにAnsiとUnicodeの両方をサポートしているので、このような複雑なコードを最初から始める必要はありません。私が以前あなたに与えたコードに問題はありましたか? –

+0

ああ、あなたは正しいのですか?あなたのコードに関しては、これはうまくいくでしょう、私たちが実装している新しいコードにこれを使用するつもりですが、既存の(欠陥のある)用途では私の答えで一時的なハック関数を使わなければなりません。 –

関連する問題