24.2 工具模块的实现
2. 工具模块的实现
此项目设计一个工具模块主要是将处理文字相关的功能提取出来,独立编写,独立测试。
英文的一个字符在内存中都是占用一个字节,在控制台终端中也是显示一个字符的宽度。
汉字的编码有两种:
-
UNICODE -
与国际文字统一编码,与他国文字兼容。UNICODE 转码后使用 UTF8编码保存。一个汉字一般占用三个字节。 -
GB 系列的编码(GB2312、GBK、GB18030) -
国标编码,只与 ASCII 兼容。一个汉字使用 2 个字节或 4 个字节(极少数GB18030编码的汉字)保存。
中文的一个汉字,在 UTF8 编码时占用3个字节,在控制台终端中是显示 2 个字符的宽度。而在 GB 系列编码时大多占用 2 个字节,在控制台终端中同样是显示 2 个字符的宽度。因此需要特殊处理一下。
为了在控制台终端上能够兼容两种不同的编码。本项目编写了一个 名为 tools 的模块,相关文件有 tools.c 和 tools.h。
-
函数 is_utf8_code用来返回当前编译环境是哪种编码,如果是 UTF8 编码则返回 1 , 否则返回 0。 -
函数 get_display_width用于计算并返回 字符串s在当前环境下显示占用的宽度(以字符为单位)。 -
函数 center_to_display_width是将原字符串s按width显示宽度生成一个新字符串并存入target指向的地址中,左右两则用空格填充非内容部分。
完整代码如下:
文件 tools.c
#include <string.h>#include "tools.h"// 测试当前文件的编码,如果是 UTF8 编码,则中文两个字占 6 字节,如果是 GBK 则占 4 字节static int is_utf8_code(void){ if(strlen("中文")==6) return 1; return 0;}/* 返回字符串s的显示宽度,中文占两个英文字符的宽度 如: "abc" -->3 "中文" --> 4 "ABC中文" --> 7*/int get_display_width(const char * s){ int display_width = 0; int is_utf8 = is_utf8_code(); // 计算字符串 s 占用屏幕控制台终端的宽度。 while (*s) { if (*s >= 0 && *s <= 127) { // 英文编码 display_width++; // 英文占一个字符宽 s++; } else if(is_utf8) { // 中文 UTF8 编码 display_width += 2; // 中文占两个字符宽 s += 3; // UTF8 编码一个汉字占 3 字节内存 } else { // 中文 GBK 编码 display_width += 2; s += 2; // GBK 编码一个汉字占 2 字节内存 } } return display_width;}/* 将字符串s的左右两端添加空格,使其达到 width 的显示宽度,存入 target 中 如: s = 'ABC中文', width = 10 返回:' ABC中文 '*/void center_to_display_width(const char * s, int width, char * target){ // 得到当前字符的显示宽度 int s_width = get_display_width(s); // 计算需要补充的空格数 int fill_blank_count = width - s_width; // 计算左侧需要填充的空格数 int left_blank = fill_blank_count / 2; // 计算右侧需要填充的空格数 int right_blanks = fill_blank_count - left_blank; // 使用指针指向 target 的内容 char * ptar = target; int i; if (fill_blank_count < 0){ // 宽度小于 字符串宽度 strcpy(target, s); return; } // 将 target 的左侧填充 fill 空格 for (i = 0; i < left_blank; i++, ptar++) { *ptar = ' '; // 填充空格 } // 将 s 追加到 target 后面 while(*s) { *ptar = *s; s++; ptar++; } // 将 target 的右侧填充空格 for (i = 0; i < right_blanks; i++, ptar++) { *ptar = ' '; // 填充空格 } *ptar = '\0'; // 尾零}
文件 tools.h
#ifndef __TOOLS_H#define __TOOLS_H/* 返回字符串s的显示宽度,中文占两个英文字符的宽度*/int get_display_width(const char *s);/* 将字符串s的左右两端添加空格,使其达到 width 的显示宽度,存入 target 中*/void center_to_display_width(const char * s, int width, char * target);#endif // __TOOLS_H
夜雨聆风