c++中utf8字符串和gbk字符串的转换

news/2024/9/18 19:13:13/文章来源:https://www.cnblogs.com/charlee44/p/18416702

这个功能C++语言本身似乎没有标准实现,需要借助于第三方库或者操作系统API。不得不吐槽一下这么重要的功能居然还没有办法依赖C++语言本身来实现,C++标准委员会真是不干人事啊。那就不废话了,直接给出windows下的实现。

std::string Utf8ToGbk(const std::string& utf8Str) {// Step 1: Convert UTF-8 to Wide Char (UTF-16)int wideCharLen =MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, nullptr, 0);if (wideCharLen == 0) {throw std::runtime_error("Failed to convert from UTF-8 to wide char.");}std::wstring wideStr(wideCharLen, 0);MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wideStr[0],wideCharLen);// Step 2: Convert Wide Char (UTF-16) to GBKint gbkLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, nullptr, 0,nullptr, nullptr);if (gbkLen == 0) {throw std::runtime_error("Failed to convert from wide char to GBK.");}std::string gbkStr(gbkLen, 0);WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &gbkStr[0], gbkLen,nullptr, nullptr);// Remove the null terminator added by the conversion functionsgbkStr.pop_back();return gbkStr;
}std::string GbkToUtf8(const std::string& gbkStr) {// Step 1: Convert GBK to Wide Char (UTF-16)int wideCharLen =MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), -1, nullptr, 0);if (wideCharLen == 0) {throw std::runtime_error("Failed to convert from GBK to wide char.");}std::wstring wideStr(wideCharLen, 0);MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), -1, &wideStr[0], wideCharLen);// Step 2: Convert Wide Char (UTF-16) to UTF-8int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, nullptr, 0,nullptr, nullptr);if (utf8Len == 0) {throw std::runtime_error("Failed to convert from wide char to UTF-8.");}std::string utf8Str(utf8Len, 0);WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, &utf8Str[0], utf8Len,nullptr, nullptr);// Remove the null terminator added by the conversion functionsutf8Str.pop_back();return utf8Str;
}

这段代码的原理很简单:

  1. CP_ACP的意思就是本地编码,就是操作系统系统定义的默认编码,依赖于当前操作系统的语言和地区设置。在中文环境下就是GBk系列的中文编码,例如GB2312、GBK或GB18030。
  2. 需要使用宽字节字符串来进行中转,在Windows下,std::wstring是16字节字符串,使用UTF-16编码。这一点有点类似于C#的string和Java的string,都是UTF-16编码。
  3. MultiByteToWideChar和WideCharToMultiByte都是操作系统的C接口,输入和返回的字符串都带'\0',因此转到c++的string需要去掉最后的'\0'字符。这一点需要注意。

测试了用例没有问题。测试Utf8ToGbk:

  // string utfStr = u8"这是一个测试的中文字符串,检查一下";// string utfStr = u8"测试";string utfStr = u8"abcdefg";string gbkStr = Utf8ToGbk(utfStr);// cout << gbkStr << "-------" << endl;// cout << gbkStr.length() << endl;// cout << gbkStr.c_str() << endl;// cout << strlen(gbkStr.c_str()) << endl;

测试GbkToUtf8:

#ifdef _WIN32SetConsoleOutputCP(65001);
#endif// string gbkStr = "测试";string gbkStr = "这是一个测试的中文字符串,检查一下";// string gbkStr = "abcdefg";cout << gbkStr.length() << endl;string utfStr = GbkToUtf8(gbkStr);cout << utfStr << endl;cout << utfStr.length() << endl;

以上是Windows的实现,Linux环境要使用别的办法,例如使用iconv库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/798232.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符编码发展史1 — ASCII和EASCII

1. 字符集与字符编码1.1. 字符集 1.2. 字符编码 1.3. 两者的关系2. 字符编码的发展历史2.1. 第一个阶段 ASCII编码2.1.1. ASCII 2.1.2. EASCII1. 字符集与字符编码 1.1. 字符集 字符集(Charcater Set或Charset): 是一个系统支持的所有抽象字符的集合,也就是一系列字符的集合…

[JVM]对象创建过程

Java 对象的创建过程 Java对象创建的过程主要分为五个步骤,下面我将详细介绍这五个步骤。 Step1:类加载检查 虚拟机遇到一条new指令时,首先会去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且会检查这个符号引用所指向的类是否已经完成加载、连接和初始化,…

教小模型进行推理

https://arxiv.org/abs/2212.08410 思维链提示在基础层面上是如此成功,以至于它产生了一些被称为 x 链现象的东西。谷歌研究院探索了如何使用 llm 为现有数据集生成 CoT 数据本体,然后如何在 CoT 上微调较小的语言模型。 介绍 众所周知,思维链提示提高了大型语言模型的推理能…

[WesternCTF2018]shrine

打开题目就得到了python代码 import flask import os #导包 app = flask.Flask(__name__) #创建一个flask实例, app.config[FLAG] = os.environ.pop(FLAG) #从操作系统的环境变量中读取名为FLAG的值,并将其存储在Flask的配置中,POP:读取后删除该环境变量@app.route(/) #定义…

MySQL 8.0 Public Key Retrieval is not allowed 错误的解决方法

原文:MySQL 8.0 Public Key Retrieval is not allowed 错误的解决方法 参考:Connection Java - MySQL : Public Key Retrieval is not allowed在使用 MySQL 8.0 时重启应用后提示com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Public Key Retrieva…

MobaXterm 密钥生成器

1、MobaXterm 密钥生成器,代码仓库地址: https://gitcode.com/gh_mirrors/mo/MobaXterm-keygen/blob/master/MobaXterm-Keygen.py 2、也可以用我打包好的exe程序,不用安装python环境: https://pan.baidu.com/s/1jo85pQc_kfWhcYmZcc49CQ 提取码:ws10 3、源码:#/usr/bin/e…

Linux引导启动程序(boot)

概述 本章主要描述boot/目录中的三个汇编代码文件,见列表6-1所示。正如在前一章中提到的,这三个文件虽然都是汇编程序,但却使用了两种语法格式。bootsect.s和setup.s是实模式下运行的16位代码程序,采用近似于Intel的汇编语言语法并且需要使用Intel 8086汇编编译器和连接器as86和…

9、const修饰指针

*代表指针,这样有助于记忆和区别这三种

day1闯关作业小结[linux基础知识]

完成SSH连接与端口映射并运行hello_world.py 1.进入InternStudio https://studio.intern-ai.org.cn/, 创建个人开发机2.使用密码进行SSH远程连接并进行端口映射3.运行hello_world.py

白云龙期货投资-第三讲

反转形态**头肩底(顶) 双底(顶) 三重底(顶) 圆弧底(顶)**持续形态**三角形 旗形 楔行 扩散三角形 收缩三角形**K线形态(反转形态,持续形态) 反转形态 头肩底(顶) 双底(顶) 三重底(顶) 圆弧底(顶) 持续形态 三角形 旗形 楔行 扩散三角形 收缩三角形 头肩顶头肩底双底(双顶)下…

java的方法和数组

什么是方法呢? 就类似c语言的函数 返回类型 方法名 形式参数列表 方法名最好使用小驼峰的形式,在java中方法不可以嵌套使用, 方法的调用: 就是在main方法里面写上调用的方法名加上需要传输的值,创建一个和方…