delphi

자모 분리 및 결합

knoen 2014. 1. 24. 23:00


http://wyb330.egloos.com/3048787

한글 자모 분리 및 결합

한국어 분석기를 만들려고 하니 형태소 분석을 위해 음절을 자모로 분리해야 할

필요가 생겼다.

즉 "한글"을 "ㅎ" +"ㅏ"+'ㄴ"+"ㄱ"+"ㅡ"+"ㄹ" 로 분리해서 어절의 원형을 찾아야

한다. 유니코드에서 한글 음절은 AC00 ~ D7A3의 영역에 있다.

유니코드에서 한글 한 글자의 값은 다음 공식에 의해 찾을 수 있다.

 

코드 = AC00 + [초성번호]*588 + [중성번호]*28 + [종성번호]

 

이를 이용하면 초성/중성/종성을 분리해 낼 수 있다.

 

유니코드에서 한글과 관련된 코드는 세가지 영역으로 나누어져 있다.

 

1100 ~ 11FF  Hangul Jamo  한글 자모

 

3130 ~ 318F  Hangul Compatibility Jamo  호환용 한글 자모

 

AC00 ~ D7A3  Hangul Syllables  한글 글자 마디

 

이 영역의 코드값은 윈도우즈 문자표에서 확인할 수 있다.

 

unit Hanguel;

interface

uses
  SysUtils;

const
  ChoSungTbl:  WideString = 'ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ';
  JungSungTbl: WideString = 'ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ';
  JongSungTbl: WideString = ' ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ';
  UniCodeHangeulBase = $AC00;
  UniCodeHangeulLast = $D79F;

type
  TSyllable = class
  public
    class function AnsiToUnicode(const Source: AnsiString): WideString;
    class function SplitJaMo(Unicode: WideChar; var ChoSung, JungSung, JongSung: WideChar): Boolean; overload;
    class function SplitJaMo(const Source: WideString): WideString; overload;
    // 초성, 중성, 종성을 가지고 한글자로 조합합니다
    // 예) ㄱ + ㅜ + ㄹ => 굴
    class function MergeJaMo(ChoSung, JungSung, JongSung: WideChar): WideChar;
  end;

implementation

{ TSyllable }

class function TSyllable.AnsiToUnicode(const Source: AnsiString): WideString;
begin
 // Result:= StringToWideChar(Source, Result, Length(Source)+ 1);
  Result:= WideString(Source);
end;

// Unicode가 한글 음절이면 True를 그렇지 않으면 False를 돌려준다.
class function TSyllable.SplitJaMo(Unicode: WideChar; var ChoSung, JungSung,
  JongSung: WideChar): Boolean;
var
  Code: Cardinal;
  Value, ChoSungIdx, JungSungIdx, JongSungIdx: Integer;
begin
  Result:= True;

  Value:= Integer(UniCode);
  if (Value < UniCodeHangeulBase) or (Value > UniCodeHangeulLast) then
    // (Value > (UniCodeHangeulBase + (19*588)+(21*28) + 28)) then
  begin
    Result:= False;
    Exit;
  end;

  Code:= Value -  UniCodeHangeulBase;
  ChoSungIdx := Code div (21 * 28);   // 초성 Index
  Code := Code mod (21 * 28);
  JungSungIdx := Code div 28;         // 중성 Index
  JongSungIdx := Code mod 28;         // 종성 Index

  ChoSung:= ChoSungTbl[ChoSungIdx + 1];
  JungSung:= JungSungTbl[JungSungIdx + 1];
  JongSung:= JongSungTbl[JongSungIdx + 1];
end;

class function TSyllable.MergeJaMo(ChoSung, JungSung, JongSung: WideChar): WideChar;
var
  Code, ChoSungIdx, JungSungIdx, JongSungIdx: Integer;
begin
  Result:= #0;
  ChoSungIdx:= Pos(ChoSung, ChoSungTbl) - 1;
  JungSungIdx:= Pos(JungSung, JungSungTbl) - 1;
  JongSungIdx:= Pos(JongSung, JongSungTbl) - 1;

  if (ChoSungIdx = -1) and (JungSungIdx = -1) and (JongSungIdx = -1)  then Exit;

  Code:= UniCodeHangeulBase +(ChoSungIdx * 21 + JungSungIdx) * 28 + JongSungIdx;

  Result:= WideChar(Code);
end;

class function TSyllable.SplitJaMo(const Source: WideString): WideString;
var
  I: Integer;
  ChoSung, JungSung, JongSung: WideChar;
begin
  Result:= '';
  if Source = '' then Exit;
  for i := 1 to Length(Source) do
  begin
    if not SplitJaMo(Source[I], ChoSung, JungSung, JongSung) then
      Result:= Result + Source[I]
    else Result:= Result + ChoSung + JungSung + JongSung;
  end;  
end;

end.


'delphi' 카테고리의 다른 글

how to save everything in the webbrowser as Image  (0) 2014.01.26
한글 조합/분리기  (0) 2014.01.24
z-order 취득  (0) 2014.01.07
web  (0) 2013.12.30
EUC-KR Decode 하는 법  (0) 2013.12.28