C++中的字符编码方式

目录

1.char

2.wchar_t

3.TCHAR

4.一些函数

1.char 转化为 16进制字符串

2.字符串的UTF-8与GBK(或GB2312)编码转换


C++基本数据类型中表示字符的有两种:charwchar_t

区别于C#中的char和string 见文章C#中的字符编码方式以及一些字符集相关的函数_c# 字符串编码_ivy_0709的博客-CSDN博客

1.char

本质上,内存中存的就是一个char是一个8个bit,0101的值,至于怎么解析这个0101,其值代表什么字符,怎么显示给你看的,就是有一个对应的字符编码表了。

一个char一个字节(8bit)。如果你要定义中文字符,其空间要预留够大,因为:

中文字符,占用的是2个字节,即2个char

英文字符,占用的是1个字节,即1个char

下面定义的“str” 为4个字节的char数组

等号右边“中”是字符常量,const char [3],本身“中”字占用2个字节,加上字符常量末尾自动添加的0

所以如果等号左边 str 定义的是 < 3 的数组长度就会提示编译不通过了

为什么中文字符占用两个字节,因为C++中中文字符用的是GBK编码的编码方式。

ps:

那么这个CPP文件是一个文本文件,选择不同的编码方式,其文本的二进制码就是不同的。一般的CPP都是选用utf编码格式的。

文本本身的编码格式,和C++对这个字符的编码格式,不是同一个概念。

比如上述的存的是 -42 -48 的原因就是 “中”GBK编码的码值为 D6D0

D6,也就是用有符号的一个字节表示的  -42。char  有符号的 

D0,也就是用有符号的一个字节表示的  -48。

查看文字的编码网址:汉字字符集编码查询;中文字符集编码:GB2312、BIG5、GBK、GB18030、Unicode

2.wchar_t

一个wchar_t占2个字节。16个bit位。

一个字符 占用一个 wchar_t,不管是中文字符还是英文字符

下面定义的“str” 为2个字节的wchar_t数组。

等号右边L“中”宽字符常量,const wchar_t[2],本身“中”字占用一个wchar_t(2个字节),加上字符常量末尾自动添加的0

所以如果等号左边 str 定义的是 < 2 的数组长度就会提示编译不通过了。

为什么是20013

因为宽字符用的是unicode,而且是utf16,中,“中”的unicode码点是4E2D,而对于一般的字符utf16正好就是直接是码点的值,因为都是16位的。

wchar_t 是 unsigned short(16bit的),那么就是4E2D就是20013

3.TCHAR这个宏的类型

我们说过在 详解windows记事本的4种编码方式 中说过字符集 和 字符编码方式的概念。

那么在C++中我们也可以选择使用什么字符集,是unicode字符集,还是其他字符集:

这里要特别注意:!!   

         当配置选择 使用多字节字符集的时候 TCHAR 为 char(注意,char对中文字符的编码是GBK。2个字节。其他ascii字符是1个字节)(为什么这叫多字节,应该就是一个字符需要用多个TCHAR来编码的意思吧。)。

          当配置选择 使用Unicode字符集的时候 TCHAR 为 wchar_t(wchar_t对中文字符的编码是Unicode。始终是2个字节,不管是中文字符还是其他ascii字符。)

具体的实现方式:是通过是否定义了_UNICODE宏,对TCHAR进行设置为上述说的不同的类型,是char还是wchar_t。

所以,上面的配置只是针对于TCHAR这个宏用的char还是wchar_t。

即使当你配置中选择了使用Unicode字符集的时候,你还是可以在代码中使用char类型来表示中文,其值还是使用GBK的编码方式。

当你配置中选择了使用多字节字符集的时候,你也还是可以在代码中用wchar_t类型来表示中文时,其值是使用utf16的编码方式。

char 和 wchar_t  对字符的编码的方式,不会随着配置中选择了什么字符集而改变,该是什么还是什么。

4.std::wstring和 std::string

std::wstring 

是一个泛型的类,其中的类型是wchar_t
typedef basic_string<wchar_t> wstring;

This is an instantiation of the basic_string class template that uses wchar_t as the character type, with its default char_traits and allocator types

wstring.length

其实就是 std::basic_string::length 

Returns the length of the string, in terms of number of characters. 所以这里的字符是wchar的个数(如果是string 就是char的个数。)

This is the number of actual characters that conform the contents of the basic_string, which is not necessarily equal to its storage capacity.

