Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 Q&A
Delphi Programming Q&A
[16113] Re:Re:Re: 길게도 짰네요. C++17 테크닉으로 구현하면
질문 [] 1002 읽음    2020-05-26 08:40
안녕하세요.
올려주신 코드 감사합니다.


유용하게 써먹을 수 있을거 같아서 vc2019로 컴파일해서 테스트해봤는데요.
컴파일 잘되고, 실행도 잘되더군요.

#include <locale>
int main()
{
  setlocale(LC_ALL, "");

  wstring w = ConvEng2Kor(L"R 國 Ekdzhd 대한alsrnr");
  wcout << w << endl;
  wcout << ConvEng2Kor(L"Rk 國 Ekdzhd 대한alsrnr vkdlxld") << endl;
}

그런데 첫번째 문장은 잘 되는데요
ConvEng2Kor(L"R 國 Ekdzhd 대한alsrnr"); ---> "ㄲ 國 땅콩 대한민국"


이어서 호출된 두번째? 문장은 변환이 안되네요.
ConvEng2Kor(L"Rk 國 Ekdzhd 대한alsrnr vkdlxld") ---> "Rk 國 Ekdzhd 대한alsrnr vkdlxld"

빌더님. 어디를 고쳐야 하는지 알려주시면 고맙겠습니다.



