SO上的大多数answers和questions用于将L
置于任何UTF-8字符串之前。我发现没有解释它是什么,在源代码中,常量是根据我的IDE在winnt.h
中定义的。
这是我如何使用它,而不知道它是什么:
std::wcout<<L"\"Přetečení zásobníku\" is Stack overflow in Czech.";
显然,常量连接不能应用于变量:
void printUTF8(const char* str) {
//Does not make the slightest bit of sense
std::wcout<<L str;
}
那么它是什么以及如何将其添加到动态字符串中?
答案 0 :(得分:1)
L表示C编译器该字符串由“宽字符”组成。在Windows中,这些将是UTF-16 - 您放入字符串的每个字符都是16位,或两个字节,宽:
L"This is a wide string"
相反,UTF-8字符串始终是由字节组成的字符串。 ASCII字符(A-Z 0-9等)按照它们一直以来的方式进行编码 - 在0x00到0x7F(或0到127)的范围内。国际字符(如ř)使用0x80到0xFF范围内的多个字节进行编码 - wikipedia有一个非常好的解释。优点是它可以使用普通的C字符串表示。
"This is an ordinary string, but also a UTF-8 string"
"This is a C cedilla in UTF-8: \xc3\x87"
但是,如果您在实际代码中输入这些国际字符,您的编辑器需要知道您输入的是UTF-8,因此它可以正确编码字符 - 就像上面的C cedilla一样。然后该字符串将正确传递给您的函数。
在您的情况下,您的评论表明您使用的是UTF-16。在这种情况下,还有另外两个问题:
默认情况下,控制台不会正确输出Unicode字符。您需要将字体更改为truidaype字体,如Lucida Console
您还需要将输出模式更改为Unicode UTF-16。你可以这样做:
_setmode(_fileno(stdout),_ O_U16TEXT);
代码示例:
#include <iostream>
#include <io.h>
#include <fcntl.h>
int wmain(int argc, wchar_t* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L"Přetečení zásobníku is Stack overflow in Czech." << std::endl;
}
答案 1 :(得分:1)
L""
是一个WIDE字符串。也就是说,它是一个wchar_t[1]
。 UTF-8字符串不能宽,因为它们是多字节(可变长度)。 VC ++略有错误,并且使得宽字符串可变长度,精确到UTF-16。但通常他们是UTF-32。
多字节字符串的问题在于有许多不同的编码,而UTF-8只是其中之一。 Windows实际上本身不支持UTF-8编码。例如MessageBoxA()
可以使用任何编码但UTF-8。只有一个例外,那就是MultiByteToWideChar(CP_UTF8, ...)
,这就是你需要的。
答案 2 :(得分:0)
重新提出实际问题
“ [
L
前缀]是什么以及如何将其添加到动态字符串中?
这与我写这篇文章时的问题标题非常不同,即“如何在控制台中使用动态字符串与UTF-8一起工作?”
简而言之, UTF-8 是Unicode的编码,其中基本编码单位是8位,通常称为字节(更确切地说,它是一个八位字节),而{{ 1}}前缀形成宽字符或字符串文字,其中编码单位通常为16或32位 - 在Windows中为16位,与原始Unicode一样。
宽字符或字符串文字基于L
类型而非wchar_t
。
在Windows中,宽字符串编码为 UTF-16 。最常见的六万个Unicode字符用单个char
值表示,但有些很少使用中文表意文字等,需要两个连续的wchar_t
值,称为代理对。
在Windows中使用16位编码单元是在1992年左右建立的。我不确定何时采用UTF-16(作为当时UCS-2编码的扩展),它只是稍后。 所以这是在C99要求宽字符集的所有字符都应该用单个 wchar_t
值表示之前建立的。这一要求似乎是一种纯粹的政治策略,确保没有Windows C编译器可以正式符合,这是一种仅适用于Unix-land的通用ISO编程语言标准。不幸的是,由于C ++ 11基于C99,我们现在也在C ++ 11中使用它,确保没有Windows C ++编译器可以完全符合。纯白痴。如果你问我。
勘误 ,重新删除上面的文字:根据Wikipedia’s article about it,单个wchar_t
的字词对于“扩展”中的任何字符都足够了字符集“已经在C90中了。这使得Windows与C和C ++标准之间的不兼容性成为微软的错,而不是C委员会的错。它似乎仍然是政治性的,并且相当愚蠢,但是(开明)与其他人相比应该比我最初维持的还要严重......
使用宽动态字符串的一种方法是使用wchar_t
标题中的std::wstring
。
使用Visual C ++,您可以使用 <string>
函数而不是标准wmain
,这是获取宽命令行参数的简便方法。
main
,尽管还不是普通的MinGW g ++,如g ++ 4.8.something。但是,就Windows API而言,它很容易实现。除非你需要严格的符合标准的代码来提供特殊的主要功能特性,例如能否使用参数声明它,但是嘿,让我们对事物有所了解。
使用Visual C ++ 12.0和g ++ 4.8.2编译好的示例:
wmain
请注意,对于Windows ANSI源,除非使用适当的编译器选项指定源编码,否则不会使用g ++编译。