c++中char*\wchar_t*\string\wstring之间的相互转换

本文介绍了Unicode、ASCII及UTF-8编码之间的转换方法,并提供了实用的代码示例。此外,还包括URL编码与解码、字符串替换等功能的实现。
string U2A(const wstring& str)//Unicode字符转Ascii字符</span>
{
	string strDes;
	if ( str.empty() )
		goto __end;
	int nLen=::WideCharToMultiByte(CP_ACP, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
	if ( 0==nLen )
		goto __end;
	char* pBuffer=new char[nLen+1];
	memset(pBuffer, 0, nLen+1);
	::WideCharToMultiByte(CP_ACP, 0, str.c_str(), str.size(), pBuffer, nLen, NULL, NULL);
	pBuffer[nLen]='\0';
	strDes.append(pBuffer);
	delete[] pBuffer;
__end:
	return strDes;
}

wstring A2U(const string& str)//Ascii字符转
{
	wstring strDes;
	if ( str.empty() )
		goto __end;
	int nLen=::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
	if ( 0==nLen )
		goto __end;
	wchar_t* pBuffer=new wchar_t[nLen+1];
	memset(pBuffer, 0, nLen+1);
	::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), pBuffer, nLen);
	pBuffer[nLen]='\0';
	strDes.append(pBuffer);
	delete[] pBuffer;
__end:
	return strDes;
}

string U2Utf(const wstring& wstrUnicode)//Unicode转utf8  
{  
	string strRet;
	if( wstrUnicode.empty() )
		return strRet;
	int nLen = WideCharToMultiByte(CP_UTF8, 0, wstrUnicode.c_str(), -1, NULL, 0, NULL, NULL);  
	char* pBuffer=new char[nLen+1];
	pBuffer[nLen] = '\0';
	nLen = WideCharToMultiByte(CP_UTF8, 0, wstrUnicode.c_str(), -1, pBuffer, nLen, NULL, NULL); 
	strRet.append(pBuffer);
	delete[] pBuffer;
	return strRet;  
}

wstring Utf2U(const string &str)//utf8转Unicode
{
	int u16Len = ::MultiByteToWideChar(CP_UTF8, NULL,str.c_str(),(int)str.size(), NULL, 0);
	wchar_t* wstrBuf = new wchar_t[u16Len + 1];
	::MultiByteToWideChar(CP_UTF8, NULL, str.c_str(),(int)str.size(), wstrBuf, u16Len);
	wstrBuf[u16Len] = L'\0';
	wstring wStr;
	wStr.assign(wstrBuf, u16Len);
	delete [] wstrBuf;
	return wStr;
}
//分割字符串
bool SplitString(const wstring& strSource,const wstring& strFlag, vector<wstring>& paramList)
{
	if ( strSource.empty() || strFlag.empty() )
		return false;
	paramList.clear();
	size_t nBeg = 0;
	size_t nFind = strSource.find(strFlag, nBeg);
	if ( nFind == std::wstring::npos )
		paramList.push_back(strSource);
	else
	{
		while ( true )
		{
			if ( nFind != nBeg )
				paramList.push_back(strSource.substr(nBeg, nFind-nBeg));
			nBeg = nFind + strFlag.size();
			if ( nBeg == strSource.size() )
				break;
			nFind = strSource.find(strFlag, nBeg);
			if ( nFind == std::wstring::npos )
			{
				paramList.push_back(wstring(strSource.begin()+nBeg, strSource.end()));
				break;
			}
		}
	}
	return true;
}
//URL编码
string UrlEncode(const string& strSrc)
{
	string strDes;
	for ( size_t i=0; i<strSrc.size(); ++i )
	{
		BYTE ch=(BYTE)strSrc[i];
		if ( isalnum(ch) || ch=='-' || ch=='_' || ch=='.' || ch=='~' )
			strDes+=ch;
		else if ( ch==' ' )
			strDes+='+';
		else
		{
			strDes+='%';
			strDes+=ToHex( (ch>>4) );
			strDes+=ToHex( ch%16 );
		}
	}
	return strDes;
}
//URL解码
string UrlDecode(const string& strSrc)
{
	string strDes;  
	for ( size_t i = 0; i < strSrc.size(); i++ )  
	{  
		BYTE ch=strSrc[i];
		if (ch == '+') 
			strDes+=' ';  
		else if (ch == '%')  
		{  
			BYTE h = FromHex((unsigned char)strSrc[++i]);  
			BYTE l = FromHex((unsigned char)strSrc[++i]);  
			strDes += (h<<4) + l;  
		}  
		else strDes += ch;  
	}  
	return strDes; 
}
//替换字符串
wstring StrReplaceW(const wstring& strContent, const wstring& strTag, const wstring& strReplace)
{
	size_t nBegin=0, nFind=0;
	nFind = strContent.find(strTag, nBegin);
	if ( nFind == wstring::npos )
		return strContent;
	size_t nTagLen = strTag.size();
	wstring strRet;
	while ( true )
	{
		strRet.append(strContent.begin()+nBegin, strContent.begin()+nFind);
		strRet.append(strReplace);
		nBegin = nFind + nTagLen;
		nFind = strContent.find(strTag, nBegin);
		if ( nFind == wstring::npos )
		{
			strRet.append(strContent.begin()+nBegin, strContent.end());
			break;
		}
	}
	return strRet;
}

