Как сконвертировать Std::wstring в Char* ?

  • Автор темы Danechka
  • Дата начала
Статус
Закрыто для дальнейших ответов.
D

Danechka

#1
Как сконвертировать std::wstring в char* ?
Желательно с конкретным примером, если можно....
 

Kmet

Java Team
25.05.2006
1 036
8
#2
не совсем корректный вопрос. общее решение для всех кодировок написать проблематично.
что то более менее общее ниже, извиняюсь за такую простыню, но было лень вырезать
Код:
#ifndef _t_char_converter_CC_
#define _t_char_converter_CC_


#include <assert.h>
#include "kmtcmn.h"



namespace kmt{
namespace conv{
////////////////////////////////////////////////////////////////////////////////
//containing

template<class unicode_string>
struct t_ansi_to_unicode;

template<class ansi_string>
struct t_unicode_to_ansi;

////////////////////////////////////////////////////////////////////////////////
//struct t_ansi_to_unicode

template<class unicode_string>
struct t_ansi_to_unicode
{
typedef unicode_string									string_type;
typedef typename string_type::value_type				 char_type;
//typedef t_void_allocator								 allocator_type;
//typedef t_typed_simple_buffer<char_type,allocator_type>  buffer_type;

//convert 't' to 'result' and return 'result'
static string_type& convert(string_type& result,LPCSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);

static string_type convert(LPCSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);
};//struct t_ansi_to_unicode

////////////////////////////////////////////////////////////////////////////////
//template struct t_ansi_to_unicode

template<class unicode_string>
typename t_ansi_to_unicode<unicode_string>::string_type&
t_ansi_to_unicode<unicode_string>::convert(string_type& result,
LPCSTR str,size_t str_len,bool* error,UINT CodePage)
{
if(error)
*error=false;

if(str==NULL || str_len==0)
return result.erase();


//åñëè str_len==-1, òî WCTMB ó÷èòûâàåò çàâåðøàþùèé íóëåâîé ñèìâîë
int wlen=::MultiByteToWideChar(CodePage,0,str, (int)str_len,NULL,0);

assert(wlen>=0);
if(wlen==0 || (wlen==1 && str_len==-1))//error èëè str==""
{
if(error)
*error=::GetLastError()?true:false;

return result.erase();
}

if(str_len!=-1)
wlen+=1;//ó÷èòûâàåì çàâåðøàþùèé UNICODE-ñèìâîë

assert(wlen>1);//âåðíåì íå òîëüêî çàâåðøàþùèé ñèìâîë

//ðåçåðâèðóåì ìåñòî ïîä âñå ñèìâîëû (âêëþ÷àÿ è òåðìèíàëüíûé)
string_type::value_type *pbuf= new string_type::value_type[wlen]; 

int rw=::MultiByteToWideChar(CodePage,0,str,(int)str_len,pbuf,wlen);
result.erase();
result.append(pbuf, pbuf+rw);
delete[] pbuf;

return result;//.erase(result.size()-1,1);
}//t_ansi_to_unicode::convert (result...)

template<class unicode_string>
typename t_ansi_to_unicode<unicode_string>::string_type
t_ansi_to_unicode<unicode_string>::convert(LPCSTR str,size_t str_len,bool* error,UINT CodePage)
{
string_type result;

return convert(result,str,str_len,error,CodePage);
}//t_ansi_to_unicode::convert

////////////////////////////////////////////////////////////////////////////////
//inline implementation

inline std::wstring ansi_to_unicode(LPCSTR t,size_t n,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;

return convertor_type::convert(t,n,error,CodePage);
}//ansi_to_unicode

inline std::wstring ansi_to_unicode(const std::string& t,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;

return convertor_type::convert(t.c_str(),t.size(),error,CodePage);
}//ansi_to_unicode

inline std::wstring& ansi_to_unicode(std::wstring& result,LPCSTR t,size_t n,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;

return convertor_type::convert(result,t,n,error,CodePage);
}//ansi_to_unicode

inline std::wstring& ansi_to_unicode(std::wstring& result,const std::string& t,bool* error,UINT CodePage)
{
typedef t_ansi_to_unicode<std::wstring> convertor_type;

return convertor_type::convert(result,t.c_str(),t.size(),error,CodePage);
}

////////////////////////////////////////////////////////////////////////////////
//struct t_unicode_to_ansi

template<class ansi_string>
struct t_unicode_to_ansi
{
typedef ansi_string									  string_type;
typedef typename string_type::value_type				 char_type;
//typedef t_void_allocator								 allocator_type;
//typedef t_typed_simple_buffer<char_type,allocator_type>  buffer_type;

//convert 't' to 'result' and resurn 'result'
static string_type& convert(string_type& result,LPCWSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);

static string_type convert(LPCWSTR t,size_t n=-1,bool* error=NULL,UINT CodePage=CP_ACP);
};//struct t_unicode_to_ansi

////////////////////////////////////////////////////////////////////////////////
//template struct t_unicode_to_ansi

template<class ansi_string>
typename t_unicode_to_ansi<ansi_string>::string_type&
t_unicode_to_ansi<ansi_string>::convert(string_type& result,
LPCWSTR wstr,size_t wstr_len,bool* error,UINT CodePage)
{
if(error)
*error=false;

if(wstr==NULL || wstr_len==0)
return result.erase();


//åñëè wstr_len==-1, òî WCTMB ó÷èòûâàåò çàâåðøàþùèé íóëåâîé ñèìâîë
int alen=::WideCharToMultiByte(CodePage,0,wstr,(int)wstr_len,NULL,0,NULL,NULL);

assert(alen>=0);
if(alen==0 || (alen==1 && wstr_len==-1))//error èëè wstr==L""
{
if(error)
*error=GetLastError()?true:false;

return result.erase();
}

//TODO: Çäåñü ïðåäïîëàãàåòñÿ, ÷òî äëÿ âñåõ ANSI êîäèðîâîê òåðìèíàëüíûé ñèìâîë
//	 çàíèìàåò 1 áàéò
if(wstr_len!=-1)
alen+=1;//ó÷èòûâàåì çàâåðøàþùèé ñèìâîë

assert(alen>1);//âåðíåì íå òîëüêî çàâåðøàþùèé ñèìâîë

//ðåçåðâèðóåì ìåñòî ïîä âñå ñèìâîëû (âêëþ÷àÿ è òåðìèíàëüíûé)
string_type::value_type *pbuf= new string_type::value_type[alen]; 

int rw=::WideCharToMultiByte(CodePage,0,wstr,(int)wstr_len,pbuf,alen,NULL,NULL);
result.erase();
result.append(pbuf, pbuf+rw);

delete[] pbuf;

//èñêëþ÷àåì òåðìèíàëüíûé ñèìâîë
//TODO: Óâåðåííîñòü îòíîñèòåëüíî îäíîãî áàéòà?
return result;//.erase(result.size()-1,1);
}//t_unicode_to_ansi::convert

template<class ansi_string>
typename t_unicode_to_ansi<ansi_string>::string_type
t_unicode_to_ansi<ansi_string>::convert(LPCWSTR wstr,size_t wstr_len,bool* error,UINT CodePage)
{
string_type result;

return convert(result,wstr,wstr_len,error,CodePage);
}//t_unicode_to_ansi::convert

//inline implementation --------------------------------------------------
inline std::string unicode_to_ansi(LPCWSTR t,size_t n,bool* error=NULL,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;

return convertor_type::convert(t,n,error,CodePage);
}

inline std::string unicode_to_ansi(const std::wstring& t,bool* error=NULL,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;

return convertor_type::convert(t.c_str(),t.size(),error,CodePage);
}

inline std::string& unicode_to_ansi(std::string& result,LPCWSTR t,size_t n,bool* error=NULL,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;

return convertor_type::convert(result,t,n,error,CodePage);
}

inline std::string& unicode_to_ansi(std::string& result,const std::wstring& t,bool* error=NULL ,UINT CodePage=CP_ACP)
{
typedef t_unicode_to_ansi<std::string> convertor_type;

return convertor_type::convert(result,t.c_str(),t.size(),error,CodePage);
}

inline std::string tchar2ansi(kmt::unicode::tstring t,bool* error=NULL ,UINT CodePage=CP_ACP)
{
#ifndef _UNICODE
return unicode_to_ansi(t,error, CodePage);
#else
return t;
#endif //_UNICODE
}

////////////////////////////////////////////////////////////////////////////////
};//namespace conv
};//namespace kmt
#endif
 
M
#3
Зачем такие усложнения? :D

Топикстартеру, смотри функцию WideCharToMultiByte, и используй её для своих конкретных нужд, выльется это в пару другую строк, но не в несколько страниц :D.

Хотя если конвертация используется часто, стоит присмотреться к методам приведенным выше ...
 
D

Danechka

#4
Всем спасибо!
Проблему решил при помощи wcstombs.
 
Статус
Закрыто для дальнейших ответов.