안녕하세요 "한글" 자음 모음 분리에 관해 질문이 있습니다.!

ozon1000의 이미지

만약에 입력으로 "안녕" 이 들어오면,
char *str 에 "ㅇㅏㄴㄴㅕㅇ" 이렇게 분리를 하고 싶습니다.

구글링을 꽤 해보았는데 좋은 자료가 없어서 애를 먹고 있습니다.
혼자 해결하려 했는데, 도저히 아이디어가 떠오르질 않네요.

한수 가르쳐 주시면 감사히 배우겠습니다.
읽어주셔서 감사합니다.

vagabond20의 이미지

컴퓨터에서 한글은 UTF-8 이나 EUC-KR 로 표시되는데, 이 두 코딩체계의 문제는 한글을 자음, 모음 또는 초성, 중성, 종성으로 분리하는것이 아니라 글자 별로 코드를 정한다는 겁니다. 예를 들어 '안' 은 C54, '녕' 은 B15 ... 이런식으로.

유니코드(UTF-8) 테이블

그렇다면, 원하시는 대로 char *str 에 자음과 모음을 분리해서 저장하려면 우선 유니코드로 들아온 글자를 분리하는 로직이나 테이블을 따로 만들어야 할것 같군요. 다른 좋은 방식을 여기 들어오시는 고수들께서 또 올리실것으로 생각합니다만, 구글링으로 비슷한 주제를 다룬 '알쯔' 라는 분의 PHP 코드 예를 찾아 링크를 남겨 둡니다.

알쯔의 외부기억장치

여의도자바

 의 이미지

일단 문자를 유니코드로 변환하기만 하면 아주 간단한 문제가 됩니다.
모든 한글 음절이 유니코드에 U+AC00(가)부터 U+D7A3(힣)까지 사전순으로 올라가 있기 때문이지요.

초성 19자 : ㄱ,ㄲ,ㄴ,ㄷ,ㄸ,ㄹ,ㅁ,ㅂ,ㅃ,ㅅ,ㅆ,ㅇ,ㅈ,ㅉ,ㅊ,ㅋ,ㅌ,ㅍ,ㅎ
중성 21자 : ㅏ,ㅐ,ㅑ,ㅒ,ㅓ,ㅔ,ㅕ,ㅖ,ㅗ,ㅘ,ㅙ,ㅚ,ㅛ,ㅜ,ㅝ,ㅞ,ㅟ,ㅠ,ㅡ,ㅢ,ㅣ
종성 28자 : (없음),ㄱ,ㄲ,ㄳ,ㄴ,ㄵ,ㄶ,ㄷ,ㄹ,ㄺ,ㄻ,ㄼ,ㄽ,ㄾ,ㄿ,ㅀ,ㅁ,ㅂ,ㅄ,ㅅ,ㅆ,ㅇ,ㅈ,ㅊ,ㅋ,ㅌ,ㅍ,ㅎ

19 * 21 * 28 = 11172자가 빈 자리 하나 없이 순서대로 연속 배치되어 있기 때문에 나눗셈 몇 번이면 분리할 수 있습니다.

진짜 어려운 문제가 뭐냐면, C언어의 멀티바이트 문자열로부터 유니코드를 얻어내는 거지요.
이 부분을 이식성 있게 작성하려면 조금 골치가 아픕니다. 저는 C언어의 여러 부분을 관심 가지고 공부했지만, 로케일이나 문자셋 변환 같은 부분은 손대기 골치 아파서 매번 필요한 만큼만 알아봐서 쓰고 그랬거든요.

귀찮아서 그냥 이렇게만 쓰고 넘어갈까 했는데, 몇 개월 주기로 이런 비슷한 질문을 보고 있기도 하고, 저도 공부삼아 제대로 동작하는 예제 코드 하나 만들어서 제 kldp 발자취에 남겨 놓으면 나중에 써먹을 일이 있지 않을까 싶어서 한번 만들어봤습니다. 참조해보세요.

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
#include <string.h>
#include <stdbool.h>
 
static const char * const initial_array[] = {
    "ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ",
    "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ"
};
static const char * const medial_array[] = {
    "ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ",
    "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ",
    "ㅣ"
};
static const char * const final_array[] = {
      "", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ",
    "ㄻ", "ㄼ", "ㄽ", "ㄾ", "ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ",
    "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ"
};
 
#define count_elements_of(array) (sizeof(array)/sizeof(array[0]))
 
static _Bool DecomposeKoreanSyllable(wchar_t code, wchar_t *initial, wchar_t *medial, wchar_t *final){
    const wchar_t num_initial = count_elements_of(initial_array);
    const wchar_t num_medial = count_elements_of(medial_array);
    const wchar_t num_final = count_elements_of(final_array);
    const wchar_t begin = 0xAC00;
    const wchar_t end = begin + num_initial * num_medial * num_final;
 
    if(begin <= code && code < end){
        code -= begin;
        if(final)*final = code % num_final;
        code /= num_final;
        if(medial)*medial = code % num_medial;
        code /= num_medial;
        if(initial)*initial = code;
        return true;
    }
    else return false;
}
 
