自学内容网 自学内容网

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


原文地址:https://blog.csdn.net/troglodyte/article/details/143782563

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!