string StrReplaceA( const string& strContent, const string& strTag, const string& strReplace )
{
	size_t nBegin=0, nFind=0;
	nFind = strContent.find(strTag, nBegin);
	if ( nFind == string::npos )
		return strContent;
	size_t nTagLen = strTag.size();
	string strRet;
	while ( true )
	{
		strRet.append(strContent.begin()+nBegin, strContent.begin()+nFind);
		strRet.append(strReplace);
		nBegin = nFind + nTagLen;
		nFind = strContent.find(strTag, nBegin);
		if ( nFind == string::npos )
		{
			strRet.append(strContent.begin()+nBegin, strContent.end());
			break;
		}
	}
	return strRet;
}

       以前的一份是很原始的代码,在多线程中已经不适用。注意:如果是utf8字符转ascii字符,这里没有单独函数,你需要两步来实现,utf8--->Unicode--->ascii,反之一样。

       至于编码的区别,简单地说下。Unicode编码中一个字符占两个字节,一个中文字占用两字节;Ascii编码是比较原始的编码方式,一个字符占用一个字节,一个中文字占用两字节;utf-8编码也叫变长编码,而前面两种编码长度是固定了的,utf-8编码中一个汉字可能占两个字节或者三个、四个字节。

       还有一点要说明的是,英文字母在这三种编码中的区别,以字母‘a’为例,Unicode编码中两个个字节是0x00 0x61;ascii编码中一个字节是0x61;UTF-8编码中也是一个字节0x61。其实,英文字符在ascii和uft-8编码中完全一样,所以在实际开发中,如果你需要在ascii和utf-8编码间转码而又知道里面全是英文,请不要转码!

      除了转码的几个基本函数,还附带了URL编码、解码和字符串替换的函数,这些代码都是在实际项目中使用的,应该很稳定,欢迎指正。
