2012년 11월 29일 목요일

C#에서 유니코드를 이용한 한글 자모 분리와 결합

 .NET은 기본적으로 UTF-16의 2바이트 유니코드를 사용한다고 보면된다.

완성형 한글의 Unicode 범위는 AC00에서부터 D7AF(정확히는 D79F) 범위에 걸쳐 매핑 되어 있다.  한글 자모의 경우 Unicode 범위는 1100에서부터 11FF 범위에 걸쳐 있다.

   유니코드의 자모값의 코드표
    http://www.unicode.org/charts/PDF/U1100.pdf
   한글 완성형 코드표
    http://www.unicode.org/charts/PDF/UAC00.pdf


# 한글 처리를 위한 기초 함수
한글은 한글자가 초성, 중성, 종성의 기본 자모로 이루어지는 형태의 문자이다.
한글은 24자의 자음과 모음의 조합으로 만들어진다.

    자음 : ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎ
    모음 : ㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣ

 아래 예제는 완성형 유니코드를 이용하여 자음과 모음을 분리, 결합하는 함수이다.
 유니코드 표를 보면 한글이 사전순으로 정리되어 있다.
 그래서 초성 자음과 종성 자음의 거리 계산하여 각 자음과 모음을 조합할 수 있다.

--------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfDynamicControl
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

        }
        // 초성, 중성, 종성 테이블.
        private static string m초성Tbl = "ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ";
        private static string m중성Tbl = "ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ";
        private static string m종성Tbl = " ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ";
        private static ushort mUniCode한글Base = 0xAC00;
        private static ushort mUniCode한글Last = 0xD79F;
        private static string m초성;
        private static string m중성;
        private static string m종성;

        public static string 자소합치기(string s초성, string s중성, string s종성)        {
            int i초성위치, i중성위치, i종성위치;
            int iUniCode;

            i초성위치 = m초성Tbl.IndexOf(s초성);   // 초성 위치
            i중성위치 = m중성Tbl.IndexOf(s중성);   // 중성 위치
            i종성위치 = m종성Tbl.IndexOf(s종성);   // 종성 위치

            // 앞서 만들어 낸 계산식
            iUniCode = mUniCode한글Base + (i초성위치 * 21 + i중성위치) * 28 + i종성위치;

            // 코드값을 문자로 변환
            char temp = Convert.ToChar(iUniCode);
            return temp.ToString();
        }


        public void 자소나누기(char c한글자)
        {
            int i초성Idx, i중성Idx, i종성Idx; // 초성,중성,종성의 인덱스
            ushort uTempCode = 0x0000;       // 임시 코드용

            //Char을 16비트 부호없는 정수형 형태로 변환 - Unicode
            uTempCode = Convert.ToUInt16(c한글자);

            // 캐릭터가 한글이 아닐 경우 처리
            if ((uTempCode < mUniCode한글Base) || (uTempCode > mUniCode한글Last))
            {
                m초성 = ""; m중성 = ""; m종성 = "";
            }

            // iUniCode에 한글코드에 대한 유니코드 위치를 담고 이를 이용해 인덱스 계산.
            int iUniCode = uTempCode - mUniCode한글Base;

            i초성Idx = iUniCode / (21 * 28);
            iUniCode = iUniCode % (21 * 28);
            i중성Idx = iUniCode / 28;
            iUniCode = iUniCode % 28;
            i종성Idx = iUniCode;

            m초성 = new string(m초성Tbl[i초성Idx], 1);
            m중성 = new string(m중성Tbl[i중성Idx], 1);
            m종성 = new string(m종성Tbl[i종성Idx], 1);
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            char cWork ;
            cWork = char.Parse("밟");
           
            자소나누기(cWork);
            txtFirst.Text = m초성;
            txtMiddle.Text = m중성;
            txtLast.Text = m종성;

            txtCompose.Text = 자소합치기(m초성, m중성, m종성);
        }
    }
}
--------------------------------------------------------------------------------------------------------

소스를 한글로 써서 가독성이 좀 떨어지려나?

댓글 3개: