如何在 Visual C++ 2008 中创建 UTF-8 字符串文字

2024-03-22

在 VC++ 2003 中,我可以将源文件保存为 UTF-8,并按原样使用所有字符串。换句话说,以下代码将按原样将字符串打印到控制台。如果源文件保存为 UTF-8,则输出将为 UTF-8。

printf("Chinese (Traditional)");
printf("中国語 (繁体)");
printf("중국어 (번체)");
printf("Chinês (Tradicional)");

我已将文件保存为带有 UTF-8 BOM 的 UTF-8 格式。然而使用 VC2008 编译会导致:

warning C4566: character represented by universal-character-name '\uC911' 
cannot be represented in the current code page (932)
warning C4566: character represented by universal-character-name '\uAD6D' 
cannot be represented in the current code page (932)
etc.

导致这些警告的字符已损坏。适合区域设置的编码(在本例中为 932 = 日语)将转换为区域设置编码,即 Shift-JIS。

我找不到让 VC++ 2008 为我编译这个的方法。请注意,我在源文件中使用什么区域设置并不重要。似乎没有一个语言环境显示“我知道我在做什么,所以不要 f$%##ng 更改我的字符串文字”。特别是,无用的 UTF-8 伪语言环境不起作用。

#pragma setlocale(".65001") 
=> error C2175: '.65001' : invalid locale

“C”也没有:

#pragma setlocale("C") 
=> see warnings above (in particular locale is still 932)

VC2008 似乎强制所有字符进入指定(或默认)区域设置,并且该区域设置不能是 UTF-8。我不想更改文件以使用“\xbf\x11...”之类的转义字符串,因为相同的源是使用 gcc 编译的,它可以非常愉快地处理 UTF-8 文件。

有没有什么方法可以指定源文件的编译应保持字符串文字不变?

换句话说,在编译源文件时,我可以使用什么编译标志来指定与 VC2003 的向后兼容性。即不要更改字符串文字,按原样逐字节使用它们。

Update

感谢您的建议,但我想避免使用 wchar。由于此应用程序专门处理 UTF-8 中的字符串,因此使用 wchar 需要我将所有字符串转换回 UTF-8,这应该是不必要的。所有输入、输出和内部处理均采用 UTF-8。这是一个简单的应用程序,在 Linux 上以及使用 VC2003 编译时可以正常工作。我希望能够使用 VC2008 编译相同的应用程序并使其工作。

为此,我需要 VC2008 不要尝试将其转换为我的本地计算机的区域设置(日语,932)。我希望 VC2008 能够向后兼容 VC2003。我想要一个区域设置或编译器设置,表明字符串按原样使用,本质上是作为不透明的 char 数组,或作为 UTF-8。看起来我可能会被 VC2003 和 gcc 困住,但 VC2008 在这种情况下试图变得太聪明。


Update:

我决定没有保证的方法可以做到这一点。我下面介绍的解决方案适用于英文版 VC2003,但在使用日文版 VC2003(或者可能是日文操作系统)编译时会失败。无论如何,不​​能依赖它来工作。请注意,即使将所有内容声明为 L"" 字符串也不起作用(并且在 gcc 中很痛苦,如下所述)。

相反,我相信您只需要硬着头皮将所有文本移动到数据文件中并从那里加载它。我现在通过以下方式存储和访问 INI 文件中的文本简单初始化 http://code.jellycan.com/simpleini/(跨平台 INI 文件库)。至少可以保证它可以工作,因为所有文本都在程序之外。

原来的:

我自己回答这个问题,因为似乎只有埃文明白这个问题。关于什么是 Unicode 以及如何使用 wchar_t 的答案与此问题无关,因为这与国际化无关,也不是对 Unicode 字符编码的误解。我很感谢你尝试提供帮助,如果我不够清楚,我深表歉意。

