swprintf 在 xcode 中使用 unicode 字符失败,但在 Visual Studio 中工作

发布于 2024-10-15 19:58:58 字数 970 浏览 1 评论 0原文

在尝试转换一些现有代码以支持 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");

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

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

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

#define EILSEQ      92      /* Illegal byte sequence */

While trying to convert some existing code to support unicode characters this problem popped up. If i try to pass a unicode character (in this case im using the euro symbol) into any of the *wprintf functions it will fail, but seemingly only in xcode. The same code works fine in visual studio and I was even able to get a friend to test it successfully with gcc on linux. Here is the offending code:

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]);
}

In xcode the call to swprintf will return -1, while in visual studio it will succeed and proceed to print out the correct values for each of the 3 chars (65, 165, 8364).

I have googled long and hard for solutions, one suggestion that has appeared a number of times is using a call such as:

setlocale(LC_CTYPE, "UTF-8");

I have tried various combinations of arguments with this function with no success, upon further investigation it appears to be returning null if i try to set the locale to any value other than the default "C".

I'm at a loss as to what else i can try to solve this problem, and the fact it works in other compilers/platforms just makes it all the more frustrating. Any help would be much appreciated!

EDIT:
Just thought i would add that when the swprintf call fails it sets an error code (92) which is defined as:

#define EILSEQ      92      /* Illegal byte sequence */

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

莫言歌 2024-10-22 19:58:58

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

#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 替代方案。

It should work if you fetch the locale from the environment:

#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]);
}

}

On my OS X 10.6, this works as expected with GCC 4.2.1, but when compiled with CLang 1.6, it places the UTF-8 bytes in the result string.

I could also compile this with Xcode (using the standard C++ console application template), but because graphical applications on OS X don't have the required locale environment variables, it doesn't work in Xcode's console. On the other hand, it always works in the Terminal application.

You could also set the locale to en_US.UTF-8 (setlocale(LC_ALL, "en_US.UTF-8")), but that is non-portable. Depending on your goal there may be better alternatives to wsprintf.

记忆消瘦 2024-10-22 19:58:58

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

If you are using Xcode 4+ make sure you have set an appropriate encoding for your files that contain your strings. You can find the encoding settings on a right pane under "Text Settings" group.

书信已泛黄 2024-10-22 19:58:58

微软曾计划从 VS 2015 开始兼容其他编译器,但最终由于遗留代码的问题而从未实现,请参阅 链接

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

Microsoft had a plan to be compatible with other compilers starting from VS 2015 but finally it never happened because of problems with legacy code, see link.

Fortunately you can still enable ISO C (C99) standard in VS 2015 by adding _CRT_STDIO_ISO_WIDE_SPECIFIERS preprocessor macro. It is recommended while writing portable code.

眼泪淡了忧伤 2024-10-22 19:58:58

我发现在格式化字符串中使用“%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。

I found that using "%S" (upper case) in the formatting string works.

"%s" is for 8-bit characters, and "%S" is for 16-bit or 32-bit characters.

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

I'm using Qt Creator 4.11, which uses Clang 10.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文