我的问题很简单,但我无法到目前为止找到一个解决方案:如何在C/C++中将字符串从UTF8转换为Latin1?
我如何转换utf-8编码string
到latin1的用C编码string
++而不使用任何额外的库像libiconv的?
到目前为止我能找到的每个例子都是针对latin1到UTF8的转换?
我的问题很简单,但我无法到目前为止找到一个解决方案:如何在C/C++中将字符串从UTF8转换为Latin1?
我如何转换utf-8编码string
到latin1的用C编码string
++而不使用任何额外的库像libiconv的?
到目前为止我能找到的每个例子都是针对latin1到UTF8的转换?
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;
}
该函数将返回位于p
的unicode代码点。现在,您可以转换为使用
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));
}
不能保证一个字符串,该代码是很老:)
latin1
(又名ISO-8859-1
)定义了Unicode的前256个编码点。因此,在UTF-8
中,如果您的字符是8位,那么它将精确映射到latin1
等价物。如果长度超过8位,那么在latin1
内没有通讯者,您应该将其映射到某个“未知字符”(例如,\0
或?)。
这是不正确的。它只适用于* 7 *位。 – filmor
真的吗?该死......在这种情况下,我猜测OP可以使用这个,然后手动映射剩下的128个点。 – Xophmeister
从UTF-16到latin1的转换只是简单地删除每一个零,但是从UTF-8到latin1的转换有点复杂。 – Dialecticus
这里是filmor的答案,我写我的目的的一个版本。更可读,可能会慢一点。我不需要模板的东西,因为我总是处理char *
,在我的情况下,我想用_替换非Latin1字符。万一它可以帮助别人:
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);
UTF8可以代表65536个点; latin1(ISO-8859-1)只能表示256.你想如何处理所有无法转换的字符? – simonc
你可以转换成C这个http://www.jamesmurty.com/2011/12/30/python-code-utf8-to-latin1/(注意不是所有的符号都可以转换) –
@DavidRF条件“不使用任何额外的库“意味着不使用现成的函数,如在给定代码的最后一行,'utf8_text.encode('ISO-8859-1','替换')' – Dialecticus