ASCIIと混在できるマルチバイト文字2-2-1.ASCIIコードこれは、バーソナル・コンピュータの黎明期から存在しており、事実上現代の全てのコンピュータが対応している文字コードです。7ビットで英数字記号を表現します。漢字に比べると形が単純な文字しかないため、ビットマップ・フォントなら、漢字より少ないピクセル数で形状を表現できます。そのため、漢字のほぼ半分の幅で表示されましたので、「半角文字」と呼ばれていました。現在のフォントはプロポーショナル・フォント(文字の幅が文字毎に異なる。本の印刷等でも使われ読みやすいフォント)がほとんどですので、半角/全角と言う表現は適切ではないのですが、当記事のように文字コードの話を書く時には都合の良い表現なので使わせて頂いています。2-2-2.JISコードコンピュータで漢字を取り扱うために決められたのですが、文字コードの切り替え用の特殊文字があるため扱いがたいへん面倒でした。文字列に含まれる文字数を数えたい時、特殊文字があるのでバイト数ではだめです。1文字削除する時、特殊文字を削除するべきかどうかの判定も複雑です。そのため、後述のShift-JISが出現するとバーソナル・コンピュータで使われることはほとんどなくなりました。2-2-3.Shift-JISコードJISコードで定められている全角文字をJISコードの半角文字とエスケープ・シーケンス無しで共存できるようにした頭の良い方法です。半角文字は1バイト、全角文字は2バイトとたいへん分かりやすく、文字数を数えるのも簡単でした。(半角の文字数=バイト数)この特徴により、当時は全角の半分のサイズで半角文字を表示していたため、画面表示の計算も簡単になるのです。Shift-JISは日本語にしか対応していません。中国語を表示したい時や韓国語を表示したい時、文字化けします。同様にドイツ語やロシア語のようにASCIIコードで表現できない文字を持つ国の言語を表示したい時も文字化けします。Windowsコントロール・パネルの地域の設定にある「Unicode対応ではないプログラムの言語」の設定で決まります。その設定と異なる非Unicodeの文字コードで開発されたプログラムを走らせると、文字化けするのです。昔はインターネットでWEBサイトを表示する時、よく文字化けしていたと思います。今も、古い古いサイトを表示すると文字化けすることがあります。それらのWEBサイトでShift-JIS等が使われ、かつ、使っている文字コードがページに記載されてなかった時に、自動判定に失敗した場合に発生します。ASCIIコードが全角文字コードに出現しないようにできればベストでしたが、それにはコードが足りないため、0x40未満のコードが現れないことを保証することが限界で、2バイト目には0x40~0x7eが出現します。Found”不具合が発生することがあります。2-2-4.UTF-16ASCIIコードで表現できない文字を表現したい国は少なくありません。中国や韓国等の「漢字」がある国は当然ですが、ヨーロッパのウムラウト(例えば、Ë等)がある文字や、アラビアの文字やロシアの文字など多数あります。それらをJISコードのように別のコード体系とし、エスケープ・シーケンスで切り替えるのは手間がかかります。そこで、2バイトあれば全ての言語の文字を十分に表現できると考え、2バイトに世界中の文字集合を割り当てようとして発案されたものがUnicodeです。(現在は2バイトでは不足するため、最大4バイトが割り当てられています。)Windowsもこれに対応し、Unicodeの2バイト版UTF-16をWindowsの標準的な文字コードとして採用しました。Unicodeにより文字化けの恐怖から逃れることができるようになったのですが、ASCIIコードで十分な文字列しか必要としないライブラリは相変わらず1バイト文字列しか使えません。2バイト文字列に対応するためだけに、1バイト文字列で対応しているのと同等な機能をもう1セット提供する必要があり、手間ばかりかかる割にメリットが少ないからです。2-2-5.UTF-8そして、UTF-8です。これはASCIIコードとその他の文字コードを共存できることがメリットです。ASCII文字コードに属する文字はそのままASCIIコードで表現されます。それ以外の文字は複数のバイトを用いて、かつ、どのバイトもASCIIコードと被らないコードのみを使用します。その為、多くの日本語文字には3バイト使いますし、レアな文字では最大6バイト使います。従来のASCIIコードとの親和性が高く、共存が容易です。ASCIIコードで定義されている特殊文字は全てのそのままUTF-8でも同じコードですから、それらを処理するプログラムを大きく変更する必要がないのです。(ASCIIで未定義なコードに対してバススルーしているなら、そもそも変更不要な筈です。)日本語文字列の密な加工を行うようなプログラムの場合はUTF-8は決してベストな選択ではないですが、日本語文字列は表示や連結程度であまり高度な処理を行わない多くのプログラムにとって、UTF-8はベストな選択と思います。XMLやJson等文字を取り扱うフォーマットのデフォルトやメジャーなコードがUTF-8になりつつありますので、それらを取り扱う時もあまり苦労しないで済みます。C++(Windows)は、日本語の取り扱い方が異なります。Shift-JISmsvcの場合、ソースの文字コードは通常Shift-JISですが、BOM付きのUTF-8でもビルト可能です。このBOMはソース・コードの先頭にある3バイトの隠し文字で、UTF-8で記録されていることを示します。ファイルの文字コードの変更方法もしも、gcc用のソース・ファイルをShift-JISで記述しているとコンパイル・オプションの指定が必要になるので面倒です。BOM付きのUTF-8はlinuxのgccでも特にオプションを指定することなくコンパイルできますので、ソースを共通化したい場合は、ソースをBOM付きUTF-8にすることがお薦めです。Stduioで文字コードを変更する場合は、変更したいソース・ファイルを開いている状態でFileメニューから次のように操作します。C++(Windows)における悩みgccは既にデフォルトがUTF-8ですので、特に悩ましいことはありません。C++とWindowsは悩ましいです。説明が不足していたので、下記を補いました。分かりやすくなったと思います。C++とWindowsの日本語用文字コードはUTF-16が基本ですが、未だにShift-JISが残っています。コマンド・プロンプトの表示コマンド・プロンプトのデフォルトはShift-JISです。65001と入力することでUTF-8に切り替わりますが、まともには動作しません。C++の文字列定数(”char型文字列”です)通常の文字列定数(”例えばこれ”)はShift-JISコードです。ソース・ファイルをUTF-8で保存しても文字列定数の文字エンコードはShift-JISです。C++はなかなか頑固です。C++11でu8′′文字列”が規定されています。これはu8指定した文字列定数をUTF-8でエンコードするという意味です。2015以降で対応されています。非公開な#pragmaがあります。execution_character_set(“utf-8”)を使うと”char型文字列”のエンコードがUTF-8に変わります。非公開だけあって完全には動作しませんでした。2008は非サポート、2本来\uXXXXのような形式でUnicodeのコードで文字を直接指定できますがこれはダメでした。他にも問題が潜んでいる可能性もあります。すると、このu8′′”文字列対応に伴い解消している可能性もあります。2-4-2.Shift-JISを使う(非推奨)先述したように、他の言語用に設定されたWindowsで動作させると文字化けします。日本語Windowsでのみ動作するプログラムならば、Shift-JISを使うことも選択肢に入ると思います。現代は国際化の時代ですので、国際化に慣れるためにもなるべくShift-JISを使わない方が好ましいです。StudioはデフォルトではUTF-16を用いますので、これをShift-JIS(日本語Windowsの場合)へ変更するには、下記手順で行います。Studioのデフォルトですし、Windows専用プログラムの場合はこちらが好ましいと思います。下記のような問題は発生します。コマンド・プロンプトへ日本語出力がやりづらいデバッグ用に出力することもあると思います。L"日本語\n";のようにして出力するのでずか、デフォルトでは何も表示されません。おまじないが必要です。char型文字列しか扱わないライブラリとの共存に手間がかかるエラー・メッセージを作る時、ライブラリへ与えた文字列をメッセージ内に含めることも少なくないですが、その時UTF-16との変換について考慮することが必要です。この問題を軽減するため、ASCII文字列をUTF-16文字列へ変換するツールを用意しておくと好ましいです。(後述)2-4-4.UTF-8を使うマルチ・プラットフォーム対応の「高度な日本語処理を行わないような普通」のプログラムを開発する時は、UTF-8を中心的な文字コードにすることがお薦めです。Stduioの設定は2-4-3.と同じくデフォルト(Unicode文字セットを使う)のまま変更しないで下さい。)LinuxではUTF-8がデファクト・スタンダードですので、よりソースを共通化しやすいです。#ifでプラットフォーム毎の分岐が大きく減ります。char型文字列しか扱わないライブラリとの共存が容易です。エラー・メッセージを作る時、ライブラリへ与えた文字列をメッセージ内に含めることも少なくないですが、その時UTF-16との変換を考慮しなくて良いので楽です。APIを呼び出す部分は専用コードを書くことになりますから、そこでUTF-8とUTF-16を変換することになります。UTF-8とUTF-16の変換関数を用意しておけば軽減できます。(後述)また、Windowsのコマンド・プロンプトへUTF-8文字列を出力すると文字化けしますので、デバッグ等でコマンド・プロンプトを使う場合にちょっとだけ面倒です。こちらもちょっとしたツールを用意すると問題を大きく軽減できます。C++でUTF-16やUTF-8を使うときのちょっとしたコード変換ツールを作ってみました。ご自由に使って下さい。私からの保証はありませんので、ご自身の責任でお願いします。)C言語で作ると結構手間がかかりますが、C++11ならたいへん楽です。2015でビルドできます。C++専用ツールですので、gccではビルドできません。MinGWならビルド出来る可能性はありますが、未確認です。3-1.文字コード変換ツール群Shift-JISとUTF-16、UTF-8とUTF-16間の相互変換を行います。UTF-8はASCIIをカバーしていますので、ASCI文字列をUTF-16へ変換する時はconvertUtf8ToUtf16()を使って下さい。std::wstring、std::u16string、wchar_t、char16_tは全てUTF-16でエンコードされた文字列が設定されていることを仮定しています。ヘッダ・オンリですので、utf16_vc++.hをインクルードすれば使えます。(utf8_vc++.hをインクルードしているのでutf8_vc++.hも同じフォルダにおいてください。...)をオーバーロードします。Shift-JIS文字列を出力しようとすると、それをUTF-8と解釈してUTF-16へ変換しようとし、かなりの率で失敗します。変換できなかった時はrange_error例外が発生します。ヘッダ・オンリですので、utf8_vc++.hをインクルードすれば使えます。10のコマンド・プロンプトの仕様がいつのまにか変わっているようです。デフォルトではShift-JIS文字列が適切に表示されません。コンソールを使う」をチェックしてコマンド・プロンプトを再起動すると表示されるようになります。しておくと新コンソールでも化けないようです。詳しい事情はまだ把握できていません。ご存知の方がいらっしゃいましたら、コメントいただけるとありがたいです。4.まとめC++による日本語プログラミング環境は、残念ながら過去のシガラミもあり、すっきり「これが正解」と言うプログラム方法が決まっていません。アプリケーションにより複数の選択肢があり、しかも、処理系によって選択できる選択肢が異なる状況です。(LinuxではUTF-8が優勢です。Windowsが特に悩ましいです。)それらの歴史的な経緯と現在使われている文字コードの特徴について解説しました。高度な日本語処理を行うアプリケーションを開発するにはとても足りませんが、メッセージ表示等を日本語化するための最小限の知識を解説できたと思います。C++で日本語を扱う際の便利ツールも提供してみました。良かったらお使い下さい。Unicode対応ですし、Shift-JISと明示的に指定しているわけでなく、Windowsのコントロール・パネルの地域に設定されている非Unicode時の言語設定に従った処理となっていますので、恐らく他の国の言語でも動作することを期待できます。(実際に走らせてないので確認出来ていません。)来週は、プリプロセッサについて少し突っ込んだ使い方等を解説したいと思います。プリプロセッサは、テンプレートと同様一種のメタ・プログラム(プログラム・コードを生成するプログラム)としても働きますので、意外に便利です。21:01はじめまして、teratailから飛んできましたw交換機やらフィルターサーバやら単発・組み込みばかりやってきて最新の知識には疎いので、(既に引退してますが)こういったサイトは、大変ありがたいです。・・・c++は、ますます難しくなって(私の頭では)なかなか追いつけません。今後ともよろしくお願いします。21:22CatEye様、コメントありがとうございます。コメントって嬉しいものですね。ありがたいと言って頂けると励みになります。時々分かりにくい部分もあるかと思いますが、頑張って更新していきますので、是非お付き合い下さい。これからもよろしくお願い致します。コメントをキャンセルメールアドレスが公開されることはありません。テクノロジーの登録商標です。technology.ブログ内サンプル・コードのライセンス1.本ソフトウェアは、ご自由にお使いください。2.本ソフトウェアは、あるがままの姿で提供いたします。明示黙示を問わず、瑕疵がないこと、特定の目的に適合すること、使用地域における法令の規制等に合致すること、その他一切の保証をいたしません。3.本ソフトウェアについては、無償で提供するものですので、何らかの不具合が発生した場合であっても、セオライドテクノロジーは、何らの責任も負いません。使用するかどうかのご判断も、ご自身でお願いいたします。テクノロジーは一切その責任を負いません。データのバックアップ等については、お客様の責任において行ってください。テクノロジーは一切その責任を負いません。テクノロジーは、一切の責任を負いません。7.セオライドテクノロジーは、本ソフトウェアに関する技術的サポートは行いません。