빌더(TWx) 님이 쓰신 글 :
:  님이 쓰신 글 :
: : 첫눈 님이 쓰신 글 :
: : : https://anal.tistory.com/entry/Delphi에서-한글관련-작업의-사용방법
: : :
: : : 위 링크에 있는 소스코드입니다.
: : :
: : :
: : : const
: : : 
: : :    ChoSungTbl  : String = 'ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ';
: : :    JungSungTbl : String = 'ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ';
: : :    JongSungTbl : String = '  ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ';
: : : 
: : :    EngChosung  : String = 'r R s e E f a q Q t T d w W c z x v g ';
: : :    EngJungsung : String = 'k o i O j p u P h hkhohly n njnpnlb m mll ';
: : :    EngJongsung : String = '  r R rts swsge f frfafqftfxfvfga q qtt T d w c z x v g ';
: : : 
: : :    UniCodeHangeulBase = $AC00;
: : :    UniCodeHangeulLast = $D79F;
: : : 
: : : 
: : :    //한글관련
: : :    function  ConvEngToHan(src:String):String;
: : :    function  CutFirstHangul(src:String):String;
: : :    function  DecodingEngToHan(src:String):String;
: : :    function  DivChoJungJong(src:String):String;
: : :    function  CharKeyCheck(c : char):boolean;
: : :    function  MoumCheck(c : char):boolean;
: : :    function  HanDiv(const Han: PChar; Han3: PChar): Boolean;
: : :    function  HanDivPas(const Src: String;Check:integer): String;
: : :    Function  GetHanType(const Src: string): Boolean;
: : : 
: : : 
: : : ////////////////////////////////////////////////////////////////////////////////
: : : function MoumCheck(c : char):boolean;
: : : Begin
: : :     Result := c in ['k','o','i','O','j','p','u','P','h','y','n','b','m','l'];
: : : end;
: : : 
: : : function MarkCheck(c : char):boolean;
: : : Begin
: : :     Result := c in ['@','#','$','%','^','&','*','(',')','_','-',' ','+','=','{','}','[',']','|','\','<','>','.',',','/','?',':',';','"',''''];
: : : end;
: : : 
: : : function CharKeyCheck(c : char):boolean;
: : : Begin
: : :     Result := c in ['A'..'Z','a'..'z'];
: : : end;
: : : 
: : : function DivChoJungJong(src:String):String;
: : : var  i, j, l : integer;
: : :     Tmp, Res  : String;
: : : Begin
: : :     l := Length(src);
: : :     If (l < 2) or (not CharKeyCheck(src[1])) Then Begin
: : :        Result := Src[1];
: : :        Exit;
: : :     end;
: : :     Tmp := src + '     ';
: : :     {초성}
: : :     i := Pos(Copy(Tmp,1,1),EngChosung);
: : :     If i > 0 Then Begin
: : :        res := Copy(tmp,1,1) + ' ';
: : :        j := 2;
: : :     End Else Begin
: : :        Result := Tmp[1];
: : :        Exit;
: : :     End;
: : :     {중성}
: : :     If (not CharKeyCheck(tmp[j])) or (not MoumCheck(tmp[j]))Then Begin
: : :        Result := Res;
: : :        Exit;
: : :     End Else Begin
: : :        i := pos(Copy(tmp,j,2),EngJungsung);
: : :        If i > 0 Then Begin
: : :           res := res + Copy(tmp,j,2);
: : :           j := j + 2;
: : :        End Else Begin
: : :           res := res + tmp[j] + ' ';
: : :           j := j + 1;
: : :        End;
: : :     End;
: : :     {종성}
: : :     If (not (tmp[j] in [' ','A'..'Z','a'..'z'])) or (MoumCheck(tmp[j]))Then Begin
: : :        Result := res + '  ';
: : :        exit;
: : :     End Else Begin
: : :        i := pos(Copy(tmp,j,2),EngJongsung);
: : :        If i > 0 Then Begin res := res + Copy(tmp,j,2);
: : :        End Else Begin      res := res + tmp[j] + ' ' ;
: : :        End;
: : :     End;
: : :     Result := res;
: : : end;
: : : 
: : : function DecodingEngToHan(src:String):String;
: : : var  UniCode                             : Integer;
: : :     ChoSung   , JungSung   , JongSung   : Integer;
: : :     ChoSungPos, JungSungPos, JongSungPos: Integer;
: : :     Tmp  : String;
: : :     Tmp2 : Array[0..2] of Char;
: : : Begin
: : :     Result := '';
: : :     Tmp    := DivChoJungJong(Src);
: : :     If Length(tmp) = 1 Then Begin
: : :        ChoSungPos  := Pos(Tmp+' ', EngChoSung );
: : :        JungSungPos := Pos(Tmp+' ', EngJungSung);
: : :        JongSungPos := Pos(Tmp+' ', EngJongSung);
: : :        If       ChoSungPos > 0 Then Result := Copy(ChoSungTbl ,ChoSungPos ,2)
: : :        Else If JungSungPos > 0 Then Result := Copy(JungSungTbl,JungSungPos,2)
: : :        Else If JongSungPos > 0 Then Result := Copy(JongSungTbl,JongSungPos,2)
: : :        Else Result := Tmp;
: : :        Exit;
: : :     End Else If Length(Tmp) <> 6 Then Begin
: : :        Result := Tmp;
: : :        Exit;
: : :     End;
: : :     ChoSungPos  := Pos(Copy(tmp, 1, 2), EngChoSung );
: : :     JungSungPos := Pos(Copy(tmp, 3, 2), EngJungSung);
: : :     JongSungPos := Pos(Copy(tmp, 5, 2), EngJongSung);
: : :     //
: : :     If (ChoSungPos And JungSungPos And JongSungPos) = 0 Then Exit;
: : :     ChoSung  := (ChoSungPos  - 1) Div 2;
: : :     JungSung := (JungSungPos - 1) Div 2;
: : :     JongSung := (JongSungPos - 1) Div 2;
: : :     UniCode  := UniCodeHangeulBase +(ChoSung * 21 + JungSung) * 28 + JongSung;
: : :     WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, @UniCode, 1, @tmp2, 2, nil, nil);
: : :     Result   := tmp2[0]+tmp2[1];
: : : end;
: : : 
: : : function CutFirstHangul(src:String):String;
: : : var l : integer;
: : : Begin
: : :     l := Length(src);
: : :     If l < 2 Then Result := src
: : :     Else If (Length(DivChoJungJong(src)) <> 6 ) Then
: : :             Result := src[1]
: : :     Else If (l < 3)  Then Result := src
: : :     Else If (Length(DivChoJungJong(Copy(src,1,2))) = 6 ) And (not CharKeyCheck(src[3])) Then
: : :             Result := Copy(src,1,2)
: : :     Else If (l < 4)  Then Result := src
: : :     Else If (Length(DivChoJungJong(Copy(src,1,2))) = 6 ) And ((not CharKeyCheck(src[3])) or (Length(DivChoJungJong(Copy(src,3,2))) = 6)) Then
: : :             Result := Copy(src,1,2)
: : :     Else If (l < 5)  Then Result := src
: : :     Else If (Length(DivChoJungJong(Copy(src,1,3))) = 6 ) And ((not CharKeyCheck(src[4])) or (Length(DivChoJungJong(Copy(src,4,2))) = 6)) Then
: : :             Result := Copy(src,1,3)
: : :     Else If (l < 6)  Then Result := src
: : :     Else If (Length(DivChoJungJong(Copy(src,1,4))) = 6 ) And ((not CharKeyCheck(src[5])) Or (Length(DivChoJungJong(Copy(src,5,2))) = 6)) Then
: : :             Result := Copy(src,1,4)
: : :     Else    Result := Copy(src,1,5);
: : : end;
: : : 
: : : function ConvEngToHan(src:String):String;
: : : var  s,r,t : String;
: : : Begin
: : :     s := Src;
: : :     r := '';
: : :     If Trim(Src)<>'' Then Begin
: : :        Repeat
: : :           t :=     CutFirstHangul(s)  ;
: : :           r := r + DecodingEngToHan(t);
: : :           Delete(s,1,Length(t));
: : :        Until s = '';
: : :     End;
: : :     Result := r;
: : : end;
: : : 
: : : function HanDiv(const Han: PChar; Han3: PChar): Boolean;
: : : var  UniCode: Word;
: : :     ChoSung, JungSung, JongSung: Integer;
: : : begin
: : :     Result := False;
: : :     MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Han, 2, @UniCode, 1);
: : :     if (UniCode < UniCodeHangeulBase) or
: : :        (UniCode > UniCodeHangeulLast) then Exit;
: : :     UniCode  := UniCode - UniCodeHangeulBase;
: : :     ChoSung  := UniCode div (21 * 28);
: : :     UniCode  := UniCode mod (21 * 28);
: : :     JungSung := UniCode div 28;
: : :     UniCode  := UniCode mod 28;
: : :     JongSung := UniCode;
: : :     StrLCopy(Han3,     Pchar(ChoSungTbl )  + ChoSung  * 2, 2);
: : :     StrLCopy(Han3 + 2, Pchar(JungSungTbl)  + JungSung * 2, 2);
: : :     StrLCopy(Han3 + 4, Pchar(JongSungTbl)  + JongSung * 2, 2);
: : :     Result := True;
: : : end;
: : : 
: : : function HanDivPas(const Src: String;Check:integer): String;
: : : var  Buff: array[0..6] of Char;
: : :     B,C:String ;
: : :     i  :Integer;
: : : begin
: : :     B:='';
: : :     C:='';
: : :     For i:=1 To Length(Src) Do Begin
: : :         B:=Copy(Src,((i-1)*2)+1,2);
: : :         if Length(Trim(B))=2 then begin
: : :            if HanDiv(PChar(B), Buff) then begin
: : :               Buff[6]:=#0;
: : :                    If Check=1 Then C :=C + Copy(String(Buff),1,2)
: : :               Else If Check=2 Then C :=C + Copy(String(Buff),3,2)
: : :               Else If Check=3 Then C :=C + Copy(String(Buff),5,2);
: : :            end;
: : :         end;
: : :     End;
: : :     HanDivPas:=C;
: : : end;
: : : 
: : : Function GetHanType(const Src: string): Boolean;
: : : var  Len, Hi, Lo: Integer;
: : : begin
: : :     Result := False;
: : :     if Length(Src) < 2 then Exit;
: : :     Len := Length(Src);
: : :     Hi  := Ord(Src[Len - 1]);
: : :     Lo  := Ord(Src[Len]);
: : :     //if ($A1 > Lo) or ($FE < Lo) then Exit;
: : :          if ($B0 <= Hi)  and ($C8 >= Hi) then Result := True   //한글
: : :     Else if ($CA <= Hi)  and ($FD >= Hi) then Result := False  //한자
: : :     Else                                      Result := False; //기타
: : : end;
: : : 

