【问题标题】:how to convert const WCHAR * to const char *如何将 const WCHAR * 转换为 const char *
【发布时间】:2012-09-28 09:58:37
【问题描述】:
CString output ;
const WCHAR* wc = L"Hellow World" ;
if( wc != NULL )
{   
     output.Append(wc);
}
printf( "output: %s\n",output.GetBuffer(0) );

【问题讨论】:

  • 请补充说明,纯代码,不多说。
  • 你不需要GetBuffer。 CString 有一个访问内部缓冲区的 LPCTSTR 运算符。
  • 如果wcпривет мир,输出应该是什么?你关心代码页还是这只是宽 -> 所有宽字符都是 ANSI 字符的窄转换?

标签: c++


【解决方案1】:

你也可以试试这个:

#include <comdef.h>  // you will need this
const WCHAR* wc = L"Hello World" ;
_bstr_t b(wc);
const char* c = b;
printf("Output: %s\n", c);

_bstr_t 实现了以下转换运算符,我觉得这很方便:

operator const wchar_t*( ) const throw( ); 
operator wchar_t*( ) const throw( ); 
operator const char*( ) const; 
operator char*( ) const;

编辑:关于回答 cmets 的说明:const char* c = b; 行导致由 _bstr_t 实例创建和管理的字符串的窄字符副本,该实例将在销毁时释放一次。运算符只返回一个指向该副本的指针。因此,无需复制此字符串。此外,在问题中,CString::GetBuffer 返回LPTSTR(即TCHAR*)和not LPCTSTR(即const TCHAR*)。

另一种选择是使用转换宏:

USES_CONVERSION;
const WCHAR* wc = L"Hello World" ;
const char* c = W2A(wc);

这种方法的问题是转换字符串的内存是在堆栈上分配的,所以字符串的长度是有限的。但是,这一系列转换宏允许您选择要用于转换的代码页,如果宽字符串包含非 ANSI 字符,则通常需要此代码页。

【讨论】:

  • 我很想为此 +1。 _bstr_t_variant_t 曾经是我最好的朋友,那时你真的需要 ATL 来用 C++ 做一个像样的 COM 组件
  • 为什么要复制它?您的代码显示您需要在printf 中使用它。 _bstr_t 将负责释放内存。如果您需要保留副本并发送字符串,请使用_bstr_t 实例,而不是const char* - 从这个意义上说,_bstr_t 类似于CString。它负责在使用对象的多个副本时正确复制字符串数据(尽管它不使用 copy-on-write)。
  • const WCHAR* wc = L"Hellow World" ; c = _bstr_t(wc);printf("输出:%s\n",c);
  • 输出如下:ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε ■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■ε■■ε■
  • 那一刻你的 _bstr_t 对象还活着吗?根据您的代码示例,它是。
【解决方案2】:

您可以为此使用sprintf

const char output[256];
const WCHAR* wc = L"Hellow World" ;
sprintf(output, "%ws", wc );

【讨论】:

  • 我认为你不能将output 声明为const
【解决方案3】:

我的 Linux 代码

// Debian GNU/Linux 8 "Jessie" (amd64)

#include <locale.h>
#include <stdlib.h>
#include <stdio.h>

// Use wcstombs(3) to convert Unicode-string (wchar_t *) to UTF-8 (char *)
// http://man7.org/linux/man-pages/man3/wcstombs.3.html

int f(const wchar_t *wcs) {
        setlocale(LC_ALL,"ru_RU.UTF-8");
        printf("Sizeof wchar_t: %d\n", sizeof(wchar_t));
        // on Windows, UTF-16 is internal Unicode encoding (UCS2 before WinXP)
        // on Linux, UCS4 is internal Unicode encoding
        for (int i = 0; wcs[i] > 0; i++) printf("%2d %08X\n",i,wcs[i]);
        char s[256];
        size_t len = wcstombs(s,wcs,sizeof(s));
        if (len > 0) {
                s[len] = '\0';
                printf("mbs: %s\n",s);
                for (int i = 0; i < len; i++)
                        printf("%2d %02X\n",i,(unsigned char)s[i]);
                printf("Size of mbs, in bytes: %d\n",len);
                return 0;
        }
        else return -1;
}

int main() {
        f(L"Привет"); // 6 symbols
        return 0;
}

如何构建

#!/bin/sh
NAME=`basename $0 .sh`
CC=/usr/bin/g++-4.9
INCS="-I."
LIBS="-L."
$CC ${NAME}.c -o _${NAME} $INCS $LIBS

