代码之家  ›  专栏  ›  技术社区  ›  Nick Bolton

当使用C++可变长度ARG时,如何将“从Tchar *”转换为“char”?

  •  8
  • Nick Bolton  · 技术社区  · 15 年前

    我们需要向一个具有可变长度参数的函数传递一个格式的TChar*字符串和一些char*字符串:

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

    所以可以这样称呼:

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

    显然,一个简单的解决方案是使用t char而不是char,但不幸的是,我们没有这种奢侈。

    我们需要使用VAXSTART等,这样我们就可以格式化一个字符串:

    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*-但是怎么做呢?

    4 回复  |  直到 15 年前
        1
  •  3
  •   Remy Lebeau    15 年前

    使用%hs或%hs而不是%s。这将强制在ANSI和Unicode版本的printf()样式函数中将参数解释为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); 
    }
    
        2
  •  2
  •   Kirill V. Lyadvinsky    15 年前

    通常如下所示:

    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
    

    你的问题还不完全清楚。你的功能是如何实现的,你如何使用它?

        3
  •  1
  •   Nick Bolton    15 年前

    这是我的解决方案——欢迎改进建议!

    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
    }
    
        4
  •  0
  •   David Menard    15 年前

    这是我以前用过的把t char转换成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);