当前位置: 首页 > article >正文

C语言中,让人又爱又恨的字符串编码

引言

在C语言的世界里,字符串编码是一个让人既爱又恨的话题。
所有的打印信息,都是以字符串输出的。但是,大家在编码的时候,经常会遇到一些情况,稍不注意,就会导致显示出乱码,到了客户那里,就尴尬了。
今天,我们就来聊聊这场混战中的三位主角:Unicode、ANSI和UTF-8。

编码格式简介

ANSI编码

ANSI编码,全称“美国国家标准协会编码”,是一种基于单字节的编码方式。它在西欧语言中大行其道,因为一个字节足以表示所有的字符。
所以,多数时候,只要我们打印的时候,用英文字母,通常就不会出问题。
但是一个字节的编码,在面对中文、日文等复杂字符时,它就完全不够了。于是就有了扩展字符编码。继续往下看。

Unicode编码

Unicode编码,旨在统一全球所有字符的编码方式,它是一个多字节的编码系统。Unicode的出现,让世界上的每个字符都有一个唯一的编码,但这也意味着它需要更多的存储空间。
如果固定是4字节,即32位,那么就称之为UTF-32编码。
UTF-16编码,在大多少情况下,占用2个字节,有时候为了扩展,也会占用4字节。
但是这两种编码,占用存储空间比较大。
更加常用的,则是UTF-8编码,继续往下看。

UTF-8编码

UTF-8编码,是Unicode的一种实现方式,它是一种可变长度的编码系统。
UTF-8的特点是它兼容ASCII,对于英文字符,UTF-8和ASCII是相同的,占用1个字节。对于其他字符,它可以表示2到4个字节。
相比UTF-16和UTF-32而言,占用空间就小多了。因此也更加受欢迎。当然,还有其它一些方面的原因。

编码格式的C语言实现

ANSI编码

在C语言中,ANSI编码通常通过char类型来处理。以下是一个简单的示例:

char ansiString[] = "Hello, World!";

这里,ansiString是一个ANSI字符串,它在大多数西欧语言中都能正常工作。

Unicode编码

Unicode在C语言中的处理稍微复杂一些,通常需要使用wchar_t类型。以下是一个Unicode字符串的例子:

wchar_t unicodeString[] = L"Hello, 世界!";

这里的L前缀告诉编译器这是一个宽字符字符串。在Windows平台上,这通常是UTF-16编码。

UTF-8编码

UTF-8在C语言中的处理与ANSI类似,但是需要确保编译器正确处理UTF-8编码。以下是一个UTF-8字符串的例子:

char utf8String[] = u8"Hello, 世界!";

这里的u8前缀是某些编译器用来表示UTF-8字符串的。

编码转换示例

在实际应用中,我们经常需要在不同的编码之间进行转换。

ANSI和Unicode之间的转换

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <windows.h>

int main()
{
    setlocale(LC_ALL, ""); // 设置本地化环境

    const char* ansiString = "世界,你好!";
    wchar_t* unicodeString = NULL;

    // ANSI到Unicode
    int unicodeLength = MultiByteToWideChar(CP_ACP, 0, ansiString, -1, NULL, 0);
    unicodeString = (wchar_t*)malloc(unicodeLength * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, ansiString, -1, unicodeString, unicodeLength);

    printf("ANSI: %s\n", ansiString);
    wprintf(L"Unicode: %ls\n", unicodeString);
    free(unicodeString);
    return 0;
}

以上代码,可以直接复制编译和运行,运行结果如下:
在这里插入图片描述

Unicode和Utf-8之间的转换

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>

int main() {
    // 设置本地化环境
    setlocale(LC_ALL, "en_US.UTF-8");

    // Unicode字符串
    const wchar_t* unicodeString = L"世界,你好!";

    // 获取转换为UTF-8所需的缓冲区大小
    int utf8Length = WideCharToMultiByte(CP_UTF8, 0, unicodeString, -1, NULL, 0, NULL, NULL);
    if (utf8Length == 0) {
        printf("WideCharToMultiByte failed with error %d\n", GetLastError());
        return 1;
    }

    // 分配缓冲区
    char* utf8String = (char*)malloc(utf8Length * sizeof(char));
    if (utf8String == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }

    // 执行转换
    int result = WideCharToMultiByte(CP_UTF8, 0, unicodeString, -1, utf8String, utf8Length, NULL, NULL);
    if (result == 0) {
        printf("WideCharToMultiByte failed with error %d\n", GetLastError());
        free(utf8String);
        return 1;
    }

    // 输出结果
    printf("UTF-8 string: %s\n", utf8String); 
    wprintf(L"Unicode: %ls\n", unicodeString);    

    // 释放内存
    free(utf8String);
    return 0;
}

以上代码,可以直接复制编译和运行,运行结果如下:
在这里插入图片描述

总结

在C语言中处理字符串编码,这个过程可能会有些复杂,但一旦掌握了这些知识,你就能在不同语言和平台之间自如地穿梭。
实际上,字符串编码的内容比上面还要多,本文算是浅尝辄止吧。有时间,真可以写成一篇更深入的文章。


http://www.kler.cn/a/393679.html

相关文章:

  • 使用 Keras 训练一个卷积神经网络(CNN)(入门篇)
  • 文件夹被占用了无法删除怎么办?强制粉碎文件夹你可以这样操作
  • 【数据结构与算法】第11课—数据结构之选择排序和交换排序
  • 界面控件Kendo UI for Angular中文教程:如何构建带图表的仪表板?(一)
  • 每日一练:二分查找-搜索插入位置
  • Springboot 启动端口占用如何解决
  • Python学习从0到1 day26 第三阶段 Spark ③ 数据计算 Ⅱ
  • java作业项目以及azkaban的操作
  • Java入门16——接口
  • exo - 使用日常设备运行AI集群
  • Linux 系统上部署 RabbitMQ
  • Python 正则表达式进阶用法:分组与引用详解
  • 数据挖掘在金融交易中的应用:民锋科技的智能化布局
  • Linux:进程概念
  • dto,vo这些有什么用
  • 万字长文解读深度学习——Transformer
  • SpringBoot(4)- data整合
  • 实习冲刺Day21
  • JSX 是react 专有的吗
  • Simulink中Matlab function使用全局变量
  • 我们来学mysql -- EXPLAIN之select_type(原理篇)
  • Rocky9/Ubuntu使用pip安装python的库mysqlclient失败解决方式
  • C# 实现对指定句柄的窗口进行键盘输入的实现
  • C++研发笔记13——C语言程序设计初阶学习笔记11
  • MongoDB新版本安装配置教程(7.0.15版本-zip下载)
  • 构建Spring Boot编程训练系统:全面指南