2014-05-15 7 views
6

레거시 코드에서 사용하기 위해 UTF-8 string을 ISO-8859-1 char*으로 변환하려고합니다. 이 작업을 수행하는 유일한 방법은 iconv입니다.UTF-8에서 ISO-8859-1로 문자열 변환

나는 완전히 string 기반 C++ 솔루션을 선호하며 그 결과 문자열에 .c_str()을 호출하면됩니다.

어떻게하면됩니까? 가능한 경우 코드 예제. 알고있는 유일한 솔루션 인 경우 iconv을 사용하면 문제가 없습니다.

+0

C++ 11에서 구현했습니다. 올바른 방식으로하는 것이 잘못된 이유는 무엇입니까? –

+0

유일한 방법은 iconv를 사용하는 것이 좋습니다. 상상할 수있는 가장 우아한 C++ 솔루션은 아닙니다. 's.toEncoding ("ISO-8859-1")과 같은 것이 훨씬 더 우아 할 것입니다. 내 요점은, 내가 iconv에서 그것을하고있다하더라도, 그것은'string' 입력으로 라이브러리를 사용하는 방법이 명확하지 않다는 것입니다. –

+0

잘 모르겠지만 도움이 될 수 있습니다. http://www.openldap.org/lists/openldap-devel/200304/msg00123.html – gerbit

답변

6

먼저 UTF-8을 32 비트 유니 코드로 변환합니다.

그런 사람들은 라틴 1 코드 포인트이며, 오류 또는 아마 코드로 교체하는 것이 치료하려면 다른 값에 대한 결정 255

의 범위의 0에있는 값을 유지 포인트 127 (내 fav, ASCII "del") 또는 물음표 또는 뭔가. 표준 라이브러리가 사용될 수 std::codecvt 전공 정의


,

template<> 
codecvt<char32_t, char, mbstate_t> 

§22.4.1.4/3 C++ 11 : 전공 codecvt <char32_t, char, mbstate_t>는 UTF-32으로 변환 사이 “ 및 UTF-8 인코딩 체계 ”

+0

이것은 유니 코드가 ISO-8859- 1로 시작합니다. http://en.wikipedia.org/wiki/Unicode#Origin_and_development P.S.를 참조하십시오. 변환을위한 출발점으로 제안 할 수 있습니다 http://stackoverflow.com/a/148766/5987 –

7

제안을 구현하려면 코드 from another answer을 수정해야합니다. Alf.

std::string UTF8toISO8859_1(const char * in) 
{ 
    std::string out; 
    if (in == NULL) 
     return out; 

    unsigned int codepoint; 
    while (*in != 0) 
    { 
     unsigned char ch = static_cast<unsigned char>(*in); 
     if (ch <= 0x7f) 
      codepoint = ch; 
     else if (ch <= 0xbf) 
      codepoint = (codepoint << 6) | (ch & 0x3f); 
     else if (ch <= 0xdf) 
      codepoint = ch & 0x1f; 
     else if (ch <= 0xef) 
      codepoint = ch & 0x0f; 
     else 
      codepoint = ch & 0x07; 
     ++in; 
     if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff)) 
     { 
      if (codepoint <= 255) 
      { 
       out.append(1, static_cast<char>(codepoint)); 
      } 
      else 
      { 
       // do whatever you want for out-of-bounds characters 
      } 
     } 
    } 
    return out; 
} 

잘못된 UTF-8 입력은 문자를 삭제합니다. 및 iconv 같은 라이브러리에 대한 좋은 일이 정확히 종류 -

+0

사실, UTF-8'string'이 들어 왔습니다.'string'-to-'string' 그거 정말 완벽 할것 같아. –

+0

@ChrisRedford, 그냥 mystr.c_str()로 호출하십시오. 더 유연하기 때문에 'const char *'입력을하는 것이 좋습니다. –

+0

입력이'std :: string'에서 왔기 때문에'const char * in' 대신'const std :: string & in'을 사용하고,'in.c_str (')에 할당 된 로컬'char *)'를 사용하고'* in! = 0' 대신에'in.size()'를 루프 카운터로 사용하십시오. 또는'in.begin()'과'in.end()'이터레이터를 사용하십시오. –

1

ALFS 제안은 잠재적으로 큰 프로젝트 같은 소리

#include <string> 
#include <codecvt> 
#include <algorithm> 
#include <iterator> 
auto i = u8"H€llo Wørld"; 
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8; 
auto wide = utf8.from_bytes(i); 
std::string out; 
out.reserve(wide.length()); 
std::transform(wide.cbegin(), wide.cend(), std::back_inserter(out), 
      [](const wchar_t c) { return (c <= 255) ? c : '?'; }); 
// out now contains "H?llo W\xf8rld"