• 在Linux的终端中显示BMPString的内容


    在上一篇博文中,介绍了怎样在 Windows 的控制台界面下输出 BMPString 的内容,可是那里的方法在 Linux 下不适用。假设将那里的演示样例代码放到 Linux 下运行。输出的结果为乱码。产生乱码的原因在于 wchar_t 类型的变量在 Windows 下和 Linux 下的字节长度不同。

    下面 C 程序在 Windows 和 Linux 下都可以运行:

    #include <stdio.h>
    #include <wchar.h>
    #if defined(_WIN32) || defined(_WIN64)
      #include <stdlib.h>
    #endif
    int main(void)
    {
      printf("wide character (wchar_t type) length is %d bytes.
    ", sizeof(wchar_t));
    #if defined(_WIN32) || defined(_WIN64)
      system("pause");
    #endif
      return 0;
    }
    

    输出结果是不同的。

    在 64 位 Windows 下。用微软的编译器将其分别编译成 32 位和 64 位可运行程序,输出结果证明 wchar_t 类型变量长度为 2 字节。

    在 64 位 Linux 下。用 64 位的 GCC 编译后运行,输出结果证明 wchar_t 类型变量长度为 4 字节。

    在 Windows 下处理 BMPString 时,比方对于字符“中”,相应的 UTF-16 编码是0x4E, 0x2D,我们处理的方法是将其由 big-endian 顺序转换为 little-endian 顺序,再用 wprintf() 函数输出。

    在 Linux 下处理 BMPString 时。比方对于字符“中”。相应的 UTF-16 编码是0x4E, 0x2D,我们处理的方法是将其由 2 字节长扩展到 4 字节长,扩展时新加入的两个字节的值为 0。即变为 0x0, 0x0, 0x4E, 0x2D。再由 big-endian 顺序转换为 little-endian 顺序,即编码变成 0x2D, 0x4E, 0x0, 0x0。再用 wprintf() 函数输出。

    所以在 Linux 下要显示 BMPString,一般方法是先将 UTF-16 big-endian 方式的字符编码扩展为 UTF-32 big-endian 方式的字符编码,扩展方法是在前面加上两个字节的 0。再将UTF-32 big-endian 方式的字符编码变为 UTF-32 little-endian 方式的字符编码。(也可先将 UTF-16 big-endian 方式的字符编码转换为 little-endian 顺序,再给后面加上两个字节的 0。效果是一样的。)

    以下给出一个演示样例程序:

    /**************************************************
    * Author: HAN Wei
    * Author's blog: http://blog.csdn.net/henter/
    * Date: Oct 31th, 2014
    * Description: demonstrate how to print BMPString
      on Linux console
    **************************************************/
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <locale.h>
    #include <wchar.h>
    
    /**************************************************
    *函数名称:PrintBMPStringOnLinux
    *功能: 在 Linux 终端下输出 BMPString
    *參数:
        BMPString     [in]      
        BMPString_len [in]   BMPString 的长度,以字节为单位
    *返回值:
        0   成功
        -1  失败
    **************************************************/
    
    int PrintBMPStringOnLinux(unsigned char *BMPString, unsigned int BMPString_len)
    {
      unsigned char *buffer;
      unsigned int buffer_len, i;
      unsigned char *p, *q;
    
      buffer_len = BMPString_len * 2 + 4; /* 缓冲区大小为 BMPString 的字节长度的两倍
                                             再加上四个字节。这四个字节用来存放字符串
    										 结束符 (其类型为 wchar_t ),其相应
    										 编码是 0x0, 0x0, 0x0, 0x0 */
    
      if ( !(buffer = (unsigned char *)malloc(buffer_len)) )
      {
    #ifdef _DEBUG
        printf("malloc() function failed!
    ");
    #endif
        return (-1);
      }
    
      memset(buffer, 0, buffer_len);
      p = buffer;
      q = BMPString;
      for (i=0; i < (int)BMPString_len/2; i++)
      {
        *p = *(q+1);
        *(p+1) = *q;
        p += 4;
        q += 2;
      }
    
      setlocale(LC_ALL, "zh_CN.utf8");
      wprintf(L"BMPString: %ls
    ", (wchar_t *)buffer);
      free(buffer);
      return 0;
    }
    
    int main(void)
    {
      int error_code;
      unsigned char BMPString_data1[]={0x4e, 0x2d, 0x56, 0xfd};  /* 中文字符串"中国"相应的 Unicode 编码 */
      unsigned char BMPString_data2[]={0x0, 0x55, 0x0, 0x73, 0x0, 0x65, 0x0, 0x72};  /* 英文字符串"User"相应的 Unicode 编码 */
      char str[]={0x2d, 0x4e, 0x0, 0x0, 0xfd, 0x56, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
    
      if ( error_code = PrintBMPStringOnLinux(BMPString_data1, sizeof(BMPString_data1)) )
      {
       printf("Print BMPstring on Windows console failed!
    ");
       return (-1);
      }
    
      if ( error_code = PrintBMPStringOnLinux(BMPString_data2, sizeof(BMPString_data2)) )
      {
       printf("Print BMPstring on Windows console failed!
    ");
       return (-1);
      }
    
    /* 以下给出了说明 unicode 编码的字符在 Linux 中是怎样存放的一个样例,
       从显示结果能够看出:对于每个用 wchar_t 类型保存的 UTF-16 字符,
       长度为 4 字节。以 little-endian 顺序存放 */
      printf("
    ");
      setlocale(LC_ALL, "zh_CN.utf8");
      wprintf(L"%ls
    ", (wchar_t *)str);
    
      return 0;
    }
    

    该程序在 64 位 CentOS 下,用 64位 GCC 编译器编译后运行。输出结果例如以下图:

  • 相关阅读:
    Windows 下搭建Android开发环境
    浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
    更新Android SDK到3.0版本时,遇到Failed to rename directory E:\android\tools to E:\android\temp\ToolPackage.old01问题
    单词计数 soj1076
    拓扑排序
    浅谈C和C++中的const关键字
    快速排序
    拓扑排序 soj1075
    集合划分问题
    浅谈C/C++中的顺序点和副作用
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6958692.html
Copyright © 2020-2023  润新知