输出

$ ./_test 
Sizeof wchar_t: 4
 0 0000041F
 1 00000440
 2 00000438
 3 00000432
 4 00000435
 5 00000442
mbs: Привет
 0 D0
 1 9F
 2 D1
 3 80
 4 D0
 5 B8
 6 D0
 7 B2
 8 D0
 9 B5
10 D1
11 82
Size of mbs, in bytes: 12

【讨论】:

    【解决方案4】:

    这很简单,因为CString 只是CStringT 的类型定义,您还可以访问CStringACStringW(您应该阅读有关差异的文档)。

    CStringW myString = L"Hello World";
    CString myConvertedString = myString;
    

    【讨论】:

    • 是的,我意识到这一点,但这样写是为了更接近他的示例代码。
    • 这种转换对没有匹配窄字符的宽字符有什么作用?
    【解决方案5】:

    你可以这样做,或者你可以做一些更干净的事情:

    std::wcout << L"output: " << output.GetString() << std::endl;
    

    【讨论】:

    • 为什么要使用GetBuffer()?这是GetString()官方C-string getter!
    • @Rost 复制粘贴:D 无需大喊:D
    • 复制粘贴是邪恶的!!!真正的开发人员总是逐个字符地重新输入字符!你不知道吗?!! :-D
    【解决方案6】:

    您可以使用sprintf 来实现此目的,正如@l0pan 提到的(但我使用%ls 而不是%ws):

    char output[256];
    const WCHAR* wc = L"Hello World" ;
    sprintf(output, "%ws", wc ); // did not work for me (Windows, C++ Builder)
    sprintf(output, "%ls", wc ); // works
    

    【讨论】:

      【解决方案7】:

      您可以使用std::wcsrtombs 函数。

      这是一个 C++17 重载集用于转换:

      #include <iostream> // not required for the conversion function
      
      // required for conversion
      #include <cuchar>
      #include <cwchar>
      #include <stdexcept>
      #include <string>
      #include <string_view> // for std::wstring_view overload
      
      std::string to_string(wchar_t const* wcstr){
          auto s = std::mbstate_t();
          auto const target_char_count = std::wcsrtombs(nullptr, &wcstr, 0, &s);
          if(target_char_count == static_cast<std::size_t>(-1)){
              throw std::logic_error("Illegal byte sequence");
          }
      
          // +1 because std::string adds a null terminator which isn't part of size
          auto str = std::string(target_char_count, '\0');
          std::wcsrtombs(str.data(), &wcstr, str.size() + 1, &s);
          return str;
      }
      
      std::string to_string(std::wstring const& wstr){
          return to_string(wstr.c_str());
      }
      
      std::string to_string(std::wstring_view const& view){
          // wstring because wstring_view is not required to be null-terminated!
          return to_string(std::wstring(view));
      }
      
      int main(){
          using namespace std::literals;
      
          std::cout
              << to_string(L"wchar_t const*") << "\n"
              << to_string(L"std::wstring"s) << "\n"
              << to_string(L"std::wstring_view"sv) << "\n";
      }
      

      如果你使用 Pre-C++17,你应该紧急更新你的编译器! ;-)

      如果这真的不可能,这里有一个 C++11 版本:

      #include <iostream> // not required for the conversion function
      
      // required for conversion
      #include <cwchar>
      #include <stdexcept>
      #include <string>
      
      std::string to_string(wchar_t const* wcstr){
          auto s = std::mbstate_t();
          auto const target_char_count = std::wcsrtombs(nullptr, &wcstr, 0, &s);
          if(target_char_count == static_cast<std::size_t>(-1)){
              throw std::logic_error("Illegal byte sequence");
          }
      
          // +1 because std::string adds a null terminator which isn't part of size
          auto str = std::string(target_char_count, '\0');
          std::wcsrtombs(const_cast<char*>(str.data()), &wcstr, str.size() + 1, &s);
          return str;
      }
      
      std::string to_string(std::wstring const& wstr){
          return to_string(wstr.c_str());
      }
      
      int main(){
          std::cout
              << to_string(L"wchar_t const*") << "\n"
              << to_string(std::wstring(L"std::wstring")) << "\n";
      }
      

      【讨论】:

        猜你喜欢
        • 2012-09-25
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-10
        • 2013-01-26
        • 2015-08-05
        相关资源
        最近更新 更多