问题是我有源文件需要在各种平台和编译器下交叉编译。该程序进行 UTF-8 处理。它不关心任何其他编码。我想要 UTF-8 格式的字符串文字,就像目前使用 gcc 和 vc2003 一样。用VC2008怎么做? (即向后兼容的解决方案)。

这是我发现的:

海湾合作委员会(v4.3.2 20081105):

  • 字符串文字按原样使用(原始字符串)
  • 支持UTF-8编码的源文件
  • 源文件不得包含 UTF-8 BOM

vc2003:

  • 字符串文字按原样使用(原始字符串)
  • 支持UTF-8编码的源文件
  • 源文件可能有也可能没有 UTF-8 BOM(没关系)

vc2005+:

  • 字符串文字由编译器处理(无原始字符串)
  • char 字符串文字被重新编码为指定的区域设置
  • 不支持 UTF-8 作为目标区域设置
  • 源文件必须具有 UTF-8 BOM

因此,简单的答案是,对于这个特定目的,VC2005+ 已损坏并且不提供向后兼容的编译路径。将 Unicode 字符串放入已编译程序的唯一方法是通过 UTF-8 + BOM + wchar,这意味着我需要在使用时将所有字符串转换回 UTF-8。

没有任何简单的跨平台方法将 wchar 转换为 UTF-8,例如,wchar 的大小和编码是什么?在 Windows 上,UTF-16。在其他平台上?它有所不同。请参阅重症监护室项目 http://icu-project.org/docs/papers/unicode_wchar_t.html了解一些细节。

最后,我决定避免在除 vc2005+ 之外的所有编译器上使用如下所示的源代码进行转换成本。

#if defined(_MSC_VER) && _MSC_VER > 1310
// Visual C++ 2005 and later require the source files in UTF-8, and all strings 
// to be encoded as wchar_t otherwise the strings will be converted into the 
// local multibyte encoding and cause errors. To use a wchar_t as UTF-8, these 
// strings then need to be convert back to UTF-8. This function is just a rough 
// example of how to do this.
# define utf8(str)  ConvertToUTF8(L##str)
const char * ConvertToUTF8(const wchar_t * pStr) {
    static char szBuf[1024];
    WideCharToMultiByte(CP_UTF8, 0, pStr, -1, szBuf, sizeof(szBuf), NULL, NULL);
    return szBuf;
}
#else
// Visual C++ 2003 and gcc will use the string literals as is, so the files 
// should be saved as UTF-8. gcc requires the files to not have a UTF-8 BOM.
# define utf8(str)  str
#endif

请注意,此代码只是一个简化的示例。生产使用需要以多种方式清理它(线程安全、错误检查、缓冲区大小检查等)。

其用法类似于以下代码。在我对 gcc、vc2003 和 vc2008 的测试中,它可以干净地编译并正常工作:

