问题陈述: 我需要将生成的字符串转换为UTF8字符串,这个生成的字符串扩展了ascii字符,我在Linux系统上(2.6.32-358.el6.x86_64)。
POC仍在进行中,所以我只能提供小代码样本 完整的解决方案只能在准备好后发布。
为什么我需要UFT8(我已将扩展的ascii字符存储在必须为UTF8的字符串中)。
我如何处理:
请查看以下示例代码
int main(){
char CharString[] = "Prova";
iconv_t cd;
wchar_t WcharString[255];
size_t size= mbstowcs(WcharString, CharString, strlen(CharString));
wprintf(L"%ls\n", WcharString);
wprintf(L"%s\n", WcharString);
printf("\n%zu\n",size);
}
这里有一个问题:
输出
PROVA ?????
取值
<小时/> 转到第二部分:
现在我将有一个wchar_t字符串,我想将其转换为UTF8字符串
为此,我正在浏览并发现iconv将在这里提供帮助。
问题在这里 这些是我在manual
中找到的方法**iconv_t iconv_open(const char *, const char *);
size_t iconv(iconv_t, char **, size_t *, char **, size_t *);
int iconv_close(iconv_t);**
在进入iconv之前,我是否需要将wchar_t数组转换回char数组?
请就上述问题提供建议。
扩展ascii我正在谈论请在下面标记的快照中看到字母i
答案 0 :(得分:4)
对于你的第一个问题(我将其解释为&#34;为什么所有的输出都不是我所期望的&#34;):
&#39; ?????&#39;来自?在调用mbstowcs(WcharString, CharString, strlen(CharString))
中,最后一个参数(strlen(CharString)
)是输出缓冲区的长度,而不是输入字符串的长度。 mbstowcs
写入的宽字符数不会超过,包括NUL终结符。由于转换需要6个宽字符,包括终结符,并且您只允许它写入5个宽字符,因此生成的宽字符串不会终止NUL,并且当您尝试将其打印出来时,最终会在结束后打印垃圾。转换后的字符串。因此?????
。您应该使用wchar_t
中的输出缓冲区的大小(在本例中为255)。
为什么第二个wprintf
只打印一个字符?当您使用宽字符串参数调用wprintf
时,必须使用{{1}格式代码(或者更确切地说,%ls
转换需要使用%s
长度修饰符进行限定)。如果您使用l
而不使用%s
,则l
会将字符串解释为wprintf
,并且会在输出时将每个字符转换为char*
它。但是,由于参数实际上是一个宽字符串,因此字符串中的第一个wchar_t
是wchar_t
,这是某个整数大小的数字L"p"
。这意味着0x70
的第二个字节(从结尾算起,因为你有一个小端架构)是0,所以如果你将字符串视为字符的字符串 ,它将在wchar_t
之后立即终止。所以只打印一个字符。
为什么最后一次p
打印没有?在C中,输出流可以是宽流或者字节流,但是在打开流时没有指定。 (并且,无论如何,标准输出已经为您打开。)这称为流的方向。新打开的流是未定向的,当您第一次输出到流时,方向是固定的。如果第一个输出呼叫是广泛呼叫,如printf
,则流是一个宽流;否则,它是一个字节流。设置后,方向是固定的,您不能使用错误方向的输出调用。因此wprintf
是非法的,除了引发错误之外什么都不做。
现在,让我们继续讨论第二个问题:我该怎么办?
首先,您需要清楚输入的格式以及输出方式。在Linux上,您根本不可能想要使用printf
。输入字符串最可能的情况是它已经是UTF-8,或者它是某些ISO-8859-x编码。输出的最可能情况是相同的:要么是UTF-8,要么是一些ISO-8859-x编码。
不幸的是,您的程序无法知道控制台所期望的编码。输出甚至可能不会进入控制台。同样,您的程序实际上无法知道输入字符串中使用了哪种ISO-8859-x编码。 (如果它是字符串文字,则在调用编译器时可能会指定编码,但没有提供信息的标准方法。)
如果由于非ascii字符未正确显示而无法查看输出,则应首先确保控制台配置为使用与程序输出相同的编码。如果程序将UTF-8发送到显示ISO-8859-15的控制台,则文本将无法正常显示。理论上,您的语言环境设置包括控制台使用的编码,但如果您使用的是远程控制台(例如,通过Windows计算机中的PuTTY),则控制台不是Linux环境的一部分,并且默认语言环境可能不正确。最简单的解决方法是正确配置控制台,但也可以更改Linux区域设置。
您从字节字符串中使用wchar_t
这一事实表明您认为原始字符串是UTF-8。所以问题似乎不太可能是你需要将它转换为到 UTF-8。
您当然可以使用mbstowcs
将字符串从一种编码转换为另一种编码;你不需要经过iconv
这样做。但您确实需要知道实际的输入编码和所需的输出编码。
答案 1 :(得分:1)
对utf8使用iconv不是一个好主意。只需自己实现utf8的定义。从描述https://en.wikipedia.org/wiki/UTF-8中可以很容易地在C中完成。 你甚至不需要wchar_t,只需使用uint32_t作为你的角色。 如果你自己实现,你将学到很多东西,你的程序将因不使用mb或iconv函数而获得速度。