Both basic_string::size and basic_string::length are synonyms and return the same value.

4.一些函数

1.char 转化为 16进制字符串

比如 char* 是utf8编码的字符,那输出char*显示肯定是乱码,因为char是用GBK编码的。

通过下面的函数输出原始的utf8编码的16进制值。

注意:当16进制的值是一位数的时候,需要保留前面的0:

#include <iostream> 
#include <stdlib.h>
#include <string.h>
using namespace std;

void main(void)
{
    // 这里没有模拟utf8编码的字符,只是举例转为16进制的过程
	char str[15] = "假如是一堆乱码";
	char hex_final[100] = "";
	char ch2[3]="";
	// 最后一个str[14] = 0 就不翻译为hex了
	for (int i = 0; i < 14; ++i)
	{
		sprintf(ch2,"%02x",str[i]);
		strcat_s(hex_final, ch2);
	}

    cout << hex_final << endl;

}

3.是否是utf8函数

bool IsTextUTF8(const std::string& str)
{
	char nBytes=0;//UFT8可用1-6个字节编码,ASCII用一个字节
	unsigned char chr;
	bool bAllAscii = true; //如果全部都是ASCII, 说明不是UTF-8

	for(int i=0; i < str.length();i++)
	{
		chr = str[i];

		// 判断是否ASCII编码,如果不是,说明有可能是UTF-8,ASCII用7位编码,
		// 但用一个字节存,最高位标记为0,o0xxxxxxx
		if( (chr&0x80) != 0 )
			bAllAscii= false;

		if(nBytes==0) //如果不是ASCII码,应该是多字节符,计算字节数
		{
			if(chr>=0x80)
			{
				if(chr>=0xFC&&chr<=0xFD)   nBytes=6;
				else if(chr>=0xF8)         nBytes=5;
				else if(chr>=0xF0)         nBytes=4;
				else if(chr>=0xE0)         nBytes=3;
				else if(chr>=0xC0)         nBytes=2;
				else{
					return false;
				}
				nBytes--;
			}
		}
		else //多字节符的非首字节,应为 10xxxxxx
		{
			if( (chr&0xC0) != 0x80 ){
				return false;
			}
			nBytes--;
		}
	}

	if( nBytes > 0 ) //违返规则
		return false;

	if( bAllAscii ) //如果全部都是ASCII, 说明不是UTF-8
		return false;

	return true;
}

2.字符串的UTF-8与GBK(或GB2312)编码转换

要么用别人写好的库 iconv

要么自己照轮子造轮子 不是很复杂的话可以用这个方法方便,如下:

C/C++,字符串的UTF-8与GBK(或GB2312)编码转换_devc++可以调gbk编码吗_xiaohu_2012的博客-CSDN博客

#include <iostream>   
#include <string>   
#include <fstream>   
#include <windows.h>      
using namespace std;

string Utf8ToGbk(const char *src_str)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0);
	wchar_t* wszGBK = new wchar_t[len + 1];
	memset(wszGBK, 0, len * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len);
	len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
	char* szGBK = new char[len + 1];
	memset(szGBK, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
	string strTemp(szGBK);
	if (wszGBK) delete[] wszGBK;
	if (szGBK) delete[] szGBK;
	return strTemp;
}
string GbkToUtf8(const char *src_str)
{

	int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0);

	wchar_t* wstr = new wchar_t[len + 1];

	memset(wstr, 0, len + 1);

	MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len);

	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);

	char* str = new char[len + 1];

	memset(str, 0, len + 1);

	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);

	string strTemp = str;

	if (wstr)

		delete[] wstr;

	if (str)

		delete[] str;

	return strTemp;

}

UE里面自带的字符转换函数

// Conversion typedefs
typedef TStringConversion<TCHAR,ANSICHAR,FANSIToTCHAR_Convert> FANSIToTCHAR;
typedef TStringConversion<ANSICHAR,TCHAR,FTCHARToANSI_Convert> FTCHARToANSI;
typedef TStringConversion<ANSICHAR,TCHAR,FTCHARToOEM_Convert> FTCHARToOEM;
typedef TStringConversion<ANSICHAR,TCHAR,FTCHARToUTF8_Convert> FTCHARToUTF8;
typedef TStringConversion<TCHAR,ANSICHAR,FUTF8ToTCHAR_Convert> FUTF8ToTCHAR;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ivy_0709

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值