Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
输入法
拼音
汉字输入
一个非常小巧高效的pinyin输入法
1.00
发布于 2021-01-08 21:19:30 浏览:1619
订阅该版
[tocm] ![pinyin_ime.jpg](https://oss-club.rt-thread.org/uploads/20210108/95361c3f50d1075a0806edea5850a831.jpg) 找了许多输入法,都是很大很慢,就自己撸了个,效率快多了。 这是第一版,缓冲了字库数据,缺点是效率低了点,优点是方便以后扩展新功能 [pinyin.c](https://oss-club.rt-thread.org/uploads/20210109/a942512b859feb006799e98b8d177e40.c) [pinyin.h](https://oss-club.rt-thread.org/uploads/20210109/4db48f39a7f09864b9e342200366277f.h) 这是简化的版本,由于撸掉了strlen等各种计算,有极高的检索效率 [pinyin.c](https://oss-club.rt-thread.org/uploads/20210111/ef256ccf954bd5fd9b37ba5f0dedea51.c) [pinyin.h](https://oss-club.rt-thread.org/uploads/20210111/e0deaead1ec83459b33a739bcf857227.h) 第一个版本基本走的商业输入法的路子,各种缓冲一堆堆,然并无卵用,如前说述,是扩展更多新功能必须的做法,例如多拼音待选,根据检索频度调整词汇位置,录入新词汇等. 第二个版本则是纯考虑嵌入式的特点,废弃字符串长度计算,检查等操作,缺点是字词库必须符合要求的个数.两者各擅胜场,无所谓那个更好. 代码很简单,输入法实现为一个独立的模块,可以方便的集成到需要的地方,用串口都能控制它工作。 #### 使用方法 第一步,定义一个input_method_t类型的变量。 例如。 ```c static input_method_t myime; ``` 第二步,初始化myime。 ```c pinyin_init(&myime); ``` 第三步,调用以下接口录入一个字母;c只接受a-z,A-Z。 ```c pinyin_getin_letter(&myime, c); ``` 例如。 ```c pinyin_getin_letter(&myime, 'a'); ``` 执行这个函数后,与字母a有关的汉字已经拷贝到myime下。 inbuf中存储的是输入的字母a。 wordstr存储的是当前的一个页,显示内容如下。 ``` 1.安 2.按 3.爱 4.阿 5.暗 6.啊 7.挨 8.碍 9.凹 ``` 如果有GUI系统,就可以用label控件显示这两条内容。 如果字比较多,会有多个page。 page_numbs表示有几个page。 page_index表示当前的是哪个page。 用户可以直接更改page_index的值实现翻页,再调用 ```c pinyin_generate_page(&myime); ``` 实现页面内容更新。 左翻页示例代码。 ```c if (ime->page_numbs > 1) { if (ime->page_index > 0) ime->page_index -= 1; memset(ime->wordstr, 0, IME_WORDSTR_SZ); pinyin_generate_page(ime); //此处可显示wordstr中的内容到GUI } ``` 右翻页示例代码。 ```c if (ime->page_numbs > 1) { if ((ime->page_index + 1) < ime->page_numbs) ime->page_index += 1; memset(ime->wordstr, 0, IME_WORDSTR_SZ); pinyin_generate_page(ime); //此处可显示wordstr中的内容到GUI } ``` 如果需要取消一个输入的字母,调用函数。 ```c pinyin_backspace(&myime); ``` 当需要选中一个字或词时,示例代码。 ```c unsigned short zh[16] = {0}; pinyin_getout_zhstring(&myime, zh, 4); ``` 以上面的wordstr内容为例进行说明。 ``` 1.安 2.按 3.爱 4.阿 5.暗 6.啊 7.挨 8.碍 9.凹 ``` zh[]中会返回"暗",因为是编号从0开始的。 如果想方便的处理page中的每个汉字或词语,也可以直接使 用数组myime.s,数组s中保存了page中的字或词。 ``` s[0]安 s[1]按 s[2]爱 s[3]阿 s[4]暗 s[5]啊 s[6]挨 s[7]碍 s[8]凹 ``` #### 结构体成员说明 ###### 结构体struct input_method说明。 ```c type;//表示检索的是字典还是词典。 *dicts;//当前字典。 *terms;//当前词典。 inbuf;//保存了输入的ascii字符串。 zhbuf;//保存了当前字典或词典下的所有内容。 wordcnt;//反映了字/词典中每个字词的长度。 //如果检索的是字典wordcnt=1。 //如果检索的是词典wordcnt=struct rtgui_terms下的cnt。 inlen;//保存了输入的ascii字符串长度。 zhlen;//保存了检索到的字/词的个数。 cnt_per_page;//保存了一个page中可以显示多少个词。 cnt_cur_page;//保存了当前page中有多少个词。 page_index;//记录当前page编号。 page_numbs;//记录总的page数量。 wordstr;//由当前page生成的带编号的待选词字符串,用于GUI显示。 s[9][20]; //对应wordstr的内容,为了方便处理字/词。 ``` --- ====================我是一条华而不实分隔线======================= 设计这个pinyin输入法的初衷是任何地方都能用,所以它是一个独立的模块, 设计目标是一定要快速反应,即使跑在8051上,应该也能流畅. 所以综合参考了许多输入法的实现,就定稿成目前的版本,称之为V0.1吧. ## 下面分析一下设计思路. 由于需要它能尽可能的快,例如键入一个字母'a'后,能够最短时间内就能反馈回备选词 列表,这个特点在低速设备上会非常受益.所以对字典/词典根据字母进行分类.这样在 浏览字典时就大大缩小了范围,避免做更多无用功. 有的输入法是字典的每条记录的一个 拼音只对应一个汉字或词语,且都记录在一个字典列表中;以GB2312编码6700多个和 GBK编码21000多个的体量,这个检索工作是惊人的.所以坚决使用字母分类字典,现在是 一级分类,如果词语量非常大,可以二级分类,即用第一个字母确定字母字典,第二个字母 确定子分类字典.这样可以将检索范围进一步缩小,以提高检索速度. 字典的第二个制定原则是,一个pinyin对应多个同样发音的字词.用户键入拼音后往往都 会在待选列表中观察一会再选择.如果首页未命中,需要翻页.那么这些待选词当然是在一 个线性表中更方便和快速的处理,否则还要从字典中检索出所有同音的建立线性表,导致 处理时间不确定,结果是字典比较小的顺畅,字典大的卡顿.使用同发音字词集中在一起的 原则后,处理的代码简化了,效率也高. 同音字词放在一个线性表中,也可以方便加入热频词功能,可以根据字词的使用频率排序; 该原理比较简单,这个版本暂时不加. **第三个原则**是,不使用文件系统存放字词库.如果使用了文件系统,拼音输入法的应用 范围也比较受限(没文件系统不让玩),一是文件系统的访问速度瓶颈,一是需要额外RAM 中建立字库cache.商业输入法都是这么做的,这里主要面向嵌入式,牺牲点ROM换取高效率, 是合适的. 核心代码寥寥几行,看源文件吧,上面已经将源代码干的事说明白了.
查看更多
liuduanfei
2021-01-09
这家伙很懒,什么也没写!
厉害,大佬可以搞成软件包啊
10
个回答
默认排序
按发布时间排序
小住住
认证专家
2021-01-08
这家伙很懒,什么也没写!
这个厉害,输入法都可以。
sync
2021-01-09
这家伙很懒,什么也没写!
先收藏了,楼主威武!
RiceChen
认证专家
2021-01-09
内核/软件架构/开源
牛逼
Jone
2021-01-09
写了还是懒
收藏了。。。
yangjie
认证专家
2021-01-09
hello
![赞](https://oss-club.rt-thread.org/uploads/20210109/a4a32819b175866a848198214cbf76c6.png)
pkokoc
2021-01-09
这家伙很懒,什么也没写!
牛B,加到软件包里去
bernard
2021-01-10
这家伙很懒,什么也没写!
?大佬
iamyhw
2021-01-10
这家伙很懒,什么也没写!
初步计算后,感觉不需要将字库的数据缓存起来,原因是,缓存前检查一遍数据中是否有空格,然后再复制到缓存中。这个步骤相当于读了两遍数据,以后生成page数据又读一遍。太丧了。应该只一遍就到生成page。嗯,参考别人的坏处就是思路被带着走了。如果字典词典数据格式是完全正确的,的确不需要检查空格啥的。可以提供一个专门工具专门检查字典词典,代码中取消检查,这样才是最快的! [pinyin.c](https://oss-club.rt-thread.org/uploads/20210112/d2c17b9c31833deaad773d8a4dfedb01.c) [pinyin.h](https://oss-club.rt-thread.org/uploads/20210112/e0deaead1ec83459b33a739bcf857227.h) ``` static const char **dicts_second[26] = { "ino","aeiou","aehiou","aeiou","inr","aeou","aeou","aeou",NULL,"iu","aeou","aeiouv","aeiou", "aeiouv","u","aeiou","iu","aeiou","aehiou","aeiou",NULL,NULL,"aeou","iu","aeiou","aehiou" }; ``` 与首楼第二版的区别, 在pinyin_update_zhbuf()开始处加入这个,快速剔除非完整拼音直接去查找词库, ``` if (ime->inlen >= 2) { //剔除无效拼音,只判断前两个字母,再多就与全检索一遍的效率差不多了 if (!strchr(dicts_second[ime->inbuf[0]-'a'], ime->inbuf[1])) goto findterms; } ``` 查找词库,首先匹配前面的字符串是否有正确的拼音,如果该拼音与词汇同时有效,优先选择词汇,同时完整拼音高亮,等待用户选字,这个逻辑就有点复杂了,词库的规模如果非常大,这个的检索效率会是一个问题. 现在对反应时间比较满意了,剩余的就是完善词库.词库尽量因需求而定,别搞的太大,建议仅包含些行业相关的就行了.目前人类的词库不知道有多少个T的容量,是一个海量. 检索过程有3种情况, -直接从字库种找到 -再次从词库种找到 -最差的是根据输入的拼音,从字库种匹配到一个最长的 所以词库的编写需要根据检索算法有针对性的定制, 字库只能匹配到完整的拼音,所以词库的拼音前面最好有完整的拼音存在,因为按照上面的原则,最差的情况,可以匹配到一个合适的字库来显示. 例如: 如果有个词库{"zhangf","丈夫,涨幅"} 现在键入了zhangfe,最差可以显示zhang的词库, 如果键入的是zf,如果没有该词条,那就没有任何东西可以显示.
搬砖仔
2021-01-11
这家伙很懒,什么也没写!
厉害了
撰写答案
登录
注册新账号
关注者
1
被浏览
1.6k
关于作者
iamyhw
这家伙很懒,什么也没写!
提问
6
回答
128
被采纳
6
关注TA
发私信
相关问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
freemodbus主机在freertos的适配,参考rtthread例程
2
开源共生 商业共赢 | RT-Thread 2024开发者大会议程正式发布!
3
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
4
RT-Thread EtherKit开源以太网硬件正式发布
5
如何在master上的BSP中添加配置yml文件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
a1012112796
20
个答案
3
次被采纳
张世争
12
个答案
3
次被采纳
踩姑娘的小蘑菇
7
个答案
3
次被采纳
rv666
9
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部