2009-10-23 5 views
8

Wir brauchen ein Format _TCHAR * string, und eine Reihe von char * Strings mit args variabler Länge in eine Funktion zu übergeben:Wie konvertiere ich von _TCHAR * nach char *, wenn ich C++ Arrows mit variabler Länge verwende?

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

:

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

So kann es wie so genannt werden Offensichtlich wäre eine einfache Lösung, _TCHAR anstelle von char zu verwenden, aber diesen Luxus haben wir leider nicht.

Wir müssen dies mit va_start verwenden, etc, so können wir einen String formatiert werden:

va_list args; 
_TCHAR szBuf[BUFFER_MED_SIZE]; 

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

Leider können wir dies nicht verwenden, weil es uns diesen Fehler geben:

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

Ich denke bin wir müssen unser char * in _TCHAR * umwandeln - aber wie?

+0

, wenn Sie den Luxus mit einem wchar haben * anstelle eines char *, ich glaube, das wäre beheben Sie Problem –

+0

Hmm, leider nicht - das derzeitige System ein Mischmasch von char * und _TCHAR * –

+0

das ist schade ... ist Effizienz ein Thema? Wenn nicht, schauen Sie sich meine Antwort an, es funktionierte für mich –

Antwort

3

Verwenden Sie% hs oder% hS anstelle von% s. Das wird die Parameter zwingen, als char * in beiden Ansi und Unicode-Versionen von printf() interpretted wird - Stil Funktionen, das heißt:

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

Sehr gute Antwort. –

2

Normalerweise sieht es wie folgt aus:

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 

Ihre Frage nicht ganz klar ist. Wie ist deine Funktion implementiert und wie benutzt du sie?

+1

Verwenden Sie% hs oder% hS anstelle von% s und% S. Das wird char * sowohl in Ansi als auch in Unicode erzwingen. Dann können Sie den Check für UNICODE entfernen. –

0

Dies ist etwas, das ich zuvor verwendet habe, um ein TCHAR in char umzuwandeln, hoffe es hilft, obwohl ich nicht wirklich nach Optimierung suchte, also ist es nicht der schnellste Weg .. aber es hat funktioniert!

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

Hier meine Lösung war - ich Verbesserungsvorschläge willkommen!

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

Ihre Argumente zum Zählen von Schleifen erlauben keine "%%" Literale und Ihre Verwendung von va_arg() erlaubt keine Parameter, die größer als 32 Bit sind. Da _vstprintf_s() bereits sowohl Ansi als auch Unicode unterstützt, ist es nicht notwendig, dass ein solcher durchdachter Code beginnt. Gab es ein Problem mit dem Code, den ich Ihnen früher gegeben habe? –

+0

Ah, du hast Recht mit dem Zähler. In Bezug auf Ihren Code, ja, das würde gut funktionieren, nehme ich an, und wir werden dies für neuen Code verwenden, den wir implementieren, jedoch für existierende (fehlerhafte) Verwendungen müssen wir die temporäre Hack-Funktion in meiner Antwort verwenden. –

Verwandte Themen