我尝试使用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
(冒号前的ę
变为T
,冒号后e
没有ogonek
请注意,我使用了CL的新/utf-8
开关(在VS 2015中引入),显然无论是否有效。基于他们的blog post:
还有一个/ utf-8选项,它是设置“/ source-charset:utf-8”和“/ execution-charset:utf-8”的同义词。
(我的源文件已经有BOM / utf8',执行charset显然没有帮助)
为了使输出看起来与gcc的输出看起来相同,代码/编译器开关的最小更改量是多少?
答案 0 :(得分:0)
基于@RemyLebeau的评论,我修改了代码以使用printf API的w
变体来获得与Windows上的msvc相同的输出,与Unix上的gcc相匹配。
此外,我现在使用_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)
(或perror(format, args)
)执行相同操作,我们还需要_setmode
stderr
。