【C++】UTF-8のファイルをコンパイルすると日本語が文字化ける件の対処法

C++ で日本語を扱いたい場合少し手間がかかります。
例えば次のように、日本を出力するプログラムを作ります。

#include <iostream>
 
int main(){
    std::cout << "日本語" << std::endl;
    return 0;
}

このコードをそのままコンパイルし実行すると、次のように文字化けした状態で表示される場合があります。

PS >  .\sample
譌・譛ャ隱

アプリケーション上は、日本語を扱う機会が多い場合、この文字化けを解決できないと死活問題になります。

さて、
今回は、実行ファイルの文字化けを解決する方法について紹介します。

何故文字化けするのか?

曖昧なところもありますので、実際は違う内容が含まれているかもしれません。
参考程度に読み流してください。

原因は Windows の デフォルト文字エンコードが Shift JIS であるためです。
別の文字コードで出力されたプログラムを実行しようとした時に、文字化けが発生してしまいます。

VSCode でコーディングする時、特に設定していなければ新しく追加するファイルの文字コードは UTF-8 です。
そのまま、g++ でコンパイラすると実行ファイルが UTF-8 で作られてしまいます。

実行環境と実行ファイルの文字コードが異なるため、文字化けが起こっているという事です。

この問題を解決する方法は複数あります。

方法1.プログラムファイルを Shift JIS にする

そもそも最初から、Shift JIS でプログラムを書くという方法です。

(コンパイラの内部的な処理は分かりかねますが) Shift JISのファイルをコンパイルすると出力される実行ファイルも Shift JIS になります。
これであれば実行しても文字化けはしません。

方法2.文字列リテラルを適用する

プログラムの記述単位で文字コードを指定する方法もあります。
それが文字列リテラルです。

learn.microsoft.com

UTF-8 の場合は 日本語文字列の前に u8 を指定する事で文字化けをせずに 表示できます。

#include <iostream>
 
int main(){
    std::cout << u8"日本語" << std::endl;
    return 0;
}

ただ、毎回書かなければいけないので、全文この方法で対応と言うのは現実的ではありませんね。

方法3.UTF-8 を SHIFT JIS に変換してコンパイルする

前述で SHIFT JIS で実行するからUTF-8が文字化けると言いましたが、
正確にはUTF-8 で出力されたファイルを文字化けせずに実行する事は可能なのです。

コマンドプロンプトの文字エンコードを変えるコマンドとして chcp と言うものがあります。

コマンドプロンプトであれば、最初に chcp で「UTF-8( 指定時は 65001 )」を宣言すれば、以降の実行ファイルの文字コードを UTF-8 として扱います。

> chcp 65001
> .\sample
日本語

しかし、PowerShellでは chcp が効きません
別の方法で文字コードを変えるのでしょうが、コマンドライン毎に文字エンコードを変えるのは面倒です。

そのため、(Windows 限定の話にはなりますが) コンパイル時に SHIFT JIS に変えてあげる方法で回避します。
コンパイルコマンドを実行する際に、fexec-charset で SHIFT JIS(指定時は cp932 ) を設定する事で、UTF-8のコードを SHIFT JIS に変換して実行ファイルを作ります。

gcc.gnu.org

PS > g++.exe -fexec-charset=cp932 -g <コンパイル元のC++ファイル> -o <出力するファイル名>

VScode のビルド機能を使う場合

VSCode ではコンパイル用の機能が用意されています。
「ターミナル」->「ビルドタスクの実行」を選択すると、コンパイルコマンドを省略する事ができます。

ビルドタスクの実行内容は .vscode/tasks.json に記載されています。
ここに、先述した-fexec-charsetを追加すれば同じように変換された実行ファイルが出来上がります。

// .vscode/tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe アクティブなファイルのビルド",
            "command": "C:\\msys64\\mingw64\\bin\\g++.exe",
            "args": [
                "-fexec-charset=cp932",      // 出力時の文字コード
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build",
            "detail": "コンパイラ: C:\\msys64\\mingw64\\bin\\g++.exe"
        }
    ]
}

以上です。
もしかしたら他の変換方法もあるかもしれませんが、参考になれば幸いです。

©︎2017-2018 WebSandBag