: : :
: : : 이 코드를 DelphiXE2에서 사용하려니 에러가 납니다.
: : : 에러메세지는
: : : Incompatible types: 'PAnsiChar' and 'PWideChar'
: : : 이렇게 나오는데요.
: : :
: : : 수정 부탁드립니다.
: : :
: : : 공부가 잛아 죄송합니다.
: : : 공부 열심히 하겠습니다.
: :
: :
: :
: : 답변:
: :
: :
: : 델파이로 구현되어 있는 위의 코드는 권장하고 싶지 않네요.
: :
: : 1.
: : 한글 오토마타 알고리즘이야 뻔한건데, 코드가 너무 장황하게 작성되어 있고.
: :
: : 2.
: : 카피가 너무 빈번하게 일어나므로 런타임 효율성이 매우 떨어지고.
: :
: :
: : C++17 테크닉 이용해서 구현하면...
: :
: :
: : #include < iostream >
: : #include < vector >
: : #include < string >
: : #include < unordered_map >
: : 
: : using namespace std;
: : 
: : const static vector< int > ivc[] = {
: :   { 12593, 12594, 12596, 12599, 12600, 12601, 12609, 12610, 12611, 12613, 12614, 12615, 12616, 12617, 12618, 12619, 12620, 12621, 12622 },
: :   { 12623, 12624,12625,12626,12627,12628,12629,12630,12631,12634,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643},
: :   { 12593,12594,12595,12596, 12597,12598,12599,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12612,12613,12614,12615,12616,12618,12619,12620,12621,12622 } };
: : 
: : const static unordered_map< int, int > map = {
: :   {0x740066, 12605}, {0x780066, 12606}, {0x760066, 12607}, {0x760066, 12608}, {0x740072, 12595}, {0x740071, 12612}, {0x6B0068, 12632},
: :   {0x6F0068, 12633}, {0x6C0068, 12634}, {0x6A006E, 12637}, {0x70006E, 12638}, {0x6C006E, 12639},
: :   {0x72, 12593}, {0x52, 12594}, {0x73, 12596}, {0x65, 12599}, {0x66, 12601}, {0x61, 12609}, {0x71, 12610}, {0x45, 12600},
: :   {0x51, 12611}, {0x74, 12613}, {0x54, 12614}, {0x64, 12615}, {0x77, 12616}, {0x57, 12617}, {0x63, 12618}, {0x7A, 12619},
: :   {0x78, 12620}, {0x76, 12621}, {0x67, 12622}, {0x6B, 12623}, {0x6F, 12624}, {0x4F, 12626}, {0x69, 12625}, {0x6A, 12627},
: :   {0x70, 12628}, {0x50, 12630}, {0x75, 12629}, {0x68, 12631}, {0x79, 12635}, {0x6E, 12636}, {0x62, 12640}, {0x6C, 12643},
: :   {0x6D, 12641}, {0x6C006D, 12642}, {0x770073, 12597}, {0x670073, 12598}, {0x720066, 12602}, {0x610066, 12603}, {0x710066, 12604},
: : };
: : 
: : wstring ConvEng2Kor(const wstring&& in)
: : {
: :   if (!in.size()) return L"";
: : 
: :   static auto cnv = [&](size_t i, int n, int& l, bool c1 = false)
: :   {
: :     if (i >= in.size())
: :       return 0;
: : 
: :     static auto map2i = [](const int& _) {
: :       if (auto it = map.find(_); it == map.end()) return 0;
: :       else return it->second;
: :     };
: : 
: :     auto tc = 0;
: :     return ([&](const auto& _) {
: :       _ && !c1 && i + 1 < in.size() ?
: :         (tc = map2i(*(int*)in.data()), l = 2) : 0;
: :       !tc ? (tc = map2i(in[i]), l = 1) : 0;
: :       }(n), [](const auto& v, auto e,int tc = 0) {
: :         if (auto _ = ::find(v.begin(), v.end(), e); _ == v.end()) return -1;
: :         else return ::distance(v.begin(), _);
: :       }(ivc[n], tc) != -1 ? tc : 0);
: :   };
: : 
: :   wstring ret;
: :   for (int i = 0, c1, c2, c3, l1, l2; i < (int)in.size();) {
: :     if (!(c1 = cnv(i, 0, l1))) {
: :       if (!(c2 = cnv(i, 1, l1))) {
: :         ret += in[i++];
: :         continue;
: :       }
: :       ret += c2, i += l1;
: :       continue;
: :     }
: : 
: :     if (cnv(i + 1, 0, l2)) {
: :       if (cnv(i + 2, 1, l2)) {
: :         ret += c1, i += l1;
: :         continue;
: :       }
: : 
: :       if ((c3 = cnv(i, 2, l2), l2 == 2)) {
: :         ret += c3, i += l2;
: :         continue;
: :       }
: :       else {
: :         ret += c1, i += l1;
: :         continue;
: :       }
: :     }
: : 
: :     if ([&ret, c1](const auto _) { return _ ? (ret += c1, 1) : 0; }(!(c2 = cnv(++i, 1, l1)))
: :     ) continue;
: : 
: :     static auto cvt = [](const std::vector< int > & v, int e) {
: :       if (auto _ = ::find(v.begin(), v.end(), e); _ != v.end()) return ::distance(v.begin(), _);
: :       return -1;
: :     };
: : 
: :     static auto cv2 = [&]() { return cvt(ivc[1], c2) * 0x1C; };
: :     static auto cvi = [&]() { return (c1 ? 0xAC00 + cvt(ivc[0], c1) * 0x24C : 0); };
: : 
: :     if (!(c3 = cnv(i += l1, 2, l1))) {
: :       ret += [&](int _) { return (c2 ? _ += cv2(): 0, _); }(cvi());
: :       continue;
: :     }
: : 
: :     if (l1 == 2) {
: :       if (cnv(i + 2, 0, l2)) {
: :         ret += [&](auto _) { return (c2 ? _ += cv2(): 0, c3 ? _ += cvt(ivc[2], c3) : 0, i += l1, _); }(cvi());
: :         continue;
: :       }
: :       ret += [&](auto _) { return (c2 ? _ += cv2(): 0, c3 = cnv(i, 2, l1, true), c3 ? _ += cvt(ivc[2], c3) + 1 : 0, i += l1, _); }(cvi());
: :       continue;
: :     }
: :     else {
: :       if (cnv(i + 1, 1, l2)) {
: :         ret += [&](auto _) { return (c2 ? _ += cv2(): 0, _); }(cvi());
: :         continue;
: :       }
: :       ret += [&](auto _) { return (c2 ? _ += cv2(): 0, c3 ? _ += cvt(ivc[2], c3) + 1 : 0, i += l1, _); }(cvi());
: :       continue;
: :     }
: :   }
: :   return ret;
: : }
: : 
: : 

