windows编程 第12课 vs中的c++编码问题

文章讨论了VisualStudio(VS)中常用的字符编码,包括UNICODE和ANSI。UNICODE使用宽字符,而ANSI是基于不同地区标准的编码,如GB2312。文中提供了宽字符转ANSI(GB2312)的C++代码示例,并强调了字符编码转换在编程中的重要性。
摘要由CSDN通过智能技术生成

vs常用的字符编码设置是多字节编码和UNICODE,如果设置使用UNICODE的话,会定义一个UNICODE的宏,windows很多的函数字符串参数都会使用宽字节字符(2个字节),如果多字节的话,会使用一种叫做ANSI的字符编码格式,ANSI是一种标准,在不同国家系统上的实现是不一样的,比如windows简体中文中的ANSI就是GB2312字符编码,简单可以理解为能用一字节的就用一字节,中文是两个字节。

2.ANSI码

a. ANSI码(American National Standards Institute),美国国家标准学会的标准码。
b. 不同的国家和地区制定了不同的标准,由此产生了 GB2312(中国), BIG5(台湾), JIS(日本) 等各自的编码标准。 这些使用 2 个字节来代表一个字符的各种延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。 不同 ANSI 编码之间互不兼容。
c. 当然对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。
ASCII字符集是与ANSI字符集中的前面128个(0-127)字符相同。这一点是ASNI编码与Unicode编码之间最大也最明显的区别。(Unicode全是两字节)
d.各国ANSI编码转Unicode码对照表http://www.opensource.apple.com/source/libiconv/libiconv-24/libiconv/tests/
e.中文国标码与Unicode码:http://www.opensource.apple.com/source/libiconv/libiconv-24/libiconv/tests/CP936.TXT

3.Unicode码

a. Universal Character Set 通用字符集
b. Unicode有两套标准,一套叫UCS-2(Unicode-16),用2个字节为字符编码,另一套叫UCS-4(Unicode-32),用4个字节为字符编码。常用的UCS-2,它可以表示的字符数为2^16=65535,基本上可以容纳所有的欧美字符和绝大部分的亚洲字符 。
c. ASCII字符集之间的不兼容问题 , ASCII字符是单个字节的,比如“A”的ASCII是65。而Unicode是双字节的,比如“A”的Unicode是0065,C语言使用‘\0’作为字符串结尾,这样一来,C语言的字符串函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉
d.unicode全码表:http://www.tamasoft.co.jp/en/general-info/unicode.html
中文国标码 Unicode码 UTF8 对照表:http://www.ansell-uebersetzungen.com/gbuni.html

通常情况下,我们vs设置的会是多字节字符编码,如图

当然,有时候不可避免的要对宽字符进行转化,以下是字符集设为UNICODE的时候将宽字符转化为ANSI(也即是GB2312)字符集的代码: 

// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <afxwin.h>
#include <TlHelp32.h>

int main()
{
    std::cout << "Hello World!\n";
    CFile cf;
    BOOL res = cf.Open(L"./1.txt", CFile::modeCreate | CFile::modeReadWrite);



	HANDLE         hProcessSnap;   // 进程快照句柄
	PROCESSENTRY32 stcPe32 = { 0 };  // 进程快照信息
	BOOLEAN isSuccess = FALSE;
	stcPe32.dwSize = sizeof(PROCESSENTRY32);

	// 1. 创建一个进程相关的快照句柄
	hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hProcessSnap == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

	// 2. 通过进程快照句柄获取第一个进程信息
	if (!Process32First(hProcessSnap, &stcPe32))
	{
		CloseHandle(hProcessSnap);
		return FALSE;
	}
	// 3. 循环遍历进程信息
	do
	{
		/*
		int  WideCharToMultiByte(
			UINT            uCodePage,     //CP_ACP
			DWORD      dwFlags,           //一般为 0
			PCSTR         pWideCharStr,  //要转换的Unicode字符串
			int               cchWideChar,   //指定字符串的长度(字符数),传-1,则自动判断
			PWSTR        pMultiByteStr,  //ANSI字符串缓冲区,可为NULL
			int               cbMultiByte,     //指定缓冲区字节数,如果传入0,则返回需要的 字节数(包括'\0')
			PCSTR         pDefaultChar,   //遇到无法转换时,使用默认字符来代替。如果为NUL,使用系统默认字符,通常为一个问号
			PBOOL        pfUsedDefaultChar    //返回值。如果全部成功返回FALSE,否则返回TRUE
		);
		*/
	
		char* str;
		// stcPe32.szExeFile UNICODE宽字符编码转化为ANSI或者UTF-8
		int size = WideCharToMultiByte(CP_ACP,
			0,
			stcPe32.szExeFile,
			-1,
			0,0,0,0
			);
		str = new char[size];
		WideCharToMultiByte(CP_ACP,
			0,
			stcPe32.szExeFile,
			-1,
			str, size, 0, 0
		);

		if (strcmp("svchost.exe", str) == 0)
		{
			std::cout << "找到进程:svchost.exe" << std::endl;
		}

		cf.Write(str, strlen(str));
		cf.Write("\r", strlen("\r"));
		
		//stcPe32:进程信息
	} while (Process32Next(hProcessSnap, &stcPe32));
	// 4. 关闭句柄退出函数
	CloseHandle(hProcessSnap);
	cf.Flush();
	cf.Close();

    getchar();

    return 0;
}

字符编码是个很头痛的问题,因为我们总希望程序能够智能地识别字符,不管他们的字符编码,也不管占用多少字节,但是对于我们程序员来说,这是必须要考虑的事情!

对了,补充一句啊!字符串比较请使用strcmp或者其它封装函数,尽量不要用"==","char*"使用"=="比较相当于比较的是字符指针指向的地址而不是地址指向的字符串!

好了 今天是2023/5/27日,祝愿大家每天的生活开开心心,快快乐乐!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值