2017-08-01 7 views
2

vsnprintfを使用してwchar_t*をUTF-8文字でフォーマットしてから、printfを使用してバッファを印刷しようとしています。 CLのV19でWindows 10上で、しかしMSVCでUTF8文字を使用するwchar_t *

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

:私はBASHで所望の出力を得るために、Ubuntuの16にgccのV5.4でコンパイルさ

/* 
    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; 
} 

は、次のコードを考えます。 10.25019(VS 2017)、私はCMDで奇妙な出力が得られます。

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

(コロンBECO前ę MES Tとコロンの後にオゴネクなしe)私は明らかの有無に関わらず効果がありませんVS 2015)、に導入されたCLの新しい/utf-8スイッチを(使用

注意です。そのblog postに基づいて:「:UTF-8 /ソース文字セットを」および「/実行-文字セット:UTF-8」

設定するための同義語である/ UTF-8オプションもあります。

(私のソースファイルが既に明らかに手助けされていませんBOM/utf8'nessと実行-文字セットを持っている)

出力は同じに見えるようにコード/コンパイラスイッチへの変更の最小限の量を何ができますかgccのそれに?

+2

Windowsでは 'printf()'(およびコンソール全体)はUTF-8をサポートしていません。 UTF-16でエンコードされた 'wchar_t'データをUTF-8に変換するには' WideCharToMultiByte() '(または相当するもの)を使うことができますが、それでもコンソールが正しく表示するという保証はありません。実際には、Win32の 'WriteConsoleW()'関数やC++の 'std :: wcout'関数などのUnicodeコンソールAPIを使用して、Unicodeデータをコンソールに書き込む必要があります。 WindowsコンソールにUnicodeデータを出力する方法については、StackOverflowに関する多くの質問があります。あなたの評判は、あなたが尋ねる前にいくつかの研究をすることを知っていたはずのほど高いです。 –

+0

PowerShell IDEを実行してプログラムのディレクトリに移動し、プログラムを実行することもできます。 –

+0

@RemyLebeau、ありがとう。 'WideCharToMultiByte()'と他のUnicodeコンソールAPIに試してみましょう。私はいくつかの調査をしましたが、製品のバージョン管理で迷っていました(たとえばVS2015以降、vsnprintf OOTBなどが含まれています)。もう少し読むでしょう。 :) –

答えて

0

@ RemyLebeauのコメントに基づいて、printf APIのwバリアントを使用してWindows上でmsvcと同じ結果を得るようにコードを修正しました。これはUnixではgccのものと同じです。

さらに、コードページを変更する代わりに、_setmodeFILE翻訳モード)を使用しました。

/* 
    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))と同じ処理を行うには、_setmodestderrも必要です。

関連する問題