2. 工具模块的实现
此项目设计一个工具模块主要是将处理文字相关的功能提取出来,独立编写,独立测试。
英文的一个字符在内存中都是占用一个字节,在控制台终端中也是显示一个字符的宽度。
汉字的编码有两种:
- UNICODE
- 与国际文字统一编码,与他国文字兼容。UNICODE 转码后使用
UTF8编码保存。一个汉字一般占用三个字节。
- 与国际文字统一编码,与他国文字兼容。UNICODE 转码后使用
- 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