int main(void){
    char buf[80];
    setlocale(LC_ALL, "");
    mbtowc(0, 0, 0); // reset
 
    while(fgets(buf, sizeof(buf), stdin)){
        size_t buf_offset = 0, buf_len = strlen(buf);
        wchar_t wc;
        int wc_len;
        while((wc_len = mbtowc(&wc, buf + buf_offset, buf_len - buf_offset)) > 0){
            wchar_t initial, medial, final;
            if(DecomposeKoreanSyllable(wc, &initial, &medial, &final)){
                fputs(initial_array[initial], stdout);
                fputs(medial_array[medial], stdout);
                fputs(final_array[final], stdout);
            }
            buf_offset += wc_len;
        }
    }
    putchar('\n');
    return 0;
}

정상 동작을 확인한 컴파일 및 테스트 환경은 아래와 같습니다.

Ubuntu 14.04.5 LTS
Linux 3.13.0-107-generic #154-Ubuntu SMP Tue Dec 20 09:57:27 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
gcc -std=c99 -pedantic -pedantic-errors

그리고 그걸 명시한다는 건 이식성에 썩 자신이 없다는 뜻이기도 하죠. -_-;;;
특히 setlocale(LC_ALL, "en_US.UTF-8"); 부분이 중요해 보이는데, 이게 정확히 무슨 의미인지, 다른 플랫폼에서는 어떻게 바꿔 주어야 하는지 감이 잘 안잡힙니다. -_-;; 로케일 언제 공부하지...
(2017-02-02 내용 수정: setlocale(LC_ALL, "");로 바꿨습니다.)

그런 면에서, 저보다 더 고수이신 분이 답을 달아 주시기를 저도 기다려야겠습니다.

vagabond20의 이미지

이곳에 자주 기웃거리는 이유중 가장 중요한 이유!
(언젠가 해 보고 싶었는데) 저도 잘 참조 하겠습니다. 고맙습니다.

여의도자바

세벌의 이미지

로캘 아니고 로케일 인가요? locale을 사전에서 찾아 보니 발음이 로케일 보다는 로캘 또는 로칼에 가까운 거 같아서요. 고수 아니어도 답변 달아도 되겠죠?

이중구의 이미지

저도 로케일이라고 읽습니다

ozon1000의 이미지

많은 것을 배우고 가요.
테스트 해보겠습니다.
감사합니다!

bushi의 이미지

utf8 nfd 로 검색해보세요.
nfd(풀어쓰기) 와 자모음 분리는 미묘하게 다르긴합니다만...

[schoi0@SEL-SCHOI0-D2 schoi0]$ echo -en "Hello~안녕" | hexdump -C
00000000  48 65 6c 6c 6f 7e ec 95  88 eb 85 95              |Hello~......|
0000000c
[schoi0@SEL-SCHOI0-D2 schoi0]$ echo -e "\xec\x95\x88"
안
[schoi0@SEL-SCHOI0-D2 schoi0]$ 
[schoi0@SEL-SCHOI0-D2 schoi0]$ echo -en "Hello~안녕" | uconv -f utf8 -t utf8 -x nfd | hexdump -C
00000000  48 65 6c 6c 6f 7e e1 84  8b e1 85 a1 e1 86 ab e1  |Hello~..........|
00000010  84 82 e1 85 a7 e1 86 bc                           |........|
00000018
[schoi0@SEL-SCHOI0-D2 schoi0]$ echo -e "\xe1\x84\x8b"
ᄋ
[schoi0@SEL-SCHOI0-D2 schoi0]$ echo -e "\xe1\x84\x8b\xe1\x85\xa1"
아
[schoi0@SEL-SCHOI0-D2 schoi0]$ echo -e "\xe1\x84\x8b\xe1\x85\xa1\xe1\x86\xab"
안
[schoi0@SEL-SCHOI0-D2 schoi0]$

uconv 는 icu 패키지에 포함된 유틸이며,
apple 이 공개 배포하는 수정된 libiconv 패키지에 utf8-mac 이라는 이름으로 포함된 놈이 utf8 nfd 입니다.


icu 의 unicode normalization 부분만 쓰고 싶다면 GNU libunistring 도 있습니다.

shint의 이미지

완성형 문자코드를 조합형 문자코드로 변환하는 방법 ★★★★★ C / C++ / WIN32 API ★ IME(Input Method Edit) | 디버깅과 테스트
http://blog.daum.net/knightofelf/17717

완성형 한글
http://codepad.org/aeH3xFUC

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

2minchul의 이미지

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.