std::string mText;
mText = utf8("Chinese (Traditional)");
mText = utf8("中国語 (繁体)");
mText = utf8("중국어 (번체)");
mText = utf8("Chinês (Tradicional)");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Visual C++ 2008 中创建 UTF-8 字符串文字 的相关文章

  • 如何在 VC++ CString 中验证有效的整数和浮点数

    有人可以告诉我一种有效的方法来验证 CString 对象中存在的数字是有效整数还是浮点数吗 Use tcstol http msdn microsoft com en us library w4z2wdyc aspx and tcstod
  • 尝试了解使用服务打开对话框

    我已经阅读了有关使用 mvvm 模式打开对话框的讨论 我看过几个使用服务的示例 但我不明白所有部分如何组合在一起 我发布这个问题寻求指导 以了解我应该阅读哪些内容 以更好地理解我所缺少的内容 我将在下面发布我所拥有的内容 它确实有效 但从我
  • Environment.CurrentDirectory 与 System.IO.Directory.GetCurrentDirectory

    我正在编写一个 Net WinForms 并不断在调试和发布配置之间切换 并且有一些文件我需要任一配置才能访问 我想做的是将文件放在 BIN 文件夹中的公共目录中 这样它看起来像这样 MyProject Bin CommonFiles My
  • 转换 const void*

    我有一个函数返回一个const void 我想用它的信息作为char 我可以将它投射为 C 风格的罚款 char variable但是当我尝试使用reinterpret cast like reinterpret cast
  • MVC3中设置下拉列表中的所选项目

    我必须为视图中的下拉列表设置所选项目 但它不起作用 View div class editor label Html LabelFor model gt model Gender div div class editor field Htm
  • 如何将 .txt 文件中的数据转换为 xml? C#

    我在一个文本文件中有数千行数据 我想通过将其转换为更容易搜索的内容来轻松搜索 我希望 XML 或其他类型的大型数据结构 尽管我不确定它是否是最好的对于我的想法 每行的数据如下所示 第 31 册 托马斯 乔治 32 34 154 每本书都不是
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 如何在 C# Designer.cs 代码中使用常量字符串?

    如何在 designer cs 文件中引用常量字符串 一个直接的答案是在我的 cs 文件中创建一个私有字符串变量 然后编辑 Designer cs 文件以使用此变量 而不是对字符串进行硬编码 但设计者不喜欢这样抛出错误 我明白为什么这行不通
  • 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

    我注意到CallContext LogicalSetData LogicalGetData不按照我期望的方式工作 内部设置的值async方法得到恢复即使没有异步或任何类型的线程切换 无论如何 这是一个简单的例子 using System u
  • 不同 C++ 文件中的相同类名

    如果两个 C 文件具有相同名称的类的不同定义 那么当它们被编译和链接时 即使没有警告也会抛出一些东西 例如 a cc class Student public std string foo return A void foo a Stude
  • 什么是空终止字符串?

    它与什么不同标准 字符串 http www cplusplus com reference string string 字符串 实际上只是一个数组chars 空终止字符串是指其中包含空字符的字符串 0 标记字符串的结尾 不一定是数组的结尾
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 在 C 中使用枚举而不是 #defines 作为编译时常量是否合理?

    在 C 工作了一段时间后 我将回到 C 开发领域 我已经意识到 在不必要的时候应该避免使用宏 以便让编译器在编译时为您做更多的工作 因此 对于常量值 在 C 中我将使用静态 const 变量或 C 11 枚举类来实现良好的作用域 在 C 中
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • Oauth2中如何同时撤销RefreshToken和使AccessToken失效

    我正在使用 Owin Oauth2 授权和资源服务器相同 开发单页面应用程序 AngularJS Net MVC Json Rest API 的身份验证流程 我选择了 Bearer Token 路由而不是传统的 cookie session
  • C++ 对象用 new 创建,用 free() 销毁;这有多糟糕?

    我正在修改一个相对较大的 C 程序 不幸的是 并不总是清楚我之前的人使用的是 C 还是 C 语法 这是在一所大学的电气工程系 我们 EE 总是想用 C 来做所有事情 不幸的是 在这种情况下 人们实际上可以逃脱惩罚 但是 如果有人创建一个对象
  • 模板类中的无效数据类型生成编译时错误?

    我正在使用 C 创建一个字符串类 我希望该类仅接受数据类型 char 和 wchar t 并且我希望编译器在编译时使用 error 捕获任何无效数据类型 我不喜欢使用assert 我怎样才能做到这一点 您可以使用静态断言 促进提供一个 ht
  • C++:为什么 numeric_limits 对它不知道的类型起作用?

    我创建了自己的类型 没有任何比较器 也没有专门化std numeric limits 尽管如此 由于某种原因 std numeric limits
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2
  • MySqlConnectionStringBuilder - 使用证书连接

    我正在尝试连接到 Google Cloud Sql 这是一个 MySql 解决方案 我能够使用 MySql Workbench 进行连接 我如何使用 C 连接MySqlConnectionStringBuilder 我找不到提供这三个证书的

随机推荐