<think>嗯,用户想知道在C/C++中如何实现wchar_t*char*之间转换。我之前学过一点字符编码的知识,记得这两种类型涉及到多字节和宽字符的区别。可能需要用到Windows API里的函数,比如MultiByteToWideChar和WideCharToMultiByte。不过具体怎么用呢? 首先,用户的问题分为两个部分:一个是将char*转成wchar_t*,另一个是反过来。根据引用中的代码示例,比如引用[1]里的char2wchar函数,使用MultiByteToWideChar两次调用,第一次获取长度,第二次实际转换。然后分配足够的内存,包括结尾的\0。这部分需要注意编码的问题,比如CP_ACP是系统默认的多字节编码,而CP_UTF8可能需要处理UTF-8的情况。 另外,引用[3]提到使用std::wstring和std::string转换函数,这样可能更安全,避免手动管理内存。还有引用[4]中的ATL转换宏,比如A2W和W2A,但需要USES_CONVERSION宏,并且可能在多线程环境下有问题。 用户可能需要多种方法,比如使用Windows API、STL封装或者ATL宏。需要比较它们的优缺点,比如手动转换更灵活但容易出错,而ATL宏方便但有使用限制。还要注意编码参数的选择,比如是否使用CP_ACP或者CP_UTF8,这会影响转换结果是否正确。 此外,用户的问题中提到“相互转换”,所以需要分别给出两种转换的方法。每个步骤要详细说明参数的作用,比如MultiByteToWideChar的代码页、标志等。同时,内存管理方面,用户需要记得释放分配的缓冲区,避免内存泄漏。 可能还需要提到跨平台的问题,因为Windows API只能在Windows下使用,而其他平台可能需要不同的方法,比如使用iconv库或者C++11的codecvt。但根据引用中的内容,用户可能更关注Windows环境下的解决方案。 总结下来,回答应该包括三种方法:Windows API手动转换、STL封装版本、ATL宏方法,并指出各自的适用场景和注意事项。同时强调编码设置的重要性,比如处理中文时的正确编码选择,避免乱码。最后提醒内存管理和线程安全的问题,确保用户在实际应用中能正确使用这些方法。</think>在C/C++中实现$wchar_t*$与$char*$相互转换需要处理字符编码差异,以下是三种主流方法及实现原理: ### 一、Windows API基础方法 1. **char*wchar_t***: ```cpp wchar_t* char2wchar(const char* cchar, UINT codePage=CP_ACP) { int len = MultiByteToWideChar(codePage, 0, cchar, -1, NULL, 0); wchar_t* wstr = new wchar_t[len]; MultiByteToWideChar(codePage, 0, cchar, -1, wstr, len); return wstr; } ``` *关键参数*:`codePage`支持`CP_UTF8`(UTF-8转Unicode)或`CP_ACP`(系统ANSI编码)[^1][^3] 2. **wchar_t*char***: ```cpp char* wchar2char(const wchar_t* wstr, UINT codePage=CP_ACP) { int len = WideCharToMultiByte(codePage, 0, wstr, -1, NULL, 0, NULL, NULL); char* cstr = new char[len]; WideCharToMultiByte(codePage, 0, wstr, -1, cstr, len, NULL, NULL); return cstr; } ``` *注意*:必须成对使用`delete[]`释放内存[^3] ### 二、STL封装方法(推荐) ```cpp std::wstring charToWstr(const char* cstr, UINT codePage=CP_ACP) { int len = MultiByteToWideChar(codePage, 0, cstr, -1, NULL, 0); std::wstring wstr(len, 0); MultiByteToWideChar(codePage, 0, cstr, -1, &wstr[0], len); return wstr; } std::string wstrToChar(const wchar_t* wstr, UINT codePage=CP_ACP) { int len = WideCharToMultiByte(codePage, 0, wstr, -1, NULL, 0, NULL, NULL); std::string str(len, 0); WideCharToMultiByte(codePage, 0, wstr, -1, &str[0], len, NULL, NULL); return str; } ``` *优势*:自动内存管理,避免手动`new/delete`[^3] ### 三、ATL转换宏方法 ```cpp #include <atlconv.h> void demo() { USES_CONVERSION; // 必须声明在函数开头 char* cstr = "示例文字"; wchar_t* wstr = A2W(cstr); // char* -> wchar_t* wchar_t* wstr2 = L"测试内容"; char* cstr2 = W2A(wstr2); // wchar_t* -> char* } ``` *限制*:只能在函数作用域使用,不支持多线程同时调用[^4] ### 编码选择对照表 | 编码类型 | API参数 | 适用场景 | |----------------|-------------|-------------------------| | 系统默认ANSI | CP_ACP | 本地化程序(GBK/GB2312) | | UTF-8 | CP_UTF8 | 跨平台/网络传输 | | Unicode | - | Windows原生API使用 | ### 典型问题排查 1. **乱码问题**:确保转换时使用的代码页与实际编码一致 - 中文系统默认使用`CP_ACP`(GBK编码) - 网页数据常用`CP_UTF8` 2. **内存泄漏**:手动分配内存时需严格配对`new[]/delete[]` 3. **缓冲区溢出**:必须通过第一次API调用获取准确长度
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值