【问题标题】:How to convert a TCHAR array to std::string?如何将 TCHAR 数组转换为 std::string?
【发布时间】:2011-09-11 14:20:44
【问题描述】:

如何将TCHAR 数组转换为std::string(而不是std::basic_string)?

【问题讨论】:

  • 你意识到 std::string 只是 std::basic_string 的 typedef?
  • 您是否想始终将特定的 Unicode 或 MBCS TCHAR(即真正的 WCHAR 或 CHAR)转换为 std::string(即 char),或者将 CHAR 转换为字符串,将 WCHAR 转换为 wstring,或者还有什么?

标签: c++ string windows unicode tchar


【解决方案1】:

TCHAR 只是一个 typedef,根据您的编译配置,默认为 charwchar_t

标准模板库支持 ASCII(std::string)和宽字符集(std::wstring)。您需要做的就是根据您的编译配置将 typedef String 作为 std::string 或 std::wstring 。为了保持灵活性,您可以使用以下代码:

#ifndef UNICODE  
  typedef std::string String; 
#else
  typedef std::wstring String; 
#endif

现在您可以在代码中使用String 并让编译器处理讨厌的部分。 String 现在将具有构造函数,可让您将TCHAR 转换为std::stringstd::wstring

【讨论】:

  • 问题是我必须调用一个接受 std::string 的接口,所以我不能发送 std::wstring :(
  • 请参阅this question 了解如何将 wstring 转换为 string。
  • @ebyrob:Alok Save 对 std::string 和 std::wstring 所做的事情与 std::cout 和 std::wcout 一样。
  • @antred 所以typedef std::wcout std_tcoutstd_tstring 等等?我不能……让自己装出这样的标准。再说一次,我以前一直这样做是为了图形操作。为什么不是std::basic_string<TCHAR> 的前半部分 string 的 typedef 有明显区别吗?
  • @ashmish2 stackoverflow.com/questions/2573834/… 显示std::wstringstd::string 之间的转换,假设为UTF-8,但还有其他场景。考虑到这是 VS,但在大多数情况下,我会尽量坚持使用 W2A()A2W()
【解决方案2】:

TCHAR 要么是 char 要么是 wchar_t,所以一个

typedef basic_string<TCHAR>   tstring;

是一种方法。

另一种是完全跳过char,直接使用std::wstring

【讨论】:

    【解决方案3】:

    TCHAR 类型为 charwchar_t,具体取决于您的项目设置。

     #ifdef UNICODE
         // TCHAR type is wchar_t
     #else
         // TCHAR type is char
     #endif
    

    因此,如果您必须使用std::string 而不是std::wstring,则应使用转换器功能。我可以使用wcstombsWideCharToMultiByte

    TCHAR * text;
    
    #ifdef UNICODE
        /*/
        // Simple C
        const size_t size = ( wcslen(text) + 1 ) * sizeof(wchar_t);
        wcstombs(&buffer[0], text, size);
        std::vector<char> buffer(size);
        /*/
        // Windows API (I would use this)
        std::vector<char> buffer;
        int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
        if (size > 0) {
            buffer.resize(size);
            WideCharToMultiByte(CP_UTF8, 0, text, -1, static_cast<BYTE*>(&buffer[0]), buffer.size(), NULL, NULL);
        }
        else {
            // Error handling
        }
        //*/
        std::string string(&buffer[0]);
    #else
        std::string string(text);
    #endif
    

    【讨论】:

    • 我试过了,得到:错误 C2664: 'std::basic_string<_elem>::basic_string(const std::basic_string<_elem> &)' : 不能将参数 1 从 'TCHAR [50]' 转换为 'const std::basic_string<_elem> &'
    • @user396483:我刚刚在 VS2012 中尝试过。代码:link.
    【解决方案4】:

    我的回答迟了,我承认这一点,但是通过“Alok Save”的回答和一些研究,我找到了一个好方法! (注意:我没有对这个版本进行很多测试,所以它可能并非在所有情况下都有效,但从我测试的情况来看应该):

    TCHAR t = SomeFunctionReturningTCHAR();
    std::string str;
    
    #ifndef UNICODE
        str = t;
    #else
        std::wstring wStr = t;
        str = std::string(wStr.begin(), wStr.end());
    #endif
    
    std::cout << str << std::endl; //<-- should work!
    

    【讨论】:

    • 它仅适用于 7 位 ASCII,但打印其他字符的垃圾。
    【解决方案5】:

    快速而肮脏的解决方案:

    TCHAR str[256] = {};
    
    // put something in str...
    
    
    // convert to string
    std::string strtmp(&str[0], &str[255]);
    
    std::cout << strtmp << std::endl;
    

    【讨论】:

    • 如果原始字符串包含任何非ASCII字符,这将导致意外行为
    • 我相信这总是会产生一个长度为 255 个字符的std::string,即使字符串包含空终止符。 std::string 可以包含空值,特别是如果您在这种情况下使用基于范围的构造函数。
    【解决方案6】:

    简单!

    std::string tcharToChar(TCHAR* buffer)
    {
        char *charBuffer = NULL;
        std::string returnValue;
        int lengthOfbuffer = lstrlenW(buffer);
        if(buffer!=NULL)
        {
            charBuffer = (char*)calloc(lengthOfbuffer+1,sizeof(char));
        }
        else
        {
            return NULL;
        }
    
        for (int index = 0;
            index < lengthOfbuffer;
            index++)
        {
            char *singleCharacter = (char*)calloc(2,sizeof(char));
            singleCharacter[0] = (char)buffer[index];
            singleCharacter[1] = '\0';
            strcat(charBuffer, singleCharacter);
            free(singleCharacter );
        }
        strcat(charBuffer, "\0");
        returnValue.append(charBuffer);
        free(charBuffer);
        return returnValue;
        
    }
    

    【讨论】:

    • 现在你有一个需要清理的原始指针。为什么不返回 std::string 呢?编辑:您还使用singleCharacter 泄漏了大量的小缓冲区。该解决方案不能按原样接受。无需为singleCharacter 动态分配,我认为strcat 不需要逐个字符地写入字符串。
    • 我接受这是一个懒惰的解决方案。我已经纠正了泄漏并返回了一个 std::string。感谢您的意见。
    • 通过更改,答案并不是严格有害的,因此我删除了我的反对票。但这仍然不是一个很好的解决方案。不需要strcatsingleCharacter,只需将最后一个字符推到charBufferindex 位置即可。您也不需要为charBufffer 分配,因为std::string 已经有一个可以使用的字符缓冲区。手动内存管理在现代 C++ 中已严重失宠,除非绝对必要,否则通常不应成为推荐解决方案的一部分。
    • callocmalloc 等是 C 内存分配函数,在 C++ 中不太好用。它们不会启动对象的生命周期。应该改用new,但即便如此,也不鼓励使用newstd::vectorstd::make_unique 应该会取代绝大多数手动内存管理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 2013-08-26
    • 1970-01-01
    • 2018-11-23
    相关资源
    最近更新 更多