5

私が持っている質問は非常に単純ですが、これまでのところ解決策を見つけることができませんでした:

libiconv のような余分なライブラリを使用せずに、UTF8 エンコードstringを C++ でエンコードされた latin1に変換するにはどうすればよいですか?string

これまでに見つけたすべての例は、latin1 から UTF8 への変換に関するものですか?

4

3 に答える 3

4
typedef unsigned value_type;

template <typename Iterator>
size_t get_length (Iterator p)
{
    unsigned char c = static_cast<unsigned char> (*p);
    if (c < 0x80) return 1;
    else if (!(c & 0x20)) return 2;
    else if (!(c & 0x10)) return 3;
    else if (!(c & 0x08)) return 4;
    else if (!(c & 0x04)) return 5;
    else return 6;
}

template <typename Iterator>
value_type get_value (Iterator p)
{
    size_t len = get_length (p);

    if (len == 1)
    return *p;

    value_type res = static_cast<unsigned char> (
                                    *p & (0xff >> (len + 1)))
                                     << ((len - 1) * 6);

    for (--len; len; --len)
        res |= (static_cast<unsigned char> (*(++p)) - 0x80) << ((len - 1) * 6);

    return res;
}

この関数は の Unicode コード ポイントを返しますp。を使用して文字列を変換できるようになりました

for (std::string::iterator p = s_utf8.begin(); p != s_utf8.end(); ++p)
{
     value_type value = get_value<std::string::iterator&>(p));
     if (value > 0xff)
         throw "AAAAAH!";
     s_latin1.append(static_cast<char>(value));
}

保証はありません。コードはかなり古いです:)

于 2012-10-12T09:20:13.630 に答える
1

これは、私が目的のために書いたフィルマーの回答のバージョンです。もう少し読みやすく、おそらく少し遅くなります。私は常にchar *. それが誰かを助ける場合に備えて:

int GetUtf8CharacterLength( unsigned char utf8Char )
{
    if ( utf8Char < 0x80 ) return 1;
    else if ( ( utf8Char & 0x20 ) == 0 ) return 2;
    else if ( ( utf8Char & 0x10 ) == 0 ) return 3;
    else if ( ( utf8Char & 0x08 ) == 0 ) return 4;
    else if ( ( utf8Char & 0x04 ) == 0 ) return 5;

    return 6;
}

char Utf8ToLatin1Character( char *s, int *readIndex )
{
    int len = GetUtf8CharacterLength( static_cast<unsigned char>( s[ *readIndex ] ) );
    if ( len == 1 )
    {
        char c = s[ *readIndex ];
        (*readIndex)++;

        return c;
    }

    unsigned int v = ( s[ *readIndex ] & ( 0xff >> ( len + 1 ) ) ) << ( ( len - 1 ) * 6 );
    (*readIndex)++;
    for ( len-- ; len > 0 ; len-- )
    {
        v |= ( static_cast<unsigned char>( s[ *readIndex ] ) - 0x80 ) << ( ( len - 1 ) * 6 );
        (*readIndex)++;
    }

    return ( v > 0xff ) ? 0 : (char)v;
}

// overwrites s in place
char *Utf8ToLatin1String( char *s )
{
    for ( int readIndex = 0, writeIndex = 0 ; ; writeIndex++ )
    {
        if ( s[ readIndex ] == 0 )
        {
            s[ writeIndex ] = 0;
            break;
        }

        char c = Utf8ToLatin1Character( s, &readIndex );
        if ( c == 0 )
        {
            c = '_';
        }

        s[ writeIndex ] = c;
    }

    return s;
}

テストコード:

char s2[ 256 ] = "lif\xc3\xa9 is b\xc3\xa9tt\xc3\xa9r with acc\xc3\xa9nts";
Utf8ToLatin1String( s2 );
于 2013-11-23T04:16:31.647 に答える
-1

latin1(別名ISO-8859-1)は、Unicodeの最初の256コードポイントを定義します。したがって、ではUTF-8、文字が8ビットの場合、latin1同等の文字に正確にマップされます。長さが8ビットを超える場合は、対応するlatin1文字が含まれていないため、「不明な文字」(たとえば、\0?)にマップする必要があります。

于 2012-10-12T09:09:56.200 に答える