:
:
: 답변:
:
: int main()
: {
:   setlocale(0, "");
:
:   wstring w = ConvEng2Kor(L"Rk 國 Ekdzhd 대한alsrnr");
:   wcout << w << endl; // 출력: "까 國 땅콩 대한민국"
: }
:
: 위와 같이 C++17 테크닉 이용해서 파스칼 원본 코드보다 절반 가량 코드를 줄일 수 있고...
:
: Range 테크닉 이용하면 코드를 더 줄여서 더 짧게 작성할 수 있으나...
: 엠바 컴파일러는 C++20을 지원하지 않으므로 생략.
:
:
: 여담이지만...
:
: 툴이 완전히 분리되어 C++20 테크닉으로 VCL 런타임 라이브러리를 구현하면
: 델파이로 구현한 것 보다 1/3 수준으로 라이브러리 코드를 확 줄일 수 있을텐데...
:
: 델파이와 C++ 빌더는 서로 완전히 분리되어 제 갈길 가는 게 맞겠으나
: 지금 까지 엠바 행태로 보아서는 의미 없는 기대.
:
: 만들기 쉬운 파스칼 컴파일러에 올인해서 현상을 유지할 수는 있겠으나
: 현재 엠바 기술력으로는 C++은 기대난망...
:
:
:
:
:
:

+ -

관련 글 리스트
16110 한글을 분해하고 조합하는 코드인데 수정 부탁드립니다. 첫눈 848 2020/05/21
16118     Re:한글을 분해하고 조합하는 코드인데 수정 부탁드립니다. 762 2020/06/11
16111     Re: 길게도 짰네요. C++17 테크닉으로 구현하면 754 2020/05/25
16112         Re:Re: 길게도 짰네요. C++17 테크닉으로 구현하면 빌더(TWx) 826 2020/05/25
16113             Re:Re:Re: 길게도 짰네요. C++17 테크닉으로 구현하면 질문 1002 2020/05/26
16114                 Re:Re:Re:Re: 길게도 짰네요. C++17 테크닉으로 구현하면 빌더(TWx) 1249 2020/05/26
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.