大家一起来研究汉字(2)

孩皮妞野 2002-09-11 08:39:21
参:http://www.csdn.net/expert/topic/1011/1011038.xml?temp=.1869928

...全文
122 52 打赏 收藏 转发到动态 举报
写回复
用AI写文章
52 条回复
切换为时间正序
请发表友善的回复…
发表回复
大大怪老张 2002-09-14
  • 打赏
  • 举报
回复
关注
孩皮妞野 2002-09-14
  • 打赏
  • 举报
回复
我现在单贴只能给200分,向多给都不行啊。 不知道有没有漏了哪位?
再说明一下, xqr和hawk_sun我会另贴给。 这个贴没给他们分不表明他们的回贴没有得到认可。
孩皮妞野 2002-09-14
  • 打赏
  • 举报
回复
这个贴子先结掉, Hawk_sun和xqr两位的分我另贴再给。
孩皮妞野 2002-09-14
  • 打赏
  • 举报
回复
谢谢Hawk_sun, 看来你还有很多好料, 我会专门开个贴子,邀请你去主持的。

孩皮妞野 2002-09-13
  • 打赏
  • 举报
回复
其实这个工作远不象我起初想的那么繁琐。

我花了不到10分钟,又找出了6个,后面剩的字非常有限了。
一丁万不且 礼丣並临丵 乾亁亂僊僵 亸償儭儳儶 儷亹儽儾囔
前25个,现在可以处理25划以下的汉字了。


现在可能有一个现实的问题,就是会有洞,比如有29划和31划而没有30划的,这会破坏美感,不过不难处理。

剩下没有数的汉字, 这么粗浅的问题,是不准备劳动大家了。
壪廳彠戅戆攮斸曯欖欘欙欚欛欝灢灣爥爦犪矘矡籫籭籮糶纘纙纚纛臠臡蠻襽覊觿讗讘讙讛豒躡躢躣躥鑭鑯鑰鑱鑲鑳鑵靉韉顱顲饞饟馕髗鬣鱨鱬鱭鱰鱴鱶鸋鸌鸍鸎鸐鸑麡黵鼈鼉鼝鼟齇齸齺齻龣圞欜氎灎灤灦癳矚籯籰糳糷虊虪蠼讚趲躦躧躪轥釁釃釄釅鑴鑶鑷鑸鑹鑺靊顴飌驠驡驢驣驥鱱鱲鱳鱵鸓鸔黶鼊龤龥灥灧灨犫纜纝虌蠽蠾蠿讜讝讞豓貜躩軉鑻鑼鑽鑾靋靌靍靎顳飍飝饠饡馫驤驦驧驩鬤鬮鬰鱷鱸鸕鸖鸗黷齈囖戇欞欟爧癴豔躨鑿钀钁钂钄雧驨鸘鸙鸚鸛麢黸鼺齼齽龞爨纞虋讟钃靏韊驘驪鬱鱹鸜麷厵癵籱饢驫鱺鸝鸞灩麣蘒灪籲龖爩鱻麤龗齾齉靐龘
sjd163 2002-09-13
  • 打赏
  • 举报
回复
不明白意义何在?
huzhangyou 2002-09-13
  • 打赏
  • 举报
回复
好贴
收藏

Hawk_sun 2002-09-13
  • 打赏
  • 举报
回复
继续告诉你们几个检索拼音的API
Retrieves the list of characters or words from one character or word (ANSI implementation).

Syntax

HRESULT GetConversionListA(
HKL hKL,
HIMC hIMC,
LPSTR pSrc,
UINT uBufLen,
UINT uFlag,
CANDIDATELIST *pDst,
UINT *puCopied
);

Parameters

hKL
[in] Handle to the keyboard layout.
hIMC
[in] Handle to the input context.
pSrc
[in] Address of a string value containing a null-terminated character string.
uBufLen
[in] Unsigned integer value that contains the size of the destination buffer, in bytes.
uFlag
[in] Unsigned integer value that contains action flags.
pDst
[out] Address of the CANDIDATELIST structure that receives the conversion result.
puCopied
[out] Address of an unsigned integer value that receives the number of bytes copied to the specified buffer. If uBufLen is zero, puCopied receives the number of bytes needed to receive the list.

