- printf(),wprintf()と変換指定子%sと%Sの使いどころ
Visual StudioでC言語、あるいはC++のプロジェクトを作成した時、プロジェクトのプロパティで文字セットを選択することができます。デフォルトでは、『Unicode文字セットを使用する』となっています。
Unicode文字セットを使用するメリットとしては、海外ロケールのPCでも、日本語を表示できたり、英語だけでなく、中国語やハングル文字なども表示可能となる点が挙げられるでしょう。または、環境依存文字(サロゲートペア)といった特殊文字が使える点も見逃せません。自分の作ったソフトウェアが海の向こう側でも正しく動作するようにし、また、日本国内の特殊な地名に対しても配慮したいならば、Unicode文字セットの一択なのだろうと思います。
本投稿では、Unicodeを扱う際のprintf文についてのTipsをまとめます。実行環境は下表の通りです。
開発環境 | Microsoft Visual Studio Community 2019 Version 16.11.7 |
OS | Windows 10 バージョン21H1 |
文字列の表示
printf()で文字列を表示させる場合、ほとんどの場合、文字列配列のポインタを”%s”で変換します。しかし、ワイドキャラクタ(wchar_t)の文字列(UTF-16)を表示する場合、正しく表示するためには、2通りの方法があります。
- printf() + “%s” + char型配列ポインタ
- wrpintf() + L”%s” + wchar_t型配列ポインタ
今回は、使ったことがなかった”%S”(ラージエス)を使った方法になります。
下記サンプルです。wchar_t型のstr1の中に、環境依存文字『髙橋』を含めています。
#include <stdio.h>
#include <locale.h>
int main()
{
wchar_t str1[128] = { L"ワイド文字列 髙橋" }; // 髙が環境依存文字
char str2[128] = { "マルチバイト文字列" }; // マルチバイト文字列
setlocale(LC_CTYPE, ""); // ロケール設定
wprintf(L"%s\n", str1); // 1)ワイド文字列を表示する
printf("%s\n", str2); // 2)マルチバイト文字列を表示する
printf("%S\n", str1); // 3)printfではワイド文字列は通常表示できないが…
}
ビルド後、実行した結果が下記となります。
1行目のワイド文字列表示、2行目のマルチバイト文字列表示は問題ありません。3行目がきちんと表示できています。printf()の変換指定が”%s”ではなく、”%S”(ラージエス)とすると、printf()でもワイド文字列表示できるのです。
wprintf() + マルチバイト文字列
前項で、printf() + “%S”(ラージエス)で、ワイド文字列が表示できることが確認できました。逆に、wprintf() + “%S”(ラージエス)とするとどうなるでしょうか。
#include <stdio.h>
#include <locale.h>
int main()
{
wchar_t str1[128] = { L"ワイド文字列 髙橋" }; // 髙が環境依存文字
char str2[128] = { "マルチバイト文字列" }; // マルチバイト文字列
setlocale(LC_CTYPE, ""); // ロケール設定
wprintf(L"%s\n", str1); // 1)ワイド文字列を表示する
printf("%s\n", str2); // 2)マルチバイト文字列を表示する
printf("%S\n", str1); // 3)printfではワイド文字列は通常表示できないが…
wprintf(L"%s\n", str2); // 4)wprintfでマルチバイト文字列表示 失敗
wprintf(L"%S\n", str2); // 5)wprintfでマルチバイト文字列表示 成功
}
結果は下記の通りです。
16行目は結果の5行目と対応し、成功しています。15行目は、文字化けしています。まとめると、下記の仕様ということになります。
【仕様】 %s :printf()/wrpintf()関数仕様に合わせて文字列を表示する。 printf()ならchar型文字列ポインタ、wprintf()ならwchar_t型文字列ポインタを指定する。 %S :printf()ならwchar_t型文字列ポインタ、wprintf()ならchar型文字列ポインタを表示する。
使いどころ
マルチバイト文字セットで作られたクライアントが、Unicode文字セット(UTF-16)のサーバーから文字列をとる時、クライアント側でデバッグ的に文字列を表示する…時などは使えるでしょう。しかし、かなりレアな状況ですね。。何か思いついたら追記します。
参考リンク
MSDNにも記載があります。
コメント