转载自:点击打开链接
由于项目需要,得做一个嵌入式输入法,但是网上一直没找到相似的模版或者资料。后来总监说这个不急,慢慢搞。因此有了足够的时间自己来做一个。
数据库的准备
首先是汉字的数据库。分为拼音输入法和五笔输入法。在上网找到了汉字文档归纳。如下
拼音输入法的 txt 文档:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
。。。。。
胺an
鞍an
谙an
埯an
揞an
犴an
庵an
桉an
铵an
鹌an
黯an
暗暗anan
岸边anbian
暗藏ancang
。。。。。。
|
五笔输入法的 txt 文档:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
。。。。
阿 BS
啊 KB
锕 QBSK
嗄 KDHT
嗄 KDHT
哎 KAQ
哀 YEU2
唉 KCT
埃 FCT
挨 RCT
锿 QYEY
捱 RDFF
皑 RMNN
。。。。
|
接下来做的事就是将 txt 中的拼音输入法以及五笔输入法文档中的内容分别录入拼音输入法和五笔输入法数据库 db 中。这儿我选择的是 sqlite3 这个数据库。当然还有其他很多牛逼的数据库,不过对于我这个简单的输入法 sqlite3 就已经足够了。
sqlite3 的使用
在录入过程中,我们只需要 sqlite3 中的创建数据库语句以及插入语句:
创建数据库:
1
|
create table pinyin(hanz varchar(20),pinyin varchar(20))
|
插入语句:
1
|
insert into pinyin(hanz, pinyin) values(
'喊'
,
'han'
)
|
以上是拼音输入法的,五笔输入法也一样。
汉字的提取
在我找到的拼音输入法的文档中,汉字与拼音是挨着的,没有间隔,而五笔输入法的文档是有间隔的。只要有间隔,将汉字区分出来就非常简单,可是没有间隔就不好说了。所以接下来遇到了这个问题,怎样将没有间隔的字符串中的汉字提取出来。
首先明白一点,汉字不是在任何时候都是占两个字节的!(可能是我太笨了,一直以为是两个字节)。如果按照两个字节来做,很可能出现汉字乱码。在不同的编码中汉字所占的字节数不同。如在GBK(如GB2312) 编码中汉字占两个字节,在 UTF-8 中汉字占三个字节,而我的电脑是 UTF-8 的。在网上搜索了一些资料,我选择了一个方案:将 UTF-8 转换为 GBK,然后对 GBK 编码下的文档进行数据库的录入工作。
其中 UTF-8 转换为 GBK 可以在网上找一个工具,直接就转换了。
接下来就是 GBK 编码下的汉字提取:
-
汉字在该编码下占两个字节,在网上搜索到当得到一个字符是小于零,那个该字符必定与下一个字符组成一个汉字。当然,这个不适合所有情况,但就针对我这个项目而言足够了,至少没有发现乱码的问题。
-
然后对两个文档进行格式的分析。 拼音输入法文档是汉字与拼音连在一起的没有间隔。而五笔输入法的汉字与五笔是有间隔的,但值得注意的是:这里的间隔不一定就是空格,还可能是 TAB 键!而这里就是 TAB 。至于是怎么发现的,直接将其值的十六进制打印出来就知道了。
-
将汉字和拼音以及五笔分别提取出来后,我们最好还要将其转换回 UTF-8 的编码格式。这里需要头文件“iconv.h”,它是将一种已知的字符集文件转换成另一种已知的字符集。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
while
(EOF != (ch=
fgetc
(fp)))
{
if
(ch < 0)
//提取汉字
{
printf
(
"in hanzi \n"
);
hanzi[0] = ch;
ch =
fgetc
(fp);
hanzi[1] = ch;
hanzi[2] =
'\0'
;
res = g2u(hanzi,
strlen
(hanzi), out, OUTLEN);
//将 GBK 转换回 UTF-8 编码格式
printf
(
"res = %d\n"
, res);
printf
(
"hanzi = %s\n"
, out);
strcat
(line, out);
strcat
(han, out);
}
else
if
(ch ==
'\n'
)
//表示一行已经读完
{
// gbk to utf8
printf
(
"gbk->utf8: %s\n"
, line);
//out);
printf
(
"han = %s\n"
, han);
printf
(
"pinyin = %s\n"
, pinyin);
memset
(sql_insert_data, 0,
sizeof
(sql_insert_data));
deletspace(pinyin, temp);
//删除间隔
printf
(
"temp: %s, len = %d\n"
, temp,
strlen
(temp));
sprintf
(sql_insert_data,
"insert into pinyin(hanz, pinyin) values('%s', '%s')"
, han, temp);
//sqlite3 的插入语句
printf
(
"%s\n"
, sql_insert_data);
ret = sqlite3_exec(db, sql_insert_data, NULL, NULL, &errmsg);
//执行插入语句
if
(ret != SQLITE_OK)
{
fprintf
(stderr,
"insert into db fail:%s\n"
, errmsg);
}
memset
(line, 0,
sizeof
(line));
memset
(han, 0,
sizeof
(han));
memset
(pinyin, 0,
sizeof
(pinyin));
memset
(temp, 0,
sizeof
(temp));
}
else
//拼音以及五笔
{
en[0] = ch;
en[1] =
'\0'
;
res = g2u(en,
strlen
(en), out, OUTLEN);
printf
(
"out: %s\n"
, out);
strcat
(pinyin, out);
strcat
(line, out);
}
}
sqlite3_free(errmsg);
sqlite3_close(db);
fclose
(fp);
printf
(
"\n"
);
return
0;
}
|
其中 deletspace() 函数不仅仅删除间隔中的 TAB,还删除了每行末尾的一个 '\r' 字符。这些字符一定要删除干净,否则后面没法用。
源代码下载地址:输入法字符数据库的录入