不用Windows API,解决 typeid().name() 中文变量输出乱码问题?

      我写了一个 Object类,它有一个属性,希望它返回 typeid().name(),但当有中文变量时,

它输出的是乱码,花了五六小时,发现网上也有一位网友遇到同样的情况,他用的是Windows API ,下面是那位网友的贴子截图:

我代码出现问题的如下:

class Object
{
private:
    /// <summary>
    /// Object 对象计数器
    /// </summary>
    static __int64 _object_count;

protected:

    inline virtual void InitData() {};

public://----------------------------------------------构造析构
    Object();
    ~Object();


public:

    inline virtual void ClearData() {};


public://----------------------------------------------------------------属性 
    inline static __int64 GetObjectCount() { return _object_count; }
    __declspec(property(get = GetObjectCount)) __int64  ObjectCount;

    inline const char* GetClassName() { return typeid(*this).name(); }
    __declspec(property(get = GetClassName)) const char* ClassName;

};

如图:

 输出:

 但我不想用API,最后发现 typeid().name 是utf8格式的,只要找出API替代版本就行,幸苦

了很久,终于找到两种方法可以不用Windws API WideCharToMultiByte解决问题

第一种,转换源码:

std::u32string UTF8ToUnicode(std::string const& utf8)
{
	if (utf8.empty())
	{
		return {};
	}

	std::u32string res;

	for (size_t i = 0; i < utf8.size(); )
	{
		auto c = (unsigned char)utf8[i];
		char32_t wideChar = 0;
		if ((c & 0x80) == 0)
		{
			wideChar = c;
			++i;
		}
		else if ((c & 0xE0) == 0xC0)  ///< 110x-xxxx 10xx-xxxx
		{
			if (i + 2 > utf8.size()) break;
			wideChar = (char32_t(c) & 0x3F) << 6;
			wideChar |= (char32_t(utf8[i + 1]) & 0x3F);
			i += 2;
		}
		else if ((c & 0xF0) == 0xE0)  ///< 1110-xxxx 10xx-xxxx 10xx-xxxx
		{
			if (i + 3 > utf8.size()) break;
			wideChar = (char32_t(c) & 0x1F) << 12;
			wideChar |= (char32_t(utf8[i + 1]) & 0x3F) << 6;
			wideChar |= (char32_t(utf8[i + 2]) & 0x3F);
			i += 3;
		}
		else if ((c & 0xF8) == 0xF0)  ///< 1111-0xxx 10xx-xxxx 10xx-xxxx 10xx-xxxx
		{
			if (i + 4 > utf8.size()) break;
			wideChar = (char32_t(c) & 0x0F) << 18;
			wideChar |= (char32_t(utf8[i + 1]) & 0x3F) << 12;
			wideChar |= (char32_t(utf8[i + 2]) & 0x3F) << 6;
			wideChar |= (char32_t(utf8[i + 3]) & 0x3F);
			i += 4;
		}
		else///< 1111-10xx 10xx-xxxx 10xx-xxxx 10xx-xxxx 10xx-xxxx
		{
			if (i + 4 > utf8.size()) break;
			wideChar = (char32_t(c) & 0x07) << 24;
			wideChar |= (char32_t(utf8[i + 1]) & 0x3F) << 18;
			wideChar |= (char32_t(utf8[i + 2]) & 0x3F) << 12;
			wideChar |= (char32_t(utf8[i + 3]) & 0x3F) << 6;
			wideChar |= (char32_t(utf8[i + 4]) & 0x3F);
			i += 4;
		}
		res.push_back(wideChar);
	}

	return res;
}

图(1)

第二种,  使用c++11标准库codecvt转换字符编码

const std::wstring utf8_2_ws(const std::string& src)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
	return conv.from_bytes(src);
}
 

图(2)

 当然我选择了第二种:

class Object
{
private:
	/// <summary>
	/// Object 对象计数器
	/// </summary>
	static __int64 _object_count;
 

protected:

	inline virtual void InitData() {};

public://----------------------------------------------构造析构
	Object();
	~Object();


public:

	inline virtual void ClearData() {};


public://----------------------------------------------------------------属性 
	inline static __int64 GetObjectCount() { return _object_count; }
	__declspec(property(get = GetObjectCount)) __int64  ObjectCount;

	inline const _string GetClassName()
	{ 
#if UNICODE		
		std::wstring_convert<std::codecvt_utf8<wchar_t> > tmp;

		return tmp.from_bytes(typeid(*this).name());
#else
		return typeid(*this).name(); 
#endif
	}

	__declspec(property(get = GetClassName)) const _string ClassName;

};

修正:

当是多字节时,利用 wcstombs wchar_t* 字符再转化为 char * 

#ifndef _LF_OBJ_H_
#define _LF_OBJ_H_


#include "macro.h"



_LF_BEGIN_

//#define _OBJECT_DEBUG_

//-----------------------------------------------------前置声明
//class Obj; 
 
 

/// <summary>
/// 不命名 Obj ,是因为跟 System::Object 同名
/// </summary>
class Obj
{
private:
	/// <summary>
	/// Obj 对象计数器
	/// </summary>
	static __int64 _iObjectCount;

	/// <summary>
	/// 是否进行全局初始化
	/// </summary>
	static bool _bInitializeGlobal;

protected:

	inline virtual void InitData();

public://----------------------------------------------构造析构
	Obj();
	virtual ~Obj();
	 

public:

	inline virtual void ClearData() {};
	inline virtual _string ToString() { return _t(""); };

public: // 运算符重载


public:
 

public://----------------------------------------------------------------属性 
	inline static __int64 GetObjectCount() { return _iObjectCount; }
	__declspec(property(get = GetObjectCount)) __int64  ObjectCount;

	const _string GetTypeName();

	/// <summary>
	/// 
	/// </summary>
	__declspec(property(get = GetTypeName)) const _string ClassName;

};

 

const _string Obj::GetTypeName()
{
	wstring wText = str.s_UTF8String_to_TextW(typeid(*this).name());

#ifdef _UNICODE_		
	return wText;
#else
	return str.s_wstring_to_string(wText);
#endif

}

string Framework_branch_str::s_wstring_to_string(const wstring& w)
{
	Mem<char> m(w.length() * 2 + 1);
	  
	wcstombs_s((size_t*)&m.effectiveCount, m.data, w.length() * 2, w.c_str(),w.length() * 2);

	return m.data;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值