2009-10-23 49 views
8

Chúng tôi cần phải vượt qua một định dạng _TCHAR * chuỗi, và một số char * chuỗi thành một chức năng với args chiều dài thay đổi:Làm cách nào để chuyển đổi từ _TCHAR * sang char * khi sử dụng độ dài biến đổi C++?

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

Vì vậy, nó có thể được gọi như vậy:

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

Rõ ràng là một sửa chữa đơn giản sẽ là sử dụng _TCHAR thay vì char, nhưng chúng tôi không có sự sang trọng đó không may.

Chúng tôi cần phải sử dụng điều này với va_start, vv vì vậy chúng tôi có thể định dạng một chuỗi:

va_list args; 
_TCHAR szBuf[BUFFER_MED_SIZE]; 

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

Đáng tiếc là chúng ta không thể sử dụng điều này bởi vì nó cung cấp cho chúng tôi lỗi này:

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

Tôi đang nghĩ chúng ta cần chuyển đổi char * thành _TCHAR * - nhưng làm thế nào?

+0

nếu bạn có sự sang trọng của việc sử dụng một WCHAR * thay vì một char *, tôi nghĩ rằng sẽ khắc phục bạn vấn đề –

+0

Hmm, tiếc là không - hệ thống hiện tại là một mish-mash của char * và _TCHAR * –

+0

thats quá xấu ... là hiệu quả một vấn đề? nếu không, hãy nhìn vào câu trả lời của tôi, nó làm việc cho tôi –

Trả lời

3

Sử dụng% hs hoặc% hS thay vì% s. Điều đó sẽ buộc các tham số để được interpretted như char * trong cả Ansi và Unicode phiên bản của printf() - chức năng phong cách, ví dụ:

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

Câu trả lời rất hay. –

2

Thông thường nó trông giống như sau:

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 

Câu hỏi của bạn không phải là hoàn toàn rõ ràng. Chức năng của bạn được triển khai như thế nào và bạn sử dụng nó như thế nào?

+1

Sử dụng% hs hoặc% hS thay vì% s và% S. Điều đó sẽ buộc char * trong cả Ansi và Unicode. Sau đó, bạn có thể xóa séc cho UNICODE. –

0

Đây là thứ tôi đã sử dụng trước đây để chuyển đổi TCHAR thành char, hy vọng nó giúp, mặc dù tôi không thực sự tìm kiếm tối ưu hóa, vì vậy nó không phải là cách nhanh nhất .. nhưng nó đã hoạt động!

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

Đây là giải pháp của tôi - Tôi hoan nghênh đề xuất cải tiến!

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

Vòng lặp đếm đối số của bạn không cho phép các chữ "%%" và việc sử dụng va_arg() của bạn không cho phép các tham số lớn hơn 32 bit. Bên cạnh đó, vì _vstprintf_s() đã hỗ trợ cả Ansi và Unicode, nên không cần phải có mã phức tạp như vậy để bắt đầu. Đã xảy ra sự cố với mã tôi đã cung cấp cho bạn trước đó chưa? –

+0

Ah bạn đã chính xác về bộ đếm. Về mã của bạn, có điều này sẽ làm việc tốt Tôi giả sử, và chúng tôi sẽ sử dụng mã NEW mà chúng tôi thực hiện, tuy nhiên để sử dụng (thiếu sót) hiện có, chúng tôi phải sử dụng chức năng hack tạm thời trong câu trả lời của tôi. –

Các vấn đề liên quan