C语言 使用char字符实现汉字处理

  • 系统:windows 64
  • 编译器:gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
  • 文本编辑器:notepad
  • 控制台:Cmder
  • 编程语言:C、Python

  首先,要想打印汉字,必须考虑到编码问题。在windows下,由于系统使用GBK编码,而GCC解析时使用UTF-8而会导致以下代码运行时出现乱码:

#include <stdio.h>

int main()
{
    char *str = "你好,世界!";

    printf("%s\n", str);

    return 0;
}

  解决方法为:使用“-fexec-charset=gbk”命令

  解决了编码问题,我们还需要了解几点:

  • char类型本质上是数字,占据一个字节(即八位),可以通过%d打印编码,通过%c打印字符
  • 在C语言中,一个汉字占据两个char类型
  • 汉字的两个char类型为负数
  • 在打印汉字时,它的两个char必须紧跟着

  根据这几点,我们可以打印出汉字以及它们的编码:

#include <stdio.h>
#include <string.h>

int main()
{
    // str为字符指针,指向一个字符字面量,这个字符字面量由'\0'结尾
    char *str = "你好,世界!Hello, world!";
    // chr为字符指针,指向str所指向的字符字面量的第一个字符的地址,即'你'字符的两个char中的第一个
    char *chr = str;

    printf("%zu %s\n", strlen(str), str);
    // 如果遇到'\0',说明字符串结束了
    while (*chr != '\0')
    {
        // 如果chr的编码为负数,则说明遇到了一个汉字
        if (*chr < 0)
        {
            // 打印汉字及汉字的编码
            // 注意两个char必须紧紧跟着打印(%c%c),否则会打印出 ?? 
            printf("%c%c: %d%d\n", *chr, *(chr+1), *(chr), *(chr+1));
            // chr自增两个字节(因为每个汉字都由两个char组成)
            chr += 2;
        }
        else
        {
            // 打印英文字符
            printf("%c: %d\n", *chr, *chr);
            // chr自增一个字节
            ++chr;
        }
    }

    return 0;
}

  从上图,我们可以看出,这个字符串占据了25个字节,4个汉字加2个全角符号占据了12个字节,再加上23个英文字符,总共25个字节。我们可以从下图更清晰地看出str的构造:

  但是,根据我们在网上查询的结果,汉字‘你’的GBK编码应为:C4E3,但是在这里,却打印出了:-60-29,这是为什么呢?

  这里涉及到进制的问题,可能-60-29是十六进制数C4E3的十进制数?

  首先,我们先通过Python看看C4E3的二进制数以及十进制数。这好像跟-60-29根本不沾边。

  我们先看看下面的代码,导入<limits.h>头文件,看看char类型的取值范围为多少:

#include <stdio.h>
#include <limits.h>

int main()
{
    printf("[%d ~ %d]\n", CHAR_MIN, CHAR_MAX);
    printf("%c%c\n", 0xC4, 0xE3);return 0;
}

  我们可以看到:char类型的取值范围为[-128 ~ 127],但是我们却可以打印出汉字”你“。这是为什么呢?明明char的取值范围最多127,而汉字“你”的两个字符分别为:196和227,都超过了这个值。其实这是因为,C语言将这两个数字的二进制数作为负数处理。C中的char类型有1个字节,占8位,而它的最高位为符号位,当它为0时为正,1时则为负。C通过对正数做补码操作得到负数。补码,即对一个二进制数取反,然后再加1。比如,0xC4的二进制数为0b11000100,我们可以看到最高位1,在C中这个数就是负数。我们可以通过对这个二进制数做补码操作,得到0b00111100,即60。所以0b11000100在C中表示为-60。

   从以上,我们可以发现,GBK编码中,一个汉字占两字节。因为C中char类型只占一个字节,所以需要使用两个char类型来表示汉字。因为C中char为有符号类型,char的表示范围为[-128 ~ 127],所以在遇到大于127的数字时,会被char表示为负数。

  其实,我们还可以使用unsigned char来实现。char默认是有符号的,取值范围为:-128 ~127。而unsigned char的取值范围则为:0~255,那么汉字“你”的编码就会被显示为:196和227。

#include <stdio.h>
#include <string.h>