///与笔划有关的微软的文档
//注意:几个词的翻译
当然最重要的一个:stroke order :笔划顺序

Da Yi, Array, and Internal Code

Two other input methods that build characters using radicals are the Da Yi input method and the Array input method. The Da Yi method defines 40 basic radicals, arranged on a standard 101-key keyboard and corresponding to the stroke order in which characters are handwritten. A maximum of four basic radicals make up a Chinese character. The Array input method defines 10 basic keystrokes, numbered 0 through 9, that represent basic radicals. The columns of keys beneath each number—for example, on a US keyboard the letters QAZ beneath 1 and the letters WSX beneath 2—are used to select specific characters.

Another method is the Internal Code input method, which allows the user to select a character by typing in its Big-5 code-point index.



Hawk_sun 2002-09-13
  • 打赏
  • 举报
回复
看这里这么热闹,我来说几句吧!
To : ALNG()
API中的确有可以获得汉字的拼音的函数,但是这些API是借助输入法来实现的,因为作为一个输入法,它不仅有从拼音到汉字的功能,而且还有从汉字到拼音的功能,微软的微软输入法就有这个功能。我不敢确定我讲的你们是否都已经知道,但是肯定不是所有的人都知道,讲出来大家共同进步吧!

这里有几个API:
GetKeyboardLayoutList:得到当台计算机中安装的的输入法列表; 定义如下:
UINT GetKeyboardLayoutList(
int nBuff, // size of array
HKL FAR *lpList // array of input locale identifiers
);
Parameters
nBuff
[in] Specifies the maximum number of handles that the buffer can hold.
lpList
[out] Pointer to the buffer that receives the array of input locale identifiers

ImmEscape :得到输入法的名称;
该函数的定义如下:
LRESULT ImmEscape(
HKL hKL,
HIMC hIMC,
UINT uEscape,
LPVOID lpData
);
Parameters
hKL
[in] Input locale identifier.
hIMC
[in] Handle to the input context.
uEscape
[in] Index of the operations. For more information, see IME Escapes.
lpData
[in] Pointer to the data required for the escape specified in uEscape. Depending on the escape, when the function returns lpData may contain the result of the escape. For more information, see IME Escapes.

ImmGetConversionList: 看看这个输入法是否支持Reverse Conversion功能,如果支持则继续使用此函数,可取得组字字根信息
DWORD ImmGetConversionList(
HKL hKL,
HIMC hIMC,
LPCTSTR lpSrc,
LPCANDIDATELIST lpDst,
DWORD dwBufLen,
UINT uFlag
);
Parameters
hKL
[in] Input locale identifier.
hIMC
[in] Handle to the input context.
lpSrc
[in] Pointer to a null-terminated character string.
lpDst
[out] Pointer to a CANDIDATELIST structure that receives the conversion result.
dwBufLen
[in] Specifies the size of the destination buffer, in bytes. If this parameter is zero, the function returns the buffer size needed for the complete conversion result.
uFlag
[in] Action flag. This parameter can be one of the following values.

理解了以上几个函数,得到汉语拼音已经不是什么神秘的事.但是你要在得到汉语拼音的同时获得声调,这里就有一个技巧了。
我们都知道,一级字库按照拼音排序,二级字库按照部首排序,我们对6763个汉字的区位码做区间分析,就很容易得出四个声调的位置了。

关于检索汉字的笔划,我不是很熟,但是完全可以从API来获得,至于说怎么做,你另开贴子吧,我们再讨论!这里也是利用windows的API结合输入法来实现的,而且,据我所知,很多做手写识别的软件中都有这张表,它不光是汉字的笔划数,就连汉字的笔顺都有,很惊讶吧!



allmywant 2002-09-13
  • 打赏
  • 举报
回复
mark
孩皮妞野 2002-09-13
  • 打赏
  • 举报
回复
笔划的问题解决的,下一步再做拼音。 从应用上讲拼音会有用得多。

