【问题标题】:swprintf fails with unicode characters in xcode, but works in visual studioswprintf 在 xcode 中使用 unicode 字符失败,但在 Visual Studio 中有效
【发布时间】:2011-02-03 10:39:50
【问题描述】:

在尝试将一些现有代码转换为支持 unicode 字符时,出现了这个问题。如果我尝试将 unicode 字符(在这种情况下使用欧元符号)传递给任何 *wprintf 函数,它将失败,但似乎只在 xcode 中。相同的代码在 Visual Studio 中运行良好,我什至可以让朋友在 linux 上使用 gcc 成功测试它。这是有问题的代码:

wchar_t _teststring[10] = L"";
int _iRetVal = swprintf(_teststring, 10, L"A¥€");

wprintf(L"return: %d\n", _iRetVal);

// print values stored in string to check if anything got corrupted
for (int i=0; i<wcslen(_teststring); ++i) {
    wprintf(L"%d: (%d)\n", i, _teststring[i]);
}

在 xcode 中,对 swprintf 的调用将返回 -1,而在 Visual Studio 中,它将成功并继续为 3 个字符(65、165、8364)中的每一个打印出正确的值。

我已经在谷歌上搜索了很长时间并且很努力地寻找解决方案,其中出现了多次的建议是使用如下调用:

setlocale(LC_CTYPE, "UTF-8");

我已经尝试了使用此函数的各种参数组合但没有成功,经过进一步调查,如果我尝试将语言环境设置为默认“C”以外的任何值,它似乎返回 null。

我不知道我还能尝试什么来解决这个问题,而且它在其他编译器/平台上也能工作的事实让这一切变得更加令人沮丧。任何帮助将不胜感激!

编辑: 只是想我会补充一点,当 swprintf 调用失败时,它会设置一个错误代码(92),定义为:

#define EILSEQ      92      /* Illegal byte sequence */

【问题讨论】:

  • 将源代码保留为 7 位 ascii,看看是否有帮助。例如在字符串中写入"\u03b2"
  • 不高兴,仍然以同样的方式失败。我认为用 unicode 字符创建字符串没有任何问题,如果我只是用“A¥€”初始化字符串并读取它们都是正确的值,它只会在通过格式化打印函数时中断。跨度>

标签: c++ c xcode gcc unicode


【解决方案1】:

如果您从环境中获取语言环境,它应该可以工作:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main(void) {
  setlocale(LC_ALL, "");
wchar_t _teststring[10] = L"";
int _iRetVal = swprintf(_teststring, 10, L"A¥€");

wprintf(L"return: %d\n", _iRetVal);

// print values stored in string to check if anything got corrupted
for (int i=0; i<wcslen(_teststring); ++i) {
    wprintf(L"%d: (%d)\n", i, _teststring[i]);
}

}

在我的 OS X 10.6 上,这在 GCC 4.2.1 中可以正常工作,但是当使用 CLang 1.6 编译时,它会将 UTF-8 字节放在结果字符串中。

我也可以用 Xcode 编译它(使用标准的 C++ 控制台应用程序模板),但是因为 OS X 上的图形应用程序没有所需的语言环境变量,它在 Xcode 的控制台中不起作用。另一方面,它总是在终端应用程序中工作。

您也可以将语言环境设置为en_US.UTF-8 (setlocale(LC_ALL, "en_US.UTF-8")),但这是不可移植的。根据您的目标,wsprintf 可能会有更好的替代方案。

【讨论】:

  • 我很确定这是我尝试过的组合之一,我要到明天才能在 xcode 中测试,但我会在早上试一试。
  • 所以我试了一下代码,我直接通过终端用 GCC 编译,正如你所说,它按预期工作。然而,它在 xcode 中仍然像以前一样失败。我想现在的问题是 xcode 究竟是如何管理它的?到目前为止,我刚刚完成了几个不同的编译器选项的测试,但没有运气。
  • @Argh:问题在于 Xcode 作为一个图形应用程序,没有所需的语言环境变量。如果您从终端运行由 Xcode 编译的程序,它应该可以工作。
  • 对不起,我可能应该在一开始就提到这一点,但该应用程序实际上是一个 iPhone 游戏。将字符正确打印到控制台中确实是完全可选的。主要用途是创建和操作字符串,然后使用这些值逐个字符地读取这些字符串,以在屏幕上绘制正确的字形。 vswprintf 是我真正需要开始工作的函数,但是所有 *wprintf 函数似乎都以相同的方式失败,所以我使用 swprintf 作为一个简单的例子。
  • @Philipp:我明白你关于控制台与终端的意思,我尝试在 xcode 中创建一个控制台应用程序,它在单独运行时确实有效,而从 xcode 运行时失败。我不确定这将如何应用于 iOS 应用程序。也许设备也限制了可以设置的语言环境,那么我是否注定将所有内容都转换为objective-c字符串?
【解决方案2】:

如果您使用的是 Xcode 4+,请确保您已为包含您的字符串的文件设置了适当的编码。您可以在“文本设置”组下的右侧窗格中找到编码设置。

【讨论】:

    【解决方案3】:

    Microsoft 计划从 VS 2015 开始与其他编译器兼容,但由于遗留代码的问题,最终没有发生,请参阅 link

    幸运的是,您仍然可以通过添加 _CRT_STDIO_ISO_WIDE_SPECIFIERS 预处理器宏在 VS 2015 中启用 ISO C (C99) 标准。建议在编写可移植代码时使用。

    【讨论】:

      【解决方案4】:

      我发现在格式化字符串中使用“%S”(大写)是可行的。

      “%s”用于 8 位字符,“%S”用于 16 位或 32 位字符。

      见:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html

      我正在使用 Qt Creator 4.11,它使用 Clang 10。

      【讨论】:

        猜你喜欢
        • 2014-10-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-31
        • 2016-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多