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日,祝愿大家每天的生活开开心心,快快乐乐!