MSVC 中带有 UTF8 字符的 wchar_t*

2024-03-10

我正在尝试格式化wchar_t*与 UTF-8 字符一起使用vsnprintf然后使用打印缓冲区printf.

给出以下代码:

/*
  This code is modified version of KB sample:
  https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rtref/vsnprintf.htm

  The usage of `setlocale` is required by my real-world scenario,
  but can be modified if that fixes the issue.
*/

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

#ifdef MSVC
#include <windows.h>
#endif

void vout(char *string, char *fmt, ...)
{
   setlocale(LC_CTYPE, "en_US.UTF-8");
   va_list arg_ptr;

   va_start(arg_ptr, fmt);
   vsnprintf(string, 100, fmt, arg_ptr);
   va_end(arg_ptr);
}

int main(void)
{
   setlocale(LC_ALL, "");
#ifdef MSVC
   SetConsoleOutputCP(65001); // with or without; no dice
#endif

   char string[100];

   wchar_t arr[] = { 0x0119 };
   vout(string, "%ls", arr);
   printf("This string should have 'ę' (e with ogonek / tail) after colon:  %s\n", string);
   return 0;
}

我在 Ubuntu 16 上使用 gcc v5.4 进行编译,以在 BASH 中获得所需的输出:

gcc test.c -o test_vsn
./test_vsn
This string should have 'ę' (e with ogonek / tail) after colon:  ę

然而,在带有 CL v19.10.25019 (VS 2017) 的 Windows 10 上,我在 CMD 中得到奇怪的输出:

cl test.c /Fetest_vsn /utf-8
.\test_vsn
This string should have 'T' (e with ogonek / tail) after colon:  e

(the ę在冒号变成之前T冒号之后是e没有奥贡内克)

注意我用的是CL的new/utf-8switch(VS 2015中引入),显然无论有没有效果都没有。基于他们的博客文章 https://blogs.msdn.microsoft.com/vcblog/2016/02/22/new-options-for-managing-character-sets-in-the-microsoft-cc-compiler/:

还有一个 /utf-8 选项,它是设置“/source-charset:utf-8”和“/execution-charset:utf-8”的同义词。

(我的源文件已经有 BOM / utf8'ness 和执行字符集显然没有帮助)

为了使输出看起来与 gcc 的输出相同,对代码/编译器开关进行的最小更改量可能是多少?


根据@RemyLebeau的评论,我修改了代码以使用wprintf API 的变体,用于获取与 Windows 上的 msvc 相同的输出,与 Unix 上的 gcc 相匹配。

此外,我现在没有更改代码页,而是使用了_setmode https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode (FILE翻译模式)。

/*
  This code is modified version of KB sample:
  https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rtref/vsnprintf.htm

  The usage of `setlocale` is required by my real-world scenario,
  but can be modified if that fixes the issue.
*/

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

#ifdef _WIN32
#include <io.h> //for _setmode
#include <fcntl.h> //for _O_U16TEXT
#endif

void vout(wchar_t *string, wchar_t *fmt, ...)
{
   setlocale(LC_CTYPE, "en_US.UTF-8");
   va_list arg_ptr;

   va_start(arg_ptr, fmt);
   vswprintf(string, 100, fmt, arg_ptr);
   va_end(arg_ptr);
}

int main(void)
{
   setlocale(LC_ALL, "");
#ifdef _WIN32
   int oldmode = _setmode(_fileno(stdout), _O_U16TEXT);
#endif

   wchar_t string[100];

   wchar_t arr[] = { 0x0119, L'\0' };
   vout(string, L"%ls", arr);
   wprintf(L"This string should have 'ę' (e with ogonek / tail) after colon:  %ls\r\n", string);

#ifdef _WIN32
   _setmode(_fileno(stdout), oldmode);
#endif
   return 0;
}

或者,我们可以使用fwprintf并提供stdout作为第一个参数。做同样的事情fwprintf(stderr,format,args) (or perror(format, args)),我们需要_setmode the stderr以及。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MSVC 中带有 UTF8 字符的 wchar_t* 的相关文章

随机推荐