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* 的相关文章

  • 我想优化这个短循环

    我想优化这个简单的循环 unsigned int i while j 0 j is an unsigned int with a start value of about N 36 000 000 float sub 0 i 1 unsig
  • WritePrivateProfileString 未在末尾添加属性

    我正在使用以下命令在 ini 文件中写入一些属性WritePrivateProfileString函数并且一切正常 但是当我添加多行文本时 出现了问题 这是代码和输出 WritePrivateProfileString T General
  • 何时在定义上下文或实例化点中发生非依赖名称的重载解析?

    3 4 基本 lookup p1 重载解析 13 3 在名称查找成功后发生 void g long void g int int template
  • IssuerSigningKeyResolver 调用异步方法

    我们使用 IssuerSigningKeyResolver 它是 Microsoft IdentityModel Tokens 的一部分 用于令牌验证并接受非异步委托 我们调用一个异步方法 这将导致阻塞调用 因此想知道使用它的正确方法是什么
  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • 慢速 WPF 文本框

    我正在开发一个简单的串行数据查看器 它将用于观察传输到计算机串行端口之一的数据 我使用 C 和 WPF 编写了一个测试应用程序 它只是将最近读取的行放入文本块中 但是 它会跳过所有其他行 我的理论是 在 WPF 渲染窗口之前 新数据会被放入
  • 在大型数据绑定 ObservableCollection 中添加/删除许多项目,而无需冻结 GUI

    我和我的团队正在开发一个 WPF 应用程序 该应用程序显示多个并发 XamDataChart 控件 由 Infragistics 提供 每个图表都绑定到不同的 ObservableCollection 最多可包含 200 万个点 对于每个图
  • 树结构的序列化/反序列化

    我试图找出保存 序列化 并稍后打开 反序列化 树结构的最佳方法 我的结构由具有不同属性的各种对象类型组成 但每个对象类型都继承自基本抽象 Node 类 每个节点都有唯一的 ID GUID 并且有一个 AddSuperNode Node nd
  • WinForms TreeView - 如何手动“突出显示”节点(就像被单击一样)

    我需要知道如何让以编程方式选择的节点以图形方式处于 选定 状态 就像用户单击它一样 SelectedNode 仅使这一节点在内部被选中 非常感谢 它没有显示为突出显示的原因是由于树视图没有焦点 这是我的测试表单上的按钮单击事件 TreeVi
  • 如何检测机器是否加入域?

    如何检测计算机是否已加入 Active Directory 域 相对于工作组模式 如果没有必要的话 不要用 pinvoke 来愚弄 参考System DirectoryServices 然后调用 System DirectoryServic
  • GCC 和 -Wconversion

    让我们编译以下程序 int main uint16 t data 0 data uint16 t std round 3 14f return 0 with g Wconversion prog cpp 我们会得到warning conve
  • C memcpy 二维数组

    我正在尝试使用将一个二维数组复制到另一个memcpy 我的代码 include
  • 如何使用 Xamarin 应用程序开发自动注销

    我必须在 App xaml cs 上添加功能才能使其正常工作 我在 OnStart 上添加了功能 但现在它会间歇性地一次又一次地将我从应用程序中注销 根据下面的代码 我需要做什么才能让它停止这样做 或者我的代码有问题 这是我最新的代码 na
  • 为什么 `boost::any` 比 `void*` 更好?

    有什么先天优势boost any and boost any cast提供超过使用void and dynamic cast 优点是boost any比类型安全得多void E g int i 5 void p i static cast
  • 模板是如何实例化的?

    这是一个练习 来自C 入门第五版 练习 16 27 对于每个带标签的语句 解释什么 如果有 实例化发生 如果实例化了模板 请解释原因 如果 不 请解释为什么不 第677页 template
  • C# 中 WinForm TextBox 中数字的按键事件

    我想限制用户在文本框中仅输入数字 我在按键事件中添加此代码 private void txtPartID KeyPress object sender KeyPressEventArgs e if e KeyChar gt 0 e KeyC
  • 在源代码和预编译二进制文件之间切换

    我们的应用程序中有大量的库 库是用 C 或 C 编写的 平台 net Framework Windows 64 位 将所有内容编译为源代码需要花费大量时间 我们正在考虑切换到预构建的二进制文件 但我们仍然希望保留返回源代码的可能性 作为版本
  • 从 Asp.Net Core 控制器返回 IAsyncEnumerable 和 NotFound

    返回一个控制器操作的正确签名是什么IAsyncEnumerable
  • 如何将 MouseDown 事件放入样式中?

    这有效 XAML
  • 计算 .NET Core 项目的代码指标?

    我正在研究 ASP NET Core 和 NET Core 项目 对于经典的 C 项目 Visual Studio 2015 具有计算代码指标的功能 对于 NET Core 预览版 2 工具中缺少支持 在工具更加完整之前 有人知道解决方法吗

随机推荐