int main()
{
    // str为字符指针,指向一个字符字面量,这个字符字面量由'\0'结尾
    unsigned char *str = (unsigned char *)"你好,世界!Hello, world!";
    // chr为字符指针,指向str所指向的字符字面量的第一个字符的地址,即'你'字符的两个char中的第一个
    unsigned char *chr = str;

    printf("%zu %s\n", strlen(str), str);
    // 如果遇到'\0',说明字符串结束了
    while (*chr != '\0')
    {
        // 如果chr的编码大于127,则说明遇到了一个汉字
        if (*chr > 127)
        {
            // 打印汉字及汉字的编码
            // 注意两个char必须紧紧跟着打印(%c%c),否则会打印出 ?? 
            printf("%c%c: %d %d\n", *chr, *(chr+1), *(chr), *(chr+1));
            // chr自增两个字节(因为每个汉字都由两个char组成)
            chr += 2;
        }
        else
        {
            // 打印英文字符
            printf("%c: %d\n", *chr, *chr);
            // chr自增一个字节
            ++chr;
        }
    }

    return 0;
}

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<> 一些背景知识: 1. 一个汉字在c\c++的存储, 使用2个字节(char)存储; 2. 汉字存储的第一个char, 其值一定大于'~'(0111 1110=126),否则将导致识别歧义; 此处, 使用"单ASCII字符"来表示非 单ASCII字符的判断, 可以根据以下规则(主要R3, R4); : 一个字符串的长度==1,那肯定是一个ASCII字符; : 一个字符串的长度==2,且第1个ASCII字符的编码小于'~'; 那肯定是2个单ASCII字符; -- (PS: "") : 一个字符串的长度==3,且中间的ASCII字符的编码小于'~'; 那第3个肯定是单ASCII字符; (前2个是否构成1个汉字不能确定) : (基于R3)如果第pos个位置的ASCII字符编码小于'~', 那从下标pos,pos+1处拆分字符串 (下标pos归前串),将不会导致乱码; A 或者 B 的选择,需要知道以下信息: (1). 从 cut_base_pos 开始到 pos_B 结束的这段字符串内, 最后一个单ASCII字符的结束下标 p 在此基础上, 若使用: y -- 表示单ASCII字符(已确定的); x -- 表示可能是 单ASCII字符,也可能是 汉字的半个ASCII存储码; 那么一段长度为N的字符串,按照存储的ASCII码可以表示为一串如下的字符串(不包含[]) "x .. x][x .. x y x .. x][x .. x", 其中 s,e表示当前正在分析的一段子串(0<=s<e<=N, 下标e-s = 期望的分割长度cut_size) ^ ^ ^ ^ ^ 0 s p e N 在 【s, e】 之间, 查找结束下标p 的思路: 从e开始向s查找, 找到 第一个y 后 break; 记录下标p, 则从位置p开始, 是一个正确的分割(cut); 但此分割并不是一个最好的分割. 可以在 位置p上, 再加上 2K 个长度, 使 p+2K 与 pos_B 最接近即可. 可以认为从2K个长度的内容是K个汉字(实际上并不一定..), 但并不影响这个最佳分割的正确性! :)
/*********************************************************** 实验名称:LCD12864显示汉字示例程序 程序说明:烧好程序,正确插上LCD12864即可观察到LCD上显示的汉字。 注意:USB供电可能不足,这时需要用变压器供电。 ***********************************************************/ /*********************************************************** 模块名称:st7920 并行方式驱动12864液晶驱动 功能概要:st7920显示驱动 完成日期:2008.07.08 驱动芯片:st7920 ***********************************************************/ #include #define uint unsigned int #define uchar unsigned char #define x1 0x80 #define x2 0x88 #define y 0x80 #define comm 0 #define dat 1 sbit RS = P2^0; //H=data; L="command"; sbit RW = P2^1; //H=read; L="write"; sbit E = P2^2; //input enable; sbit PSB= P2^3; //H=并口; L="串口"; sbit RST= P2^5; //Reset Signal 低电平有效 sbit busy=P1^7; //lcd busy bit void wr_lcd (uchar dat_comm,uchar content); void chk_busy (void); void delay (uint us); uchar code tab31[]={ " RF-X1开发板 " " 您学习的首选 " }; uchar code tab32[]={ /*-- 调入了一幅图像:F:\梁\画图\HOCO12832.bmp --*/ /*-- 宽度x高度=128x32 --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x18,0x0C,0x00,0x00,0x01,0x00,0x00,0x00,0x00, 0x01,0xFF,0x80,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x13,0x10,0x03,0xFE,0x00, 0x03,0xFF,0xC0,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x3F,0x30,0x1F,0xFF,0xC0, 0x03,0xFF,0xE0,0x00,0x00,0x00,0x00,0x8C,0x03,0xF0,0x00,0x7F,0xE0,0x7C,0x01,0xE0, 0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0x36,0x06,0xC0,0x00,0x5F,0xC0,0xFF,0xFC,0x60, 0x01,0xFF,0xF0,0x00,0x00,0x00,0x02,0x1B,0x0F,0x80,0x00,0xFF,0x01,0xFE,0x0F,0x30, 0x00,0xEF,0xF0,0x00,0x00,0x00,0x02,0x6D,0x9F,0x00,0x00,0x3E,0x03,0xFF,0xF1,0x90, 0x00,0xFF,0xF8,0x00,0x00,0x00,0x04,0x36,0xFE,0x00,0x01,0xFF,0x07,0xFF,0xFC,0x90, 0x00,0xEF,0xFF,0xFF,0x80,0x00,0x04,0xDB,0x7E,0x00,0x03,0xFF,0x87,0xFF,0xFC,0xD0, 0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x04,0x6D,0xFC,0x00,0x07,0xFF,0x8F,0xFF,0xFE,0x50, 0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x04,0x36,0xFC,0x10,0x07,0xFF,0x8F,0xFF,0xFE,0x90, 0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x04,0x1B,0xF8,0x10,0x07,0xFF,0xCF,0xFF,0xFE,0x80, 0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x04,0x0F,0xF8,0x10,0x07,0xFF,0xFF,0xFF,0xFA,0x00, 0x00,0x07,0xFF,0xFF,0xF0,0x00,0x04,0x07,0xF0,0x10,0x07,0xFF,0xFF,0xFF,0xFA,0x00, 0x00,0xFF,0xFF,0xFF,0xF8,0x00,0x02,0x03,0xF0,0x20,0x07,0xFF,0xFF,0xFF,0xBA,0x00, 0x00,0xFD,0xFF,0xFF,0xFC,0x00,0x02,0x03,0xF0,0x20,0x03,0xFF,0xFF,0xDF,0xB8,0x00, 0x00,0xC1,0xC0,0x3F,0xFC,0x00,0x01,0x01,0xE0,0x40,0x00,0xFF,0xFF,0xDF,0xB0,0x00, 0x00,0x81,0xC0,0x3F,0xCE,0x00,0x00,0x81,0xE0,0x80,0x00,0x7F,0xFF,0xDF,0xA0,0x00, 0x00,0x81,0x80,0x1D,0xCF,0x00,0x00,0x41,0xE1,0x00,0x00,0x3F,0xFF,0x9B,0x00,0x00, 0x01,0x83,0x80,0x1F,0xC7,0x80,0x00,0x21,0xE2,0x00,0x00,0x1F,0xFD,0xB6,0x00,0x00, 0x01,0xC3,0x00,0x0E,0xE6,0x80,0x00,0x19,0xEC,0x00,0x00,0x07,0xFE,0x20,0x00,0x00, 0x00,0xC3,0x00,0x07,0x67,0x40,0x00,0x07,0xF0,0x00,0x00,0x03,0x3E,0x00,0x00,0x00, 0x00,0x02,0x00,0x03,0xE7,0xA0,0x00,0x00,0x00,0x00,0x00,0x02,0x8E,0x00,0x00,0x00, 0x00,0x06,0x00,0x03,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03,0x00,0x00,0x00, 0x00,0x06,0x00,0x07,0x03,0x00,0x77,0x46,0x74,0x24,0x80,0x06,0x04,0x00,0x00,0x00, 0x00,0x1C,0x00,0x06,0x00,0x00,0x55,0x45,0x54,0x57,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x1C,0x00,0x0E,0x00,0x00,0x45,0x45,0x74,0x57,0x80,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x1C,0x00,0x00,0x55,0x45,0x44,0x74,0x80,0xF0,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x38,0x00,0x00,0x77,0x76,0x47,0x54,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uchar code tab5[]={ /*-- 调入了一幅图像:F:\梁\画图\COCK.bmp --*/ /*-- 宽度x高度=128x64 --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x04,0x00,0xC0,0x00,0x38, 0x00,0x00,0x30,0x00,0x00,0x69,0xC0,0x00, 0x00,0x00,0x00,0x04,0x18,0xC0,0x00,0x18, 0x00,0x00,0x30,0x00,0x01,0xFF,0xF0,0x00, 0x00,0x00,0x00,0x0C,0x18,0xC0,0x0A,0xBD, 0x50,0x1D,0x75,0xE0,0x01,0xC0,0xF0,0x00, 0x00,0x74,0x00,0x3F,0x8C,0x80,0x1F,0xFF, 0xF0,0x3F,0xFF,0xF0,0x00,0x0D,0xE0,0x00, 0x03,0x8F,0x00,0xF0,0x3F,0xF0,0x30,0x18, 0x00,0x18,0x30,0x60,0x00,0x07,0x00,0x00, 0x0C,0x03,0x80,0xDF,0x30,0x70,0x00,0x38, 0x00,0x1D,0x75,0x60,0x05,0x57,0x54,0x00, 0x10,0x41,0x80,0x3E,0x30,0x20,0x07,0xFF, 0xE0,0x1F,0xFF,0xE0,0x1F,0xFF,0xFF,0x80, 0x21,0xC1,0xC0,0x04,0x3C,0xF0,0x02,0x08, 0x00,0x18,0x30,0x60,0x3F,0x47,0xBF,0x80, 0x40,0xC1,0x80,0x7F,0x9F,0xA0,0x02,0x19, 0x80,0x1D,0x7F,0xE0,0x30,0x03,0x03,0x00, 0xC1,0xC1,0x80,0x2E,0x05,0x80,0x27,0x99, 0x80,0x0F,0xFF,0xE0,0x00,0x03,0x00,0x00, 0x81,0x83,0x00,0x04,0x0D,0x00,0x33,0xE3, 0x00,0x0C,0x70,0x00,0x00,0x03,0x00,0x00, 0x81,0x86,0x00,0x0D,0x99,0x80,0x60,0x3E, 0x00,0x00,0x38,0x01,0x00,0x07,0x00,0x00, 0x81,0xBC,0x00,0x0F,0x39,0xC6,0xE0,0x0F, 0xB6,0x00,0x3F,0xBF,0x00,0x07,0x00,0x00, 0x83,0xF0,0x00,0x1E,0xE0,0xFE,0xE0,0x03, 0xFE,0x00,0x0F,0xFE,0x01,0xFF,0x00,0x00, 0xC3,0x30,0x00,0x89,0x80,0x7C,0x00,0x01, 0xF8,0x00,0x07,0xFC,0x00,0x7C,0x00,0x00, 0x63,0x31,0xFF,0x00,0x00,0x00,0x00,0x00, 0x20,0x00,0x00,0x50,0x00,0x00,0x00,0x00, 0x63,0x19,0x12,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x07,0x19,0x04,0x3F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80, 0x07,0x19,0x88,0x3F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80, 0x06,0x0C,0x10,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0E,0x0C,0x20,0x00,0x00,0x00,0x00,0x00, 0x08,0x00,0x00,0x00,0x00,0x40,0x00,0x00, 0x3E,0x0E,0x40,0x0A,0x6D,0xB4,0x07,0x84, 0x35,0x1A,0x67,0xA2,0x01,0xA7,0x9B,0x00, 0x45,0x86,0x80,0x0A,0xAA,0xB4,0x04,0x44, 0x26,0x92,0x68,0xA2,0x01,0x34,0x93,0x00, 0x00,0x03,0x01,0x0E,0xAE,0xB4,0x04,0x44, 0x61,0x1B,0x68,0xA2,0x01,0x0C,0x5B,0x00, 0x00,0x07,0x03,0x0A,0xBA,0xD8,0x06,0x84, 0x41,0xF2,0xC8,0x22,0x03,0x08,0xD7,0x00, 0x00,0x07,0x87,0x0D,0x96,0x68,0x05,0x84, 0x61,0x9B,0xE8,0x22,0x02,0x0C,0x5F,0x00, 0x00,0x1F,0xF6,0x0D,0xB6,0x58,0x04,0x84, 0x45,0x15,0xA8,0xA2,0x03,0x14,0xD5,0x00, 0x00,0x10,0xFC,0x05,0x92,0x48,0x04,0x84, 0x25,0x93,0xAC,0xA2,0x01,0x24,0x95,0x00, 0x00,0x00,0x00,0x0D,0x96,0x49,0x04,0x44, 0x3D,0x14,0xA7,0x1C,0x41,0xE7,0x15,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; /****************************************************************************************** * 函数名称 : * 功能描述 : * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void init_lcd (void) { RST = 1; PSB = 1; wr_lcd(comm,0x30); /*30---基本指令动作*/ wr_lcd(comm,0x01); /*清屏,地址指针指向00H*/ wr_lcd(comm,0x06); /*光标的移动方向*/ wr_lcd(comm,0x0c); /*开显示,关游标*/ } /****************************************************************************************** * 函数名称 :chn_disp * 功能描述 : 显示汉字字符 * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void chn_disp(uchar code *chn) { uchar i,j; wr_lcd(comm,0x30); wr_lcd(comm,0x80); for(j=0;j<4;j++) { for(i=0;i<16;i++) wr_lcd(dat,chn[j*16+i]); } } /****************************************************************************************** * 函数名称 :chn_disp1 * 功能描述 : 上半屏显示汉字字符 * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void chn_disp1(uchar code *chn) { uchar i,j; wr_lcd(comm,0x30); wr_lcd(comm,0x80); j=0; for(i=0;i<16;i++) wr_lcd(dat,chn[j*16+i]); wr_lcd(comm,0x90); j=1; for(i=0;i<16;i++) wr_lcd(dat,chn[j*16+i]); } /****************************************************************************************** * 函数名称 :img_disp * 功能描述 : 显示图形 * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void img_disp(uchar code *img) { uchar i,j; for(j=0;j<32;j++) { for(i=0;i<8;i++) { wr_lcd(comm,0x34); wr_lcd(comm,y+j); wr_lcd(comm,x1+i); wr_lcd(comm,0x30); wr_lcd(dat,img[j*16+i*2]); wr_lcd(dat,img[j*16+i*2+1]); } } for(j=32;j<64;j++) { for(i=0;i<8;i++) { wr_lcd(comm,0x34); wr_lcd(comm,y+j-32); wr_lcd(comm,x2+i); wr_lcd(comm,0x30); wr_lcd(dat,img[j*16+i*2]); wr_lcd(dat,img[j*16+i*2+1]); } } wr_lcd (comm,0x36); } /****************************************************************************************** * 函数名称 :img_disp1 * 功能描述 : 下半屏显示图形 * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void img_disp1(uchar code *img) { uchar i,j; for(j=0;j<32;j++) { for(i=0;i<8;i++) { wr_lcd(comm,0x34); wr_lcd(comm,y+j); wr_lcd(comm,x2+i); wr_lcd(comm,0x30); wr_lcd(dat,img[j*16+i*2]); wr_lcd(dat,img[j*16+i*2+1]); } } wr_lcd(comm,0x36); } /****************************************************************************************** * 函数名称 :lat_disp * 功能描述 : 显示点阵 * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void lat_disp(uchar data1,uchar data2) { uchar i,j,k,x; x=x1; for(k=0;k<2;k++) { for(j=0;j<16;j++) { for(i=0;i<8;i++) { wr_lcd(comm,0x34); wr_lcd(comm,y+j*2); wr_lcd(comm,x+i); wr_lcd(comm,0x30); wr_lcd(dat,data1); wr_lcd(dat,data1); } for(i=0;i<8;i++) { wr_lcd(comm,0x34); wr_lcd(comm,y+j*2+1); wr_lcd(comm,x+i); wr_lcd(comm,0x30); wr_lcd(dat,data2); wr_lcd(dat,data2); } } x=x2; } wr_lcd(comm,0x36); } /****************************************************************************************** * 函数名称 :con_disp * 功能描述 : 当data1=0xff,data2=0xff时,在x0,y0处反白显示16xl*yl * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void con_disp(uchar data1,uchar data2,uchar x0,uchar y0,uchar xl,uchar yl) { uchar i,j; for(j=0;j<yl;j++) { for(i=0;i<xl;i++) { wr_lcd(comm,0x34); wr_lcd(comm,y0+j); wr_lcd(comm,x0+i); wr_lcd(comm,0x30); wr_lcd(dat,data1); wr_lcd(dat,data2); } } wr_lcd(comm,0x36); } /****************************************************************************************** * 函数名称 :clrram * 功能描述 : 清DDRAM * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void clrram(void) { wr_lcd(comm,0x30); wr_lcd(comm,0x01); } /****************************************************************************************** * 函数名称 :wr_lcd * 功能描述 : * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void wr_lcd(uchar dat_comm,uchar content) { chk_busy (); if(dat_comm) { RS = 1; //data RW = 0; //write } else { RS = 0; //command RW = 0; //write } P0=content; //output data or comm E = 1; ; E = 0; } /****************************************************************************************** * 函数名称 :chk_busy * 功能描述 : * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void chk_busy(void) { P0 = 0xff; RS = 0; RW = 1; E = 1; while(busy==1); E = 0; } /****************************************************************************************** * 函数名称 : * 功能描述 : * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void delay(uint us) //delay time { while(us--); } /****************************************************************************************** * 函数名称 : * 功能描述 : * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void delay1(uint ms) { uint i,j; for(i=0;i<ms;i++) for(j=0;j<15;j++) delay(1); } /****************************************************************************************** * 函数名称 : * 功能描述 : * 参数 : 参数名称: 输入/输出? 类型 描述 * * 返回值 : * 作者 : * 创建日期 :2007-12-19 * 全局变量 : * 全局静态变量: * 局部静态变量: *----------------------------------------修改历史------------------------------------------ * 当前版本 : 修改人: 修改日期: * 修改说明 : ******************************************************************************************/ void main() { SP=0x5f; init_lcd(); while(1) { //lat_disp(0x00,0x00); // chn_disp(tab1); //con_disp(0xff,0xff,0x8c,0x80,2,16); //delay1(8000); //clrram(); //lat_disp(0xcc,0xcc); //delay1(8000); lat_disp(0x00,0x00); chn_disp1(tab31); img_disp1(tab32); delay1 (8000); clrram(); //lat_disp (0xff,0x00); //delay1(8000); img_disp(tab5); delay1(8000); } }
目录 第一章 C 语言概述 1 第一节 C 语言的特点 1 第二节 C 语言的程序结构 2 第三节 C 语言的关键字和标识符 3 第二章 C 语言的基本语法 5 第一节 数据类型 5 2 1 1 整型int 5 2 1 2 浮点型float 6 2 1 3 字符char 6 2 1 4 指针型 7 2 1 5 无值型void 8 2 1 7 各类数值型数据间的混合运算 8 第二节 常量与变量 8 2 2 1 常量和变量 8 2 2 2 变量赋初值 9 第三节 运算符和表达式 9 2 3 1 算术运算符和算术表达式 9 2 3 2 赋值运算符和赋值表达式 10 2 3 3 关系运算符和关系表达式 10 2 3 4 逻辑运算符和逻辑表达式 11 2 3 5 位运算符 11 2 3 6 逗号运算符 12 2 3 6 条件运算符和条件表达式 12 2 3 7 强制类型转换运算符 12 2 3 8 sizeof 运算符 13 2 2 9 运算符的优先级和结合方向 13 第四节 表达式语句 14 2 4 1 基本表达式语句 14 2 4 2 复合语句 14 第五节 判断选取控制语句 15 2 5 1 条件语句if 语句 15 2 5 2 开关语句switch 语句 16 第六节 循环语句 17 2 6 1 while 语句 17 2 6 2 do while 语句 18 2 6 3 for 语句 18 2 6 4 goto 语句 19 2 6 5 continue 语句 20 第七节 返回语句 20 第三章 函数 21 第一节 函数的定义 21 3 1 1 函数的分类 21 C 语言手册基础篇 3 1 2 无参数函数的定义方法 21 3 1 3 有参数函数的定义方法 21 3 1 4 空函数的定义方法 22 3 1 5 函数的返回值 22 第二节 函数的调用 22 3 2 1 函数的调用形式 22 3 2 2 对被调用函数的说明 23 3 2 3 函数的参数和传递方式 23 3 2 4 函数的嵌套和递归调用 24 第三节 中断服务函数 24 第四节 变量的种类和存储 25 3 4 1 局部变量与全局变量 25 3 4 2 变量的存储种类 25 第四章 数组与指针 28 第一节 数组的定义和引用 28 第二节 字符数组 28 第三节 数组的初始化 29 第四节 数组作为函数的参数 29 第五节 指针的概念 30 4 5 1 指针变量的基本概念 30 4 5 2 指针变量的定义 30 4 5 3 指针变量的引用 31 4 5 4 指针的地址运算 31 4 5 5 指针变量作为函数的参数 32 4 5 6 用指针引用数组元素 32 第六节 函数型指针和指针函数 33 4 6 1 函数型指针 33 4 6 2 指针函数 34 第七节 指针数组和指针型指针 34 4 7 1 指针数组 34 4 7 2 指针型指针 35 第五章 结构和联合 37 第一节 结构的概念 37 5 1 1 结构变量的定义 37 5 1 2 结构变量的引用 38 5 1 3 结构变量的初值 39 5 1 4 结构数组 39 第二节 结构型指针 39 5 2 1 结构型指针的概念 39 5 2 2 使用结构型指针访问结构成员 40 第三节 结构与函数 40 第四节 联合 40 5 4 1 联合的定义 40 5 4 2 联合变量的引用 41 C 语言手册基础篇 第五节 位段 41 5 5 1 位段的概念 41 5 5 2 有关位段的说明 42 附录 44 附录1 C中的关键字 44 附录2 运算符的优先级和结合性 45">目录 第一章 C 语言概述 1 第一节 C 语言的特点 1 第二节 C 语言的程序结构 [更多]
实现中文字符串排序,需要先对中文进行编码,常用的编码方式有GBK、UTF-8等。在排序时,可以采用快速排序、归并排序等算法。 以下是一个示例代码,使用GBK编码方式对中文字符串进行排序: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义中文字符编码方式为GBK #define CODE_GBK 936 // 定义字符串数组 char *strArr[] = {"中华", "人民", "共和国", "万岁", "中国"}; // 获取中文字符串的长度(单位为字节) int getStrLen(char *str) { int len = 0; while (*str) { if (*str & 0x80) // 如果是中文字符 { len += 2; // 长度加2 str += 2; // 指针向后移2位 } else { len++; // 长度加1 str++; // 指针向后移1位 } } return len; } // 比较函数,用于快速排序 int cmp(const void *a, const void *b) { char *strA = *(char **)a; char *strB = *(char **)b; int lenA = getStrLen(strA); int lenB = getStrLen(strB); int len = lenA < lenB ? lenA : lenB; int i = 0, res = 0; while (i < len) { if (*strA == *strB) { strA++; strB++; i++; } else { res = strA[0] - strB[0]; break; } } if (i == len) // 如果前面的字符都相同,则判断长度 { res = lenA - lenB; } return res; } int main() { int len = sizeof(strArr) / sizeof(strArr[0]); int i; // 对字符串数组进行排序 qsort(strArr, len, sizeof(char *), cmp); // 输出排序后的结果 for (i = 0; i < len; i++) { printf("%s\n", strArr[i]); } return 0; } ``` 在上面的示例代码中,我们定义了一个`getStrLen`函数,用于获取中文字符串的长度(单位为字节)。在比较函数`cmp`中,我们先获取两个字符串的长度,并取其中较短的一个长度作为比较的长度。然后逐个比较两个字符串相应位置的字符,如果相同则继续比较下一个字符,否则返回它们的差值。如果前面的字符都相同,则根据字符串长度的差值返回结果。 在`main`函数中,我们使用了`qsort`函数对字符串数组进行排序,排序时使用了`cmp`函数进行比较。最后将排序后的结果输出即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值