C++Builder Unicode対応 ====================== [[devtool/ide/cpp_builder-rad_studio/start|C++Builder]]の RAD Studio 2009 バージョン以降で、完全に[[wpjp>Unicode|Unicode]]をサポートして内部の文字列の扱いが変更になっている。特に、それ以前のバージョン(私の場合は C++Builder 5)のソースを動かそうとした場合に、色々と留意する点があるので備忘録を残す。 文字列の扱い変更対応 ----------------- `UnicodeString`型が追加され、従来の `String`型,`Char`型,`PChar`型の定義が以下のように変更されている。({{https://www.embarcadero.com/images/jp/dm/technical-papers/delphi_unicode_wp_jp.pdf|参考1.}}資料参照) ^ 型 ^ 意味 ^ 備考 ^ | `String` | `UnicodeString`型でtypedef | UTF-16文字列 | | `Char` | `wchar_t`でtypedef | UTF-16文字 | | `PChar` | `wchar_t *`でtypedef | | ### 準備 ソースファイルは全て UTF-8 のBOM付きに変換して保存しておく。 ### 文字列及び文字の型移行 従来の`AnsiString`や`char`型も引き続き使えるが、将来の事も考えて以下のようにソースを修正。 ^ 移行前 ^ 移行後 ^ 備考 ^ | `AnsiString` | `String` | あえて`UnicodeString`にしない | | `char` | `Char` | | | `char *` | `PChar` | | ### 文字列定数及び文字定数の修正 文字列と文字定数の前には、以下のように `L` 文字を付加する。 String str = L"文字列"; Char c = L'あ'; ### C標準関数の修正 `fopen`などのC標準関数は、`char`型を要求しているのでコンパイルエラーとなる。以下のように、`_w`を付加した関数名に変更する。 String fname = L"test.txt"; fp = fopen(fname.c_str(), "rt"); ↓ fp = _wfopen(fname.c_str(), L"rt"); * 「[[http://docwiki.embarcadero.com/RADStudio/Rio/ja/Fopen%EF%BC%8C_wfopen|fopen,_wfopen]]」ヘルプページ その他対応の関数名は「[[http://docwiki.embarcadero.com/RADStudio/Rio/ja/%E3%83%9E%E3%83%83%E3%83%97%E9%96%A2%E6%95%B0|マップ関数]]」ヘルプページを参照し下記のように変更。 ^ 移行前 ^ 移行後 ^ リンク ^ 備考 ^ | `fgetc` | `fgetwc` | [[http://docwiki.embarcadero.com/RADStudio/Rio/ja/Fgetc%EF%BC%8Cfgetwc|fgetc,fgetwc]] | 終了時は `WEOF` が戻る | | `sprintf` | `swprintf` | [[http://docwiki.embarcadero.com/RADStudio/Rio/ja/Sprintf%EF%BC%8Cswprintf|sprintf,swprintf]] | | | `toupper` | `towupper` | [[http://docwiki.embarcadero.com/RADStudio/Rio/ja/Toupper%EF%BC%8C_mbctoupper%EF%BC%8Ctowupper|toupper,_mbctoupper,towupper]] | | | `tolower` | `towlower` | [[http://docwiki.embarcadero.com/RADStudio/Rio/ja/Tolower%EF%BC%8C_mbctolower%EF%BC%8Ctowlower|tolower,_mbctolower,towlower]] | | その他注意点 ---------- ### 添え字番号の開始は1 String型の文字列は文字配列のようにアクセスできるが、添え字の開始番号は 0 でなくて 1〜 なので注意。(0でアクセスすると例外トラップ) String text = L"あいうえお"; Char c = text[1]; /* 'あ'が取り出される */ 所感 ---- 最初は「かなり思い切った仕様変更だな」と戸惑ったが、ソース修正は必要だが上記要領で案外スムーズに動いた。 参考 ---- 1. {{https://www.embarcadero.com/images/jp/dm/technical-papers/delphi_unicode_wp_jp.pdf|Delphiにおける一般的なUnicodeへの移行テクニック}} 2. [[http://docwiki.embarcadero.com/RADStudio/Rio/ja/RAD_Studio_%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B_Unicode|RAD Studio における Unicode]] 3. [[https://www.embarcadero.com/images/jp/event/devcamp/session_docs/11/a6.pdf|Delphi 2009ではじめるUnicodeアプリケーション - 既存コード移行のポイント -]] 4. [[https://www.embarcadero.com/jp/migration-and-upgrade-resources-for-delphi-c-builder-and-rad-studio|旧バージョンからの移行]] 5. [[https://www.gesource.jp/weblog/?p=543|C++Builder2009におけるStringの変更による既存コードの修正]] 6. [[http://slapper.sblo.jp/article/62581507.html|C++Builder 文字列変換]] 7. [[https://stackoverflow.com/questions/26073814/cannot-convert-const-char-to-wchar-in-argument-passing|Cannot convert 'const char*' to 'WCHAR*' in argument passing]] 8. [[http://docwiki.embarcadero.com/Libraries/Rio/ja/System.UnicodeString_Methods|System.UnicodeString のメソッド]] 9. [[https://www.gesource.jp/programming/bcb/37.html|UTF-8を使う]] 10. [[https://rosettacode.org/wiki/Read_a_file_character_by_character/UTF8|Read a file character by character/UTF8]]