中文字符处理"/>
编程中的中文字符处理
文章目录
- 前言
- 中文在不同编码环境下的处理
- 程序在单一系统上运行
- 程序在多个系统上运行
- 中文在相同编码不同存储类型下的处理
前言
编程遇到中文的时候,需要注意下。其一,软件中使用的编码,与软件运行环境的编码是否一致。比如,在客户端编程中,编程界面使用utf-8编码,而运行程序的win环境是gb2312编码,则显示会乱码。其二,以何种数据结构存储包含中文的变量。比如,如果使用string结构存储可能包含中文的配置文件路径,处理不当,函数加载配置文件可能失败。
下面两个小结,将会讨论上面两点。在讨论之前,我们需要对编码有基本的认知。我之前整理过文件乱码处理,我个人的背景知识点中包含编码的基本常识,所以本文不包含编码的基本介绍。另外,我这里简单补充下常见的编程环境,使用的编码方式。
- linux系统 -> vscode 编辑器 -> utf-8编码
- win11系统 -> vscode 编辑器 -> utf-8编码
- win11系统 -> vs 编辑器 -> gb2312编码
中文在不同编码环境下的处理
程序在单一系统上运行
如果程序仅仅运行在linux环境下,整个程序项目文件,可以保存为utf-8格式。
如果程序仅仅运行在windows环境下,整个程序项目文件,可以保存为gb2312格式。
虽然程序仅仅运行在单一环境下,但程序员的开发环境可能是千奇百怪。EditorConfig似乎可以解决这个问题。但是我没折腾出来,EditorConfig
并没有修改文件的编码。
程序在多个系统上运行
对于需要显示中文的跨平台客户端程序,如使用qt、electron、cef等框架开发的软件,应该结合框架,解决不同系统的编码问题。如:彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)_libaineu2004的博客-CSDN博客_qt中文乱码
非必要显示中文的地方,尽量使用英文。
没有使用框架,而又不得不处理不同系统间的编码问题,可以考虑借助std::basic_string - cppreference来实现utf-8和gbk之间的转换。(PS: [日常]GB2312 GBK GB18030的区别和演进过程_陶士涵的菜地的技术博客_51CTO博客)
这里从网上找了几个函数:C++11 字符串编码转换_帝江VII的博客-CSDN博客_c++11编码转换
// utf-8转gbk
std::string utf8_to_gbk(const std::string& str)
{std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;std::wstring tmp_wstr = conv.from_bytes(str);//GBK locale name in windowsconst char* GBK_LOCALE_NAME = ".936";std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));return convert.to_bytes(tmp_wstr);
}
//gbk转utf-8
std::string gbk_to_utf8(const std::string& str)
{//GBK locale name in windowsconst char* GBK_LOCALE_NAME = ".936";std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));std::wstring tmp_wstr = convert.from_bytes(str);std::wstring_convert<std::codecvt_utf8<wchar_t>> cv2;return cv2.to_bytes(tmp_wstr);
}
如果使用boost,可以考虑使用下面函数。
inline std::string utf8_to_gbk(const std::string &str) {return boost::locale::conv::between(str, "GBK", "UTF-8");
}inline std::string gbk_to_utf8(const std::string &str) {return boost::locale::conv::between(str, "UTF-8", "GBK");
}
中文在相同编码不同存储类型下的处理
当编码一致之后,还得考虑相同的字符串内容,在不同存储类型之间的转换,特别是有windows环境编程时。比如,我们通常使用std::string来保存字符串,里面是否有中文,并不在意,因为只需要一个结构来存储。但是,当使用windows api来处理这些字符串的时候,就稍微有些头疼。比如ExtractIconExA function (shellapi.h) - Win32 apps | Microsoft Docs函数,需要传入一个LPCTSTR类型的路径,而我们使用stiring来保存路径。此时,需要进行一些类型转换。
在此之前,我们先瞅瞅有哪些类型可以表示一个字符串。
在windows环境编程中,字符串的表示,参考:Windows Data Types (BaseTsd.h) - Win32 apps | Microsoft Docs、LPSTR、LPCSTR、LPTSTR、LPCTSTR、LPWSTR及LPCWSTR的意义及区别_hellokandy的博客-CSDN博客
-
[MS-DTYP]: LPSTR | Microsoft Docs :指定了一个指向 8 位字符数组的指针,该数组可以由一个空字符终止。(当作char*使用)
-
[MS-DTYP]: LPCSTR | Microsoft Docs:指向一个由 8 位 Windows (ANSI) 字符组成的以空字符结尾的常量字符串。(当作const char*使用)
-
[MS-DTYP]: LPWSTR | Microsoft Docs:指向一个由 16 位Unicode 字符组成的字符串,它可以以空字符结尾。(当作wchar_t*使用)
-
[MS-DTYP]: LPCWSTR | Microsoft Docs :(当作const LPWSTR )
-
LPTSTR:如果是UNICODE编码,则表示为LPWSTR;否则,表示为LPSTR。
-
LPCTSTR:(当作const LPTSTR)
在上面的类型中,L表示long, P表示指针,C表示constant, T表示指针指向的字符占的字节数取决于Unicode是否定义,W表示wide,STR就是string的意思。
如果需要一些强制类型转换,可以参考:c++ - How to convert std::string to LPCSTR? - Stack Overflow
// sting到LPSTR的转换(下面的代码注意生命周期)(本质没有改变)
std::string myString("SomeValue");
LPSTR lpSTR = const_cast<char*>(myString.c_str());
// 将字符串映射成utf-16
// 代码来自:
wstring ANSIToUnicode(string str)
{int lengthW = MultiByteToWideChar(CP_ACP,0,str.c_str(),-1,NULL,NULL);wchar_t* pUnicode = new wchar_t [lengthW*sizeof(wchar_t)];memset(pUnicode,0,lengthW*sizeof(pUnicode));MultiByteToWideChar(CP_ACP,0,str.c_str(),-1,pUnicode,lengthW);wstring strw = pUnicode;delete[] pUnicode;return strw;
}
另外有几个宏,可以用以方便的转换:A2W、W2A、A2T、T2A的使用方法
更多推荐
编程中的中文字符处理
发布评论