码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 编程中的中文字符处理


    文章目录

      • 前言
      • 中文在不同编码环境下的处理
        • 程序在单一系统上运行
        • 程序在多个系统上运行
      • 中文在相同编码不同存储类型下的处理

    前言

    编程遇到中文的时候,需要注意下。其一,软件中使用的编码,与软件运行环境的编码是否一致。比如,在客户端编程中,编程界面使用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.com来实现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 windows
    	const 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //gbk转utf-8
    std::string gbk_to_utf8(const std::string& str)
    {
    	//GBK locale name in windows
    	const 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    如果使用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");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    中文在相同编码不同存储类型下的处理

    当编码一致之后,还得考虑相同的字符串内容,在不同存储类型之间的转换,特别是有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());
    
    • 1
    • 2
    • 3
    // 将字符串映射成utf-16
    // 代码来自:https://blog.csdn.net/d14665/article/details/46958477
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    另外有几个宏,可以用以方便的转换:A2W、W2A、A2T、T2A的使用方法

  • 相关阅读:
    【Java基础】继承、抽象类、注解
    ROS播包可视化
    【2023华为杯B题】DFT类矩阵的整数分解逼近(思路及代码下载)
    java基础(冒泡排序)精简
    基于讯飞星火大语言模型开发的智能插件:小策问答
    ElasticSearch分布式搜索引擎-03
    idea导入eclipse项目,不能直接open!
    安装注册使用gitlab-runner
    服务器开发24:tinyxml使用(服务器起服读取配置信息接口)
    Beam failure Recovery
  • 原文地址:https://blog.csdn.net/sinat_38816924/article/details/126332816
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号