unsigned stroke_count(const char * const cc){
const static char ccs[] =
"一丁万不且礼丣並临丵乾亁亂僊僵亸償儭儳儶"
"儷亹儽儾囔圞灥囖爨厵灩麣蘒灪爩齾齉靐龘" ;
# define CCS_SIZE ( sizeof(ccs)-1 )
// 对序号大于31的,其笔划数要进行调整,这是调整数组
const static short adjust[]=
{-2, -7, -2, -2, -1, -1, 1, 9 };
unsigned i = 0;
for( ; i < CCS_SIZE; i += 2 )
if(compare_chinese_stroke(ccs+i,cc)>0) break;
i >>= 1; // divide i by 2
if(i == CCS_SIZE) return 0; // not a known Chinese Charater
if(i>31) i += adjust[i-32];
return i;
# undef CCS_SIZE
}
孩皮妞野 2002-09-12
  • 打赏
  • 举报
回复
这是我用你的函数对我的1-19划的特征字数组的返回结果,不太理想,是不是要用其他API?

一 1
丁 1
万 1
不 2
且 4
礼 5
丣 3
並 3
临 7
丵 4
乾 4
亁 6
亂 9
僊 9
僵 14
亸 10
償 11
儭 9
儳 11

我的stroke_count有个小bug, 要修改一下:

// 目前可以处理所有18划及以下的汉字,对18划以上的返回-1.
// 扩展ccs数组后行为立刻正确

unsigned stroke_count_1(const char * const cc){
const static char *ccs="一丁万不且礼丣並临丵乾亁亂僊僵亸償儭儳";

for(unsigned i=0; i<sizeof(ccs)/sizeof(ccs[0])-1; i+=2)
if(compare_chinese_stroke(ccs+i,cc)>0)
return i >> 1;
return -1; //stroke count unknown
}


孩皮妞野 2002-09-12
  • 打赏
  • 举报
回复
我犯了个错误,我原来的实现也叫stroke_count, 参数类型略有不同,结果是调用我的那个。

你上面的好像总返回1.

我把hDC初始化为Form1->Canvas->Handle.

你也用BCB呀, API玩得不赖啊!
孩皮妞野 2002-09-12
  • 打赏
  • 举报
回复
好的,我等你!
xqr 2002-09-12
  • 打赏
  • 举报
回复
ALNG(?)老弟:

对代码未作实质性修改,在C++Builder下运行通过。结果如下:
"一十人大"均返回1, "口"返回2, "三中"均返回3, "田"返回5
"灪籲龖爩鱻麤龗齾齉靐龘"分别返回 17,18,14,16,30,22,18,17,19,30,21

结果不理想,是算法问题还是TrueType的笔画划分法有别于常规?
待我抽空检查一下统计strokes中有无失误。今天可能来不及,明日要外出。
////////////////////////////////////////////////////////////////
unsigned stroke_count(const char * const cc)
//cc[0]和cc[1]存放着汉字, 返回汉字的笔划数
{
HDC hDC;
char *FaceName="宋体";
HFONT hFont,hOldFont;
char ch[3];
WORD uChar; //转换后的待读的字
GLYPHMETRICS gm;
DWORD cbBuffer; //全部笔画数据的体积
void FAR *lpBuffer; //笔画数据首地址
HGLOBAL hBuffer;
MAT2 mat2;
TTPOLYGONHEADER tph;
DWORD lpb=0; //地址偏移量
unsigned strokes=0; //笔画数

//将字符串cc转换为WORD类型的uChar;
ch[0]=cc[1];
ch[1]=cc[0];
ch[2]='\0';
_fmemcpy(&uChar,ch,2);

mat2.eM11.fract=0;
mat2.eM11.value=1;
mat2.eM12.fract=0;
mat2.eM12.value=0;
mat2.eM21.fract=0;
mat2.eM21.value=0;
mat2.eM22.fract=0;
mat2.eM22.value=1;

//创建逻辑字
hDC=GetDC(Application->Handle);
hFont=CreateFont(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FaceName);
hOldFont=(HFONT)SelectObject(hDC,hFont);
//获取全部笔画数据的体积
cbBuffer=GetGlyphOutline(hDC,uChar,GGO_NATIVE,(LPGLYPHMETRICS)&gm,0,NULL,
(LPMAT2)&mat2);
hBuffer=GlobalAlloc(GHND,cbBuffer);
lpBuffer=(void FAR *)GlobalLock(hBuffer);
//获取笔画数据首地址
GetGlyphOutline(hDC,uChar,GGO_NATIVE,(LPGLYPHMETRICS)&gm,cbBuffer,
(void *)lpBuffer,(LPMAT2)&mat2);
//统计笔画数
while(cbBuffer>=sizeof(TTPOLYGONHEADER))
{
_fmemcpy((char *)&tph,(char *)lpBuffer+lpb,sizeof(TTPOLYGONHEADER));
cbBuffer-=tph.cb;
lpb+= tph.cb;
strokes++; //笔画数
}
GlobalUnlock(hBuffer);
GlobalFree(hBuffer);
SelectObject(hDC,hOldFont);
DeleteObject(hFont);
ReleaseDC(Application->Handle, hDC);
return strokes;
}
孩皮妞野 2002-09-12
  • 打赏
  • 举报
回复
是 xqr(星球人) ( )兄;

我试了一些,大多数可以,但是对"一", 返回0, 错误;

对笔划较多的,全部错误,如:"灪籲龖爩鱻麤龗齾齉靐龘"

可不可以麻烦你看看有没有修正的法子?

btw: xqr的程序在BCB下的修改版:


unsigned stroke_count(const char * const cc)
//cc[0]和cc[1]存放着汉字, 返回汉字的笔划数
{
HDC hDC; // strange enough, an uninitialized hDC works just fine.
char *FaceName="宋体";//,"黑体")

HFONT hFont,hOldFont;
char ch[3];
WORD uChar; //转换后的待读的字
GLYPHMETRICS gm;
DWORD cbBuffer; //全部笔画数据的体积
void FAR *lpBuffer; //笔画数据首地址
HGLOBAL hBuffer;
MAT2 mat2;
TTPOLYGONHEADER tph;
DWORD lpb=0; //地址偏移量
int strokes=0; //笔画数

//将字符串cc转换为WORD类型的uChar;
ch[0]=cc[1];
ch[1]=cc[0];
ch[2]='\0';
memcpy(&uChar,ch,2);

mat2.eM11.fract=0;
mat2.eM11.value=1;
mat2.eM12.fract=0;
mat2.eM12.value=0;
mat2.eM21.fract=0;
mat2.eM21.value=0;
mat2.eM22.fract=0;
mat2.eM22.value=1;

//创建逻辑字
hFont=CreateFont(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FaceName);
hOldFont=(HFONT)SelectObject(hDC,hFont);
//获取全部笔画数据的体积
cbBuffer=GetGlyphOutline(hDC,uChar,GGO_NATIVE,(LPGLYPHMETRICS)&gm,0,NULL,
(LPMAT2)&mat2);
hBuffer=GlobalAlloc(GHND,cbBuffer);
lpBuffer=(void FAR *)GlobalLock(hBuffer);
//获取笔画数据首地址
GetGlyphOutline(hDC,uChar,GGO_NATIVE,(LPGLYPHMETRICS)&gm,cbBuffer,
(void *)lpBuffer,(LPMAT2)&mat2);
//搜索笔画数
while(cbBuffer>=sizeof(TTPOLYGONHEADER))
{
memcpy((char *)&tph,(char *)lpBuffer+lpb,sizeof(TTPOLYGONHEADER));
cbBuffer-=tph.cb;
lpb+= tph.cb;
strokes++; //笔画数
}
GlobalUnlock(hBuffer);
GlobalFree(hBuffer);
SelectObject(hDC,hOldFont);
DeleteObject(hFont);
return strokes;
}
Chxis 2002-09-12
  • 打赏
  • 举报
回复
gz
suerain 2002-09-12
  • 打赏
  • 举报
回复
错了,是五笔字型,^_^
suerain 2002-09-12
  • 打赏
  • 举报
回复
好像有按笔划输入的输入法,无比字型好像也是要拆分汉字的,不知道可不可以
研究一下他们的实现方法
孩皮妞野 2002-09-12
  • 打赏
  • 举报
回复
TR@SOE()兄,对了,pazee兄也提到了,通过API一定可以完成,可惜我们对API太陌生了。

我在研究汉字时发现,相同笔划的,同样偏旁部首的是放在一起的。实际上这个工作MS已经做了,而且通过API提供了,奈何我们不会用啊!
加载更多回复(32)

13,826

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