目的
Visual Studio(Windows)を使ってC++のコンソールアプリケーションを開発する際、
- ソースファイルの文字コード
- 出力するときの文字コード
- プログラム内で扱うデータの文字コード
全てをUTF-8
で扱うための試行錯誤をまとめてみることにします。
2022/01/16 :
記事の公開当初は、ISO C++ 20 標準 (/std:c++20)
(u8string
)を使う予定でした。
しかし、検証した結果、ISO C++ 20 標準 (/std:c++20)
は使わずにISO C++ 17 標準 (/std:c++17)
を使う事にしました。
なぜならば、mbrtoc8
(char -> char8_t
) および c8rtomb
(char8_t -> char
)が実装されていないからです。
環境
Microsoft Visual Studio Community 2022 (3)
Version 17.0.4
VisualStudio.17.Release/17.0.4+32014.148
Microsoft .NET Framework
Version 4.8.04161
インストールされているバージョン:Community
Visual C++ 2022 00482-90000-00000-AA281
Microsoft Visual C++ 2022
Microsoft Visual C++ ウィザード 1.0
Microsoft Visual C++ ウィザード
Microsoft Visual Studio VC パッケージ 1.0
Microsoft Visual Studio VC パッケージ
...
Windows Terminal
バージョン: 1.11.3471.0
エディション Windows 11 Pro
バージョン 21H2
インストール日 2021/10/24 日
OS ビルド 22000.376
エクスペリエンス Windows 機能エクスペリエンス パック 1000.22000.376.0
システムの種類 64 ビット オペレーティング システム、x64 ベース プロセッサ
WindowsのコンソールのコードページをUTF-8にする
設定->時刻と言語->言語と地域->管理用の言語設定->システムロケールの変更->ベータ: ワールドワイド言語サポートで Unicode UTF-8を使用
にチェックを入れます。
こうする事でコンソールのデフォルトコードページがUTF-8
になるようです。
もしくは、main関数の先頭あたりに以下のコードを記述すれば、出力コンソールのコードページがUTF-8
になります。
そして、setvbuf()
でstdout
にバッファを設定します。
文字列がUTF-8
の場合は、バッファを設定しないと正常に出力されない事があるらしいです。
また、バッファを設定するとprintf_s()
の後などでfflush(stdout)
を用いてバッファをフラッシュする必要が出てくることがあります。
#include <Windows.h>
#include <stdio.h>
int main() {
SetConsoleOutputCP(CP_UTF8);
setvbuf(stdout, nullptr, _IOFBF, 1024);
return 0;
}
.editorconfig
を用意する
.editorconfig
を使うとソリューション毎に文字コードを制御できます。
ほぼ全てのソリューションに対して設定したい場合は、Visual Studioのデフォルト設定の場合は、C:\Users\<UserName>\source\repos
に.editorconfig
を作成します。
その内容は、以下のようにします。
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2
```
# Visual Studioのテキストエディターの設定
ツール -> オプション -> テキストエディター -> 全般 -> `シグネチャなしの UTF-8エンコードを自動検出`をチェック
これでソースファイルが`UTF-8`でも扱えるようになります。
# Visual Studioのプロジェクトテンプレートを作成する
Visual Studioで`新しいプロジェクトの作成`を実行し、`空のプロジェクト`を作成します。
1. デバッグ-> <SolutionName>のデバッグプロパティを開く
2. 構成 -> `全ての構成`に変更する
3. **必要に応じて** 構成プロパティ-> 全般 -> C++ 言語標準 -> `ISO C++ 17 標準 (/std:c++17)`に変更する
4. 構成プロパティ-> 詳細 -> 文字セット -> `Unicode 文字セットを使用する`に変更する
5. 構成プロパティ-> リンカー -> コマンド ライン -> 追加のオプションに`/utf-8`を追加する
デフォルトのソースファイルやヘッダーファイルが要らない場合は、このままプロジェクトテンプレートを作成します。
この記事では、`UTF-8`が有効になっているか確認の意味を込めて以下のファイルをプロジェクトに追加してからテンプレートを作成することにします。
1. ソリューション エクスプローラー -> ソースファイルを右クリック
2. 追加 -> 新しい項目 -> C++ ファイル
```cpp:main.cpp
#include <Windows.h>
#include <vector>
#include <string>
int main()
{
std::string u8str = u8"尾も白い猫";
std::string str = "尾も黒い猫";
printf_s("%d\n", GetConsoleOutputCP());
printf_s("start\n");
printf_s(u8"動物: %s\n", u8str.data());
printf_s("動物: %s\n", str.data());
printf_s("end\n");
return 0;
}
```
最後にプロジェクトテンプレートを保存します。
- プロジェクト-> テンプレートのエクスポート
# 動作確認
作成したプロジェクトテンプレートを用いて新しいプロジェクトを作成すれば、ソースファイルと出力と扱うデータ全て`UTF-8`になっているかと思います。
標準ライブラリだけで`UTF-8`を楽に扱えるようになってもらいたいものです。