C 文字列操作 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(文字列の型変換)
(文字列と日付・日時・時間の変換)
 
1行: 1行:
 +
[[C PlusPlus#Cにもあった技術|C++]]へ戻る
 +
 +
 
※このページではC言語にも存在していたという意味で記事タイトルがC 文字列操作になっていますが、<br />
 
※このページではC言語にも存在していたという意味で記事タイトルがC 文字列操作になっていますが、<br />
 
[[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br />
 
[[C PlusPlus|C++]]でも同様です。[[C PlusPlus|C++]]だけの機能がある場合は明記します。<br />
 
<br />
 
<br />
 
== '''文字列操作''' ==
 
== '''文字列操作''' ==
 +
 
文字列のコピー、連結、比較、一致、区切り文字分割、探索、文字列長取得といった操作を文字列操作と呼びます。上記のような操作はCRT関数として提供されているため、関数の使い方さえ覚えれば簡単に操作できます。
 
文字列のコピー、連結、比較、一致、区切り文字分割、探索、文字列長取得といった操作を文字列操作と呼びます。上記のような操作はCRT関数として提供されているため、関数の使い方さえ覚えれば簡単に操作できます。
更に、文字列の型変換、文字コード変換、大文字小文字変換、半角文字、全角文字変換、ファイルパス操作、ファイル名操作、拡張子取得といった文字列操作の応用もプログラミングでは必要になってきますし、文字列の検索と置換、ファイルへの入出力といった操作までを習得すると概ねの操作ができるようになります。<br />
+
更に、文字列の型変換、文字コード変換、大文字小文字変換、半角文字、全角文字変換、ファイルパス操作、ファイル名操作、拡張子取得といった文字列操作の応用もプログラミングでは必要になってきますし、文字列の検索と置換、ファイルへの入出力といった操作までを習得すると概ねの操作ができるようになります。ちなみに、XMLとか、HTMLとか特定の形式のテキストを取り扱う技術についてはここでは、取り上げません。記述するとしたら別の項目になるかと思います。<br />
  
  
19行: 23行:
 
http://msdn.microsoft.com/ja-jp/library/f0151s4x.aspx<br />
 
http://msdn.microsoft.com/ja-jp/library/f0151s4x.aspx<br />
 
上記があれば、自分が説明する必要はもうないかなと思うわけですが、一応、自分なりに。<br />
 
上記があれば、自分が説明する必要はもうないかなと思うわけですが、一応、自分なりに。<br />
 +
 +
ちなみにマルチバイト文字関連の操作は関数が用意されていますが、Windowsストアアプリを作成することはできません。詳細は以下のページの説明のとおりです。変換以外の操作はUnicodeで文字列を扱ってください。つまり、以下で紹介する_mbs***系の操作関数は使えないと考えてください。_wcs***系や_tcs***系でワイド文字を扱う関数にする必要があります。
 +
http://msdn.microsoft.com/library/windows/apps/jj606124.aspx
  
 
=='''文字列長取得'''==
 
=='''文字列長取得'''==
53行: 60行:
  
  
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <tchar.h>
 
#include <tchar.h>
 
int main() {
 
int main() {
62行: 69行:
 
}
 
}
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
出力結果
 
出力結果
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
  0/ 3:cStr0[ 0]=表示:よねウィキの機能<yonewiki>
 
  0/ 3:cStr0[ 0]=表示:よねウィキの機能<yonewiki>
 
StrCount=21
 
StrCount=21
73行: 80行:
 
  2/ 3:cStr0[ 2]=表示:よねウィキの機能2<yonewiki>
 
  2/ 3:cStr0[ 2]=表示:よねウィキの機能2<yonewiki>
 
StrCount=22
 
StrCount=22
</syntaxhighlight>
+
</syntaxhighlight2>
 
_mb系の関数を利用するには、<nowiki>#include <mbstring.h></nowiki>をインクルードする必要があります。<br />
 
_mb系の関数を利用するには、<nowiki>#include <mbstring.h></nowiki>をインクルードする必要があります。<br />
  
82行: 89行:
  
  
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <tchar.h>
 
#include <tchar.h>
 
#include <mbstring.h>
 
#include <mbstring.h>
105行: 112行:
 
delete[] ppcStr1;
 
delete[] ppcStr1;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
という具合にして、const char→char→_mabslenで文字列長探索が出来ます。出力結果は以下のとおりです。<br />
 
という具合にして、const char→char→_mabslenで文字列長探索が出来ます。出力結果は以下のとおりです。<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
const マルチバイト文字→マルチバイト文字コピー→_mbslen関数2バイト文字認識文字列長探索
 
const マルチバイト文字→マルチバイト文字コピー→_mbslen関数2バイト文字認識文字列長探索
 
  0/ 4:cStr1[ 0]=
 
  0/ 4:cStr1[ 0]=
121行: 128行:
 
StrCount=22
 
StrCount=22
  
</syntaxhighlight>
+
</syntaxhighlight2>
 
_mbstrlen関数を使う場合はコピー操作が必要にならず、const宣言している文字列変数を使っての文字列長探索ができます。<br />
 
_mbstrlen関数を使う場合はコピー操作が必要にならず、const宣言している文字列変数を使っての文字列長探索ができます。<br />
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <tchar.h>
 
#include <tchar.h>
 
#include <mbstring.h>
 
#include <mbstring.h>
134行: 141行:
 
}
 
}
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
出力結果は以下のとおりです。<br />
 
出力結果は以下のとおりです。<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
const マルチバイト文字→_mbstrlen関数2バイト文字認識文字列長探索
 
const マルチバイト文字→_mbstrlen関数2バイト文字認識文字列長探索
 
  0/ 4:cStr1[ 0]=
 
  0/ 4:cStr1[ 0]=
150行: 157行:
 
StrCount=22
 
StrCount=22
  
</syntaxhighlight>
+
</syntaxhighlight2>
 
といった具合にいろいろな関数があるので、一つづつ掘り下げて理解しておくのも、必要です。こういう違いがあるということを把握していれば、臨機応変に対応しやすくなるかもです。自分は分かったつもりにならずに、常に謙虚に確かめてみる姿勢ってのは、必要なんじゃないかと思います。そして常に、自分が実施するであろうパターンを網羅して確かめる。だから、あえて文字列の配列の場合にどうやればいいのかを探ります。
 
といった具合にいろいろな関数があるので、一つづつ掘り下げて理解しておくのも、必要です。こういう違いがあるということを把握していれば、臨機応変に対応しやすくなるかもです。自分は分かったつもりにならずに、常に謙虚に確かめてみる姿勢ってのは、必要なんじゃないかと思います。そして常に、自分が実施するであろうパターンを網羅して確かめる。だから、あえて文字列の配列の場合にどうやればいいのかを探ります。
  
180行: 187行:
  
 
で、結局は_tcsncpy_sを使いなさいってことになります。Unicode設定ならワイド文字版で、文字列長に厳しい設定が必要なwcsncpy_sだね。第二引数は配列の大きさ+終端\0のための要素1つ分。バイト数ではないです。動的に生成した変数の場合は配列の大きさが取得できないので、wcslen(_tcslen)のような文字列長取得関数を使って、戻ってきた値に\0の要素のために1を加算した値が良いです。<br />
 
で、結局は_tcsncpy_sを使いなさいってことになります。Unicode設定ならワイド文字版で、文字列長に厳しい設定が必要なwcsncpy_sだね。第二引数は配列の大きさ+終端\0のための要素1つ分。バイト数ではないです。動的に生成した変数の場合は配列の大きさが取得できないので、wcslen(_tcslen)のような文字列長取得関数を使って、戻ってきた値に\0の要素のために1を加算した値が良いです。<br />
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
 
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
242行: 249行:
 
return 0;
 
return 0;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
という感じでしたね。無理やり_mbscpy関数を使ってみるとこんな感じですね。unsigned char型は宣言と同時にnew演算子の定義は出来ないようです。const型のcharからはキャストできないから、結局は一度、strcpy_sを使って、char型の文字列に置き換えないといけないです。マルチバイト型の2バイト文字認識操作関数って結局は、char型と同じなので、文字数を数えるときはstrlenで数えないといけない。char型と_mbsxxx関数を行ったり来たりするだけです。<br />
 
という感じでしたね。無理やり_mbscpy関数を使ってみるとこんな感じですね。unsigned char型は宣言と同時にnew演算子の定義は出来ないようです。const型のcharからはキャストできないから、結局は一度、strcpy_sを使って、char型の文字列に置き換えないといけないです。マルチバイト型の2バイト文字認識操作関数って結局は、char型と同じなので、文字数を数えるときはstrlenで数えないといけない。char型と_mbsxxx関数を行ったり来たりするだけです。<br />
 
出力結果は以下のとおり<br />
 
出力結果は以下のとおり<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
_tcslen(cStr0[i])=21
 
_tcslen(cStr0[i])=21
 
ppcStr0=表示:よねウィキの機能<yonewiki>,
 
ppcStr0=表示:よねウィキの機能<yonewiki>,
289行: 296行:
 
ppucStr2=表示:よねウィキの機能2<yonewiki>,
 
ppucStr2=表示:よねウィキの機能2<yonewiki>,
 
  cStr1=表示:よねウィキの機能2<yonewiki>,
 
  cStr1=表示:よねウィキの機能2<yonewiki>,
</syntaxhighlight>
+
</syntaxhighlight2>
 
上記に加えて、コピーする文字数を引数とするcpyの前にnが付く関数_tcsncpy_s/wcsncpy_s/strncpy_s/_mbsncpy_sにする場合は<br />
 
上記に加えて、コピーする文字数を引数とするcpyの前にnが付く関数_tcsncpy_s/wcsncpy_s/strncpy_s/_mbsncpy_sにする場合は<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
 
 
 
307行: 314行:
 
 
 
 
</syntaxhighlight>
+
</syntaxhighlight2>
 
と、4つの引数をとるように記述します。第4引数が出力する最大文字の配列数です。出力する文字数と考えることもできます。マルチバイト文字の場合には出力する文字数を指定できるのは効果的で、先頭から何バイト目で区切れば日本語文字が分断されないかの判断もしてくれながらの出力となります。この出力する文字数をあえてバイト単位で指定する_mbsnbcpy_sもあります。ただし、コピー先の文字列の配列はstrlenのようなバイト数分で準備する必要があることに注意が必要です。出力文字数を指定する場合は文字列全体の長さではなく、指定した文字数で必要な文字列バイト数を算出しておいて、メモリを確保するように処理を記述するのが良いかもしれません。ここでは強制キャストを使いましたが、もともとの文字列がunsigned charとして定義されているものをコピーするときに_mbs系の文字列コピーを利用するというのが自然な使い方になります。<br />
 
と、4つの引数をとるように記述します。第4引数が出力する最大文字の配列数です。出力する文字数と考えることもできます。マルチバイト文字の場合には出力する文字数を指定できるのは効果的で、先頭から何バイト目で区切れば日本語文字が分断されないかの判断もしてくれながらの出力となります。この出力する文字数をあえてバイト単位で指定する_mbsnbcpy_sもあります。ただし、コピー先の文字列の配列はstrlenのようなバイト数分で準備する必要があることに注意が必要です。出力文字数を指定する場合は文字列全体の長さではなく、指定した文字数で必要な文字列バイト数を算出しておいて、メモリを確保するように処理を記述するのが良いかもしれません。ここでは強制キャストを使いましたが、もともとの文字列がunsigned charとして定義されているものをコピーするときに_mbs系の文字列コピーを利用するというのが自然な使い方になります。<br />
  
329行: 336行:
 
例によって_sのついた連結先文字列の配列サイズを明記する関数に_lのついた個別ロケール設定関数。そして連結させたい文字列の文字数を記述するncatに文字数をバイト数で指定するnbcat。あとはワイド文字のwcsで始まる関数。マルチバイトのstrで始まる関数。マルチバイト2バイト文字対応の_mbsで始まる関数。全部で22種類。引数は文字列コピーと同じですが、コピー先の変数が既に文字列が格納されてる\0で終わる文字列になっていて、処理をした結果、第一引数の文字列先頭アドレスの中身が文字列連結した結果になるという点が異なると覚えれば、連結とコピーは似ていると覚えればよいかと思います。先の文字列コピーのプログラムのコピーcpy系関数の後ろに連結cat系関数を追加して、文字列を2回繰り返されるようにしたサンプルです。所謂(いわゆる)、手抜きです。ただし、連結関数では連結後の文字列の配列大きさを要求されるため、あらかじめ動的に確保する領域が2倍になっていることに注意して下さい。<br />
 
例によって_sのついた連結先文字列の配列サイズを明記する関数に_lのついた個別ロケール設定関数。そして連結させたい文字列の文字数を記述するncatに文字数をバイト数で指定するnbcat。あとはワイド文字のwcsで始まる関数。マルチバイトのstrで始まる関数。マルチバイト2バイト文字対応の_mbsで始まる関数。全部で22種類。引数は文字列コピーと同じですが、コピー先の変数が既に文字列が格納されてる\0で終わる文字列になっていて、処理をした結果、第一引数の文字列先頭アドレスの中身が文字列連結した結果になるという点が異なると覚えれば、連結とコピーは似ていると覚えればよいかと思います。先の文字列コピーのプログラムのコピーcpy系関数の後ろに連結cat系関数を追加して、文字列を2回繰り返されるようにしたサンプルです。所謂(いわゆる)、手抜きです。ただし、連結関数では連結後の文字列の配列大きさを要求されるため、あらかじめ動的に確保する領域が2倍になっていることに注意して下さい。<br />
  
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> tchar.hがインクルードされていればいらない。
 
//#include<locale.h> tchar.hがインクルードされていればいらない。
394行: 401行:
 
return 0;
 
return 0;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
  
 
出力結果<br />
 
出力結果<br />
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
_tcslen(cStr0[i])=21
 
_tcslen(cStr0[i])=21
 
ppcStr0=表示:よねウィキの機能<yonewiki>表示:よねウィキの機能<yonewiki>,
 
ppcStr0=表示:よねウィキの機能<yonewiki>表示:よねウィキの機能<yonewiki>,
441行: 448行:
 
ppucStr2=表示:よねウィキの機能2<yonewiki>表示:よねウィキの機能2<yonewiki>表示:よねウィキの機能2<yonewiki>表示:よねウィキの機能2<yonewiki>,
 
ppucStr2=表示:よねウィキの機能2<yonewiki>表示:よねウィキの機能2<yonewiki>表示:よねウィキの機能2<yonewiki>表示:よねウィキの機能2<yonewiki>,
 
  cStr1=表示:よねウィキの機能2<yonewiki>,
 
  cStr1=表示:よねウィキの機能2<yonewiki>,
</syntaxhighlight>
+
</syntaxhighlight2>
  
 
=='''文字列比較'''==
 
=='''文字列比較'''==
474行: 481行:
  
  
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
//#include<locale.h> wchar.hがインクルードされていれば、いらない。
 
//#include<locale.h> wchar.hがインクルードされていれば、いらない。
562行: 569行:
 
return 0;
 
return 0;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
  
 
出力結果
 
出力結果
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
_tcslen(cStr0[i])=22
 
_tcslen(cStr0[i])=22
 
ppcStr0=表示:よねウィキの機能0<yonewiki>表示:よねウィキの機能0<yonewiki>,
 
ppcStr0=表示:よねウィキの機能0<yonewiki>表示:よねウィキの機能0<yonewiki>,
660行: 667行:
 
i=3, k=3, iCmpResult=0,
 
i=3, k=3, iCmpResult=0,
  
</syntaxhighlight>
+
</syntaxhighlight2>
 
と、こんな感じです。結果を見るとわかるのですが、1,-1,0で結果が表現され、先頭から比較して、一番最初に異なる文字同志を比較したときの結果、文字コードの値が大きかったか小さかったかで、1と-1とに結果が分かれます。これを使って昇順に並べたりすることも出来ます。もちろん0が返ってきたときは、完全一致です。等しかったということになります。<br />
 
と、こんな感じです。結果を見るとわかるのですが、1,-1,0で結果が表現され、先頭から比較して、一番最初に異なる文字同志を比較したときの結果、文字コードの値が大きかったか小さかったかで、1と-1とに結果が分かれます。これを使って昇順に並べたりすることも出来ます。もちろん0が返ってきたときは、完全一致です。等しかったということになります。<br />
  
696行: 703行:
 
<br />
 
<br />
 
という具合の動作であります。collの特徴的なのは辞書順と呼んでいる比較の概念だと思います。ASCIIコードでは大文字と小文字とでは、小文字の方が大きい文字コード番号が付与されていますが、wcs**coll系の比較をする関数では、小文字の方が値が小さいものとして判定してくれます。漢字の範囲になるとロケールで指定したcp932の文字コード順で比較してくれます。阿という文字と哀という文字はUnicode(UTF16)では阿-0x963F 哀-0x54C0 表-0x8868であり、Shift_JISのcp932では阿-0x88A2 哀-0x88A3 表-0x955Cと定義されていますから、阿<nowiki><</nowiki>哀<nowiki><</nowiki>表 のように比較をしてくれます。coll系の関数を使わない場合は 哀<nowiki><</nowiki>表<nowiki><</nowiki>阿のように比較されます。この阿や哀や表という名前のファイル名のテキストをWindowsのエクスプローラで昇順表示すると、この順番になることも確認できます。Shift_JISコード順でソートされてるんだなぁと確認が出来ると思います。Cp932の半角記号あたりの辞書順ってのは、どうなってるんでしょうね。これもまた今度しらべてみたいと思います。ファイル名に使えない文字あたりはどんな順番なんだろうか?
 
という具合の動作であります。collの特徴的なのは辞書順と呼んでいる比較の概念だと思います。ASCIIコードでは大文字と小文字とでは、小文字の方が大きい文字コード番号が付与されていますが、wcs**coll系の比較をする関数では、小文字の方が値が小さいものとして判定してくれます。漢字の範囲になるとロケールで指定したcp932の文字コード順で比較してくれます。阿という文字と哀という文字はUnicode(UTF16)では阿-0x963F 哀-0x54C0 表-0x8868であり、Shift_JISのcp932では阿-0x88A2 哀-0x88A3 表-0x955Cと定義されていますから、阿<nowiki><</nowiki>哀<nowiki><</nowiki>表 のように比較をしてくれます。coll系の関数を使わない場合は 哀<nowiki><</nowiki>表<nowiki><</nowiki>阿のように比較されます。この阿や哀や表という名前のファイル名のテキストをWindowsのエクスプローラで昇順表示すると、この順番になることも確認できます。Shift_JISコード順でソートされてるんだなぁと確認が出来ると思います。Cp932の半角記号あたりの辞書順ってのは、どうなってるんでしょうね。これもまた今度しらべてみたいと思います。ファイル名に使えない文字あたりはどんな順番なんだろうか?
 +
 +
 +
coll系の比較の中身を見るための関数としては、strxfrm関数がある。これがロケール設定にしたがった照合順序文字列を生成してくれる。これは文字列ではあるが、書き出すことは出来ない照合のための文字コードだと考えればよい。中身をみたければstrxfrmで変換してバイトコードを確認することができるが、ロケール設定によってはなぜこんな変換になるんだ?というような不思議な変換がなされる。とくにen-US.utf8とかになると発音記号のアクセントや、特殊記号を別の辞書順と管理するため、1つの文字列が3つに分割され、1文字でもトークンとなるバイトコードが2つと文字列、アクセント、大文字小文字で3つのバイトコードで5バイトになる。更に特殊記号がひとつでも現れる文字列なら4つに分割され、特殊記号の使われる位置情報まで生成される。このような照合順序規則がロケールごとに存在する。coll系の比較関数はとんでもなく複雑な処理を行う比較関数なのだ。それゆえ通常のcmp系の関数と比べても、処理時間がかかる。localeごとの照合順序について理解しているならば、strxfrmで返還後のコードを使って、strcoll関数のような比較処理を高速化することも可能となる。ロケールによる処理も含めた関数の利用が必要になるケースもあるかもしれないが、ロケールの特徴を理解して、使うのも大事だし、使いどころが肝心となる。
  
 
  '''★豆知識'''
 
  '''★豆知識'''
 
  '''Unicodeの符号化方式UTF-16とは…'''
 
  '''Unicodeの符号化方式UTF-16とは…'''
 
  日本語の範囲ではUTF16は2バイト文字と考えて良いですが、Unicode全体では0x10FFFFまで利用することになっていますので、0x10000以上の値を持つ文字コードは4バイト文字になります。この0x10000以上の値になる場合は、ビット列で表現すると110110????xxxxxx 110111xxxxxxxxxxのような形式になり????の部分のには上位ビットと下位ビットを16ビットずつに分けた時に0xUUUUDDDDと表記するならば、0xUUUUは0x0001~0x0010の値となり得て、そのUUUU-1の値が????に入ります。xの部分には下位DDDDのビット列そのものが
 
  日本語の範囲ではUTF16は2バイト文字と考えて良いですが、Unicode全体では0x10FFFFまで利用することになっていますので、0x10000以上の値を持つ文字コードは4バイト文字になります。この0x10000以上の値になる場合は、ビット列で表現すると110110????xxxxxx 110111xxxxxxxxxxのような形式になり????の部分のには上位ビットと下位ビットを16ビットずつに分けた時に0xUUUUDDDDと表記するならば、0xUUUUは0x0001~0x0010の値となり得て、そのUUUU-1の値が????に入ります。xの部分には下位DDDDのビット列そのものが
  入ったような値になります。そういう意味ではUnicodeのUTF-16という符号化方式では16bit(2byte)だったり32bit(4byte)のコードになります。
+
  入ったような値になります。そういう意味ではUnicodeのUTF-16という符号化方式では16bit(2byte)だったり32bit(4byte)のコードになります。※更に異体字セレクタというコードが付与されるケースがあり、付与される場合はUnicode文字番号つづけて、E0100、E0101、E0102…といった値が付与されます。UTF-16の2バイトコードであれば、さらにDB40 DD00という4バイトが付与され一文字が6文字になります。似ている文字をこのセレクタ番号によって切り替えるという仕組みです。したがって2バイト文字は6バイトに、4バイト文字は8バイトになります。テキストエディタおよびフォントも対応していないと使えないような特殊な文字ですが、存在している以上、対応しなければならない可能性はあります。現状はあまり対応されていないようですが、メモ帳でさえも異体字セレクタに対応しているというのが現実です。
 
   
 
   
 
  '''Unicodeの符号化方式UTF-8とは…'''
 
  '''Unicodeの符号化方式UTF-8とは…'''
707行: 717行:
 
  x0,x1,x2,x3, x4,x5,x6,x7, x8,x9,xA,xB, xC,xD,xE,xFと表現すると、
 
  x0,x1,x2,x3, x4,x5,x6,x7, x8,x9,xA,xB, xC,xD,xE,xFと表現すると、
 
  (1110),(x0,x1,x2,x3),(10,x4,x5),(x6,x7, x8,x9),(10,xA,xB),(xC,xD,xE,xF)となります。
 
  (1110),(x0,x1,x2,x3),(10,x4,x5),(x6,x7, x8,x9),(10,xA,xB),(xC,xD,xE,xF)となります。
  文字の先頭に3バイトなら3つの1が付き、1バイト目を構成し、 次のバイト以降はバイト先頭に全て10をつける。おかげさまで、1バイト目の下位4bitと、3バイト目の下位4bitの16進数だけはそのままだけど、他のbitは16進表記が、変化します。読み起こすのは大変ですね。文字列の最初を見つけたら、そこから文字列に起こしていけば良いですが、新しい変換表を考えないと直感的にはUnicode文字のコード表には表現できないですね。
+
  文字の先頭に3バイトなら3つの1が付き、1バイト目を構成し、 次のバイト以降はバイト先頭に全て10をつける。おかげさまで、1バイト目の下位4bitと、3バイト目の下位4bitの16進数だけはそのままだけど、他のbitは16進表記が、変化します。読み起こすのは大変ですね。文字列の最初を見つけたら、そこから文字列に起こしていけば良いですが、新しい変換表を考えないと直感的にはUnicode文字のコード表には表現できないですね。UTF-8の場合、異体字セレクタはF3 A0 84 80という4バイトが不可されて、3バイト文字は7バイト 4バイト文字は8バイトになります。セレクタがひとつ変化する都度最後の2バイトが80→81→82と変化していきます。
  
 
=='''文字列区切り文字分割'''==
 
=='''文字列区切り文字分割'''==
730行: 740行:
 
比較関数よりは少ないけど、やっぱりマルチバイト版、マルチバイト2バイト文字対応版、ワイド文字版、それに_sをつけた文字列長を指定するセキュア版と個別ロケール指定をする_lのロケール版があります。_l版についてはココまで使い方を触れてこなかったのですが、
 
比較関数よりは少ないけど、やっぱりマルチバイト版、マルチバイト2バイト文字対応版、ワイド文字版、それに_sをつけた文字列長を指定するセキュア版と個別ロケール指定をする_lのロケール版があります。_l版についてはココまで使い方を触れてこなかったのですが、
  
<syntaxhighlight lang="cpp">
+
<syntaxhighlight2 lang="cpp">
 
_locale_t locale;
 
_locale_t locale;
 
locale = _tsetlocale(LC_ALL, _T("Japanese"));
 
locale = _tsetlocale(LC_ALL, _T("Japanese"));
</syntaxhighlight>
+
</syntaxhighlight2>
 
として、localeという変数に_locale_t型の値を_tsetlocaleの返り値として格納しておいたものを関数の最後の引数にします。<br />
 
として、localeという変数に_locale_t型の値を_tsetlocaleの返り値として格納しておいたものを関数の最後の引数にします。<br />
 
コマンドプロンプトで動作確認してるだけの段階でlocale変数を利用しても、文字化けしか起こせないと思うので、テキスト出力とかを覚えてから試してみるといいかもしれません。<br />
 
コマンドプロンプトで動作確認してるだけの段階でlocale変数を利用しても、文字化けしか起こせないと思うので、テキスト出力とかを覚えてから試してみるといいかもしれません。<br />
758行: 768行:
  
 
区切り文字として複数の文字を指定できますが、それぞれ1文字が独立した区切り文字ですので、// のような2文字以上で構成される区切り文字はこの関数だけでは対応できません。新しい手法が必要になります。
 
区切り文字として複数の文字を指定できますが、それぞれ1文字が独立した区切り文字ですので、// のような2文字以上で構成される区切り文字はこの関数だけでは対応できません。新しい手法が必要になります。
<syntaxhighlight lang="cpp" line start="1">
+
<syntaxhighlight2 lang="cpp" line start="1">
 
#include <iostream>
 
#include <iostream>
 
#include <tchar.h>
 
#include <tchar.h>
918行: 928行:
 
   return 0;
 
   return 0;
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight2>
 
という具合にtcstok_s関数を使えば、並列してトークン処理が進められるようです。第3引数の参照というC++独自の型を使って、44行目 78行目での最初の呼び出し(エスタブリッシュとも表現します。エスタブリッシュショットというと撮影なんかでワンシーンの手前に一枚絵の風景絵を置くことで、時間帯を表現したりする手法を指します。夜景がシーンの前に入れば室内に映像が切り替わっても夜の出来事であるように示唆するものです。)をして、111、114、131行目のように連続して現れるであろう区切り文字を検索します。111,114行目では、もう区切り文字が現れることがないことがわかっているのですが、2個目のトークンを取得するために実行したり、ループ処理を終わらせるために再度、実行したりという手法で使っています。アイデア次第でなんでもありです。最初にカンマ区切りでトークンを取得するのですが、その間で、さらにカンマ区切りトークンの中に必ず一度現れる、スラッシュによるトークン処理を入れこんでいます。区切り文字が違うだけで全く同じ処理です。こういうプログラム記法は普通はしません。通常は、関数のようなサブプログラムにして、関数を呼び出すことで同じ処理になるように記述します。C++の場合は関数でなくても、クラスのメンバ関数にしても良い訳です。結局同じことですが…。<br />
 
という具合にtcstok_s関数を使えば、並列してトークン処理が進められるようです。第3引数の参照というC++独自の型を使って、44行目 78行目での最初の呼び出し(エスタブリッシュとも表現します。エスタブリッシュショットというと撮影なんかでワンシーンの手前に一枚絵の風景絵を置くことで、時間帯を表現したりする手法を指します。夜景がシーンの前に入れば室内に映像が切り替わっても夜の出来事であるように示唆するものです。)をして、111、114、131行目のように連続して現れるであろう区切り文字を検索します。111,114行目では、もう区切り文字が現れることがないことがわかっているのですが、2個目のトークンを取得するために実行したり、ループ処理を終わらせるために再度、実行したりという手法で使っています。アイデア次第でなんでもありです。最初にカンマ区切りでトークンを取得するのですが、その間で、さらにカンマ区切りトークンの中に必ず一度現れる、スラッシュによるトークン処理を入れこんでいます。区切り文字が違うだけで全く同じ処理です。こういうプログラム記法は普通はしません。通常は、関数のようなサブプログラムにして、関数を呼び出すことで同じ処理になるように記述します。C++の場合は関数でなくても、クラスのメンバ関数にしても良い訳です。結局同じことですが…。<br />
  
1,114行: 1,124行:
  
 
MFC STL COM ATL CLIと短い略称ですが、それぞれは膨大なライブラリでして、その技術の応用についても、本当は知っていく必要がありますが、ActiveXやらDirectXやらと言い出したらきりがないほど情報技術は歴史が深いし、細かい。Webサービス、SOAP、ネットワーク、暗号化、セキュア…鬼のように沢山の既存技術がある。結構使われてる。ここで触れようとしていること自体もかなり多いけど、それでも、その中のほんの一部に過ぎない。
 
MFC STL COM ATL CLIと短い略称ですが、それぞれは膨大なライブラリでして、その技術の応用についても、本当は知っていく必要がありますが、ActiveXやらDirectXやらと言い出したらきりがないほど情報技術は歴史が深いし、細かい。Webサービス、SOAP、ネットワーク、暗号化、セキュア…鬼のように沢山の既存技術がある。結構使われてる。ここで触れようとしていること自体もかなり多いけど、それでも、その中のほんの一部に過ぎない。
 +
 +
ちなみにワイド文字とマルチバイト文字の相互変換の簡単な例については<br />
 +
[[C 日本語文字列#マルチバイト文字列、ワイド文字列の相互変換]]<br />
 +
に記述があります。ここでは、更に踏み込んだ変換について触れたいと思います。
  
 
というわけで、これくらいできて当然という変換をやってみます。
 
というわけで、これくらいできて当然という変換をやってみます。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#include <string>
 +
#include <stdlib.h>
 +
#include <iostream>
 +
#include <tchar.h>
 +
#include <mbstring.h>
 +
#include "atlstr.h"//CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "cstringt.h"//CStringTの定義プリプロセッサ
 +
#include "atlbase.h"
 +
 +
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
# ifdef _DEBUG
 +
# pragma comment(lib, "comsuppwd.lib")
 +
# else
 +
# pragma comment(lib, "comsuppw.lib")
 +
# endif
 +
 +
 +
using namespace std;
 +
using namespace System;
 +
using namespace System::Runtime::InteropServices;
 +
 +
int main() {
 +
  _tsetlocale(LC_ALL, _T("Japanese"));
 +
  _locale_t locale;
 +
  locale = _create_locale(LC_ALL, "Japanese");
 +
 +
  //プロジェクトの設定の文字セットでunicode文字セットを使用するに設定しているので、TCHAR→wchar_t型と定義される。
 +
  //プロジェクトの設定をかえるとTCHAR→char型になるので、設定によってはTCHAR型に変換する方式を切り替えないとダメ。
 +
  //実際の変換処理は#ifdef UNICODEで分けた関数を作る必要がある。
 +
 
 +
  size_t *sizeReturnValue;
 +
  sizeReturnValue = new size_t;
 +
 
 +
  const char *pcStrMoto[] ={"char型の変数 配列要素1","char型の変数 配列要素2"};
 +
  const LPSTR pLPSTRStrMoto[] = {"LPSTR型の変数 配列要素1","LPSTR型の変数 配列要素2"};
 +
  TCHAR **pptcStrCnv = new TCHAR*[sizeof(pcStrMoto)/sizeof(*pcStrMoto)];
 +
  LPTSTR *ppLPTSTRStrCnv = new TCHAR*[sizeof(pcStrMoto)/sizeof(*pcStrMoto)];
 +
 
 +
  _tprintf(_T("文字列の型変換char→TCHAR\n"));
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
 +
#ifdef UNICODE
 +
 +
  //配列要素i番目の変換後のサイズ取得処理と要素iの実体化と文字列長さ設定。
 +
  mbstowcs_s(sizeReturnValue, NULL, 0,pcStrMoto[i], 0);
 +
  pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
  ppLPTSTRStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
  //変換処理。
 +
  mbstowcs_s(sizeReturnValue, pptcStrCnv[i], *sizeReturnValue, pcStrMoto[i], *sizeReturnValue);
 +
  mbstowcs_s(sizeReturnValue, ppLPTSTRStrCnv[i], *sizeReturnValue, pcStrMoto[i], *sizeReturnValue);
 +
#else
 +
 +
  //マルチバイト定義の場合はchar型同志のコピーになるので変換不要。
 +
  pptcStrCnv[i] = new TCHAR[_tcslen(pcStrMoto[i]) + 1];
 +
  ppLPTSTRStrCnv[i] = new TCHAR[_tcslen(pcStrMoto[i]) + 1];
 +
  _tcscpy_s(pptcStrCnv[i],_tcslen(pcStrMoto[i]) + 1,pcStrMoto[i]);
 +
  _tcscpy_s(ppLPTSTRStrCnv[i],_tcslen(pcStrMoto[i]) + 1,pcStrMoto[i]);
 +
 +
#endif
 +
  //出力
 +
  _tprintf(_T("要素[%d]\n"),i);  
 +
  for(unsigned int j = 0; j < *sizeReturnValue; j++){
 +
  _tprintf(_T("[%2d]=%x,"),j,*(*(pptcStrCnv + i) + j));
 +
  }
 +
  _tprintf(_T("\n%s\n"),*(pptcStrCnv + i));
 +
  }
 +
 +
  _tprintf(_T("\n文字列の型変換TCHAR→char\n"));
 +
  const TCHAR *ptcStrMoto[] = {_T("TCHAR型の変数 配列要素1"),_T("TCHAR型の変数 配列要素2")};
 +
  const LPTSTR pLPTSTRStrMoto[] = {_T("LPTSTR型の変数 配列要素1"),_T("LPTSTR型の変数 配列要素2")};
 +
  char **ppcStrCnv = new char*[sizeof(ptcStrMoto)/sizeof(*ptcStrMoto)];
 +
  LPSTR *ppLPSTRStrCnv = new char*[sizeof(ptcStrMoto)/sizeof(*ptcStrMoto)];
 +
 +
  for(int i = 0; i < (sizeof(ptcStrMoto)/sizeof(*ptcStrMoto)); i++){
 +
 +
#ifdef UNICODE
 +
 +
  //配列要素i番目の変換後のサイズ取得処理と要素iの実体化と文字列長さ設定。
 +
  wcstombs_s(sizeReturnValue, NULL, 0,ptcStrMoto[i], 0);
 +
  ppcStrCnv[i] = new char[*sizeReturnValue];
 +
  ppLPSTRStrCnv[i] = new char[*sizeReturnValue];
 +
  //変換処理。
 +
  wcstombs_s(sizeReturnValue, ppcStrCnv[i], *sizeReturnValue, ptcStrMoto[i], *sizeReturnValue);
 +
  wcstombs_s(sizeReturnValue, ppLPSTRStrCnv[i], *sizeReturnValue, ptcStrMoto[i], *sizeReturnValue);
 +
#else
 +
 +
  //マルチバイト定義の場合はchar型同志のコピーになるので変換不要。
 +
  ppcStrCnv[i] = new TCHAR[_tcslen(ptcStrMoto[i]) + 1];
 +
  ppLPSTRStrCnv[i] = new TCHAR[_tcslen(ptcStrMoto[i]) + 1];
 +
  _tcscpy_s(ppcStrCnv[i],_tcslen(ptcStrMoto[i]) + 1,ptcStrMoto[i]);
 +
  _tcscpy_s(ppLPSTRStrCnv[i],_tcslen(ptcStrMoto[i]) + 1,ptcStrMoto[i]);
 +
 +
#endif
 +
  //出力
 +
  _tprintf(_T("要素[%d]\n"),i);  
 +
  for(unsigned int j = 0; j < *sizeReturnValue; j++){
 +
  printf("[%2d]=%x,",j,*(*(ppcStrCnv + i) + j));
 +
  printf("[%2d]=%x,",j,*(*(ppLPSTRStrCnv + i) + j));
 +
  }
 +
  printf("\n%s\n",*(ppcStrCnv + i));
 +
  printf("%s\n",*(ppLPSTRStrCnv + i));
 +
  }
 +
 +
  //_bstr_t,CComBSTR,CString,System::Stringいずれもcharの先頭アドレスを代入すれば格納できる。
 +
  _tprintf(_T("\n文字列の型変換char→_bstr_t\n"));
 +
  _bstr_t bstrt[(sizeof(pcStrMoto)/sizeof(*pcStrMoto))];
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
bstrt[i] = pcStrMoto[i];//代入するだけ
 +
std::cout << bstrt[i] << std::endl;
 +
printf("_bstr_t %s\n",(LPCSTR)bstrt[i]);
 +
  }
 +
 +
  _tprintf(_T("\n文字列の型変換char→CComBSTR\n"));
 +
  CComBSTR ccombstr[(sizeof(pcStrMoto)/sizeof(*pcStrMoto))];
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
ccombstr[i] = pcStrMoto[i];//代入するだけ
 +
//マクロにより出力用の変数に文字列を移す必要がある。これはCComBSTR型の決まり。
 +
CW2A printstr(ccombstr[i]);
 +
std::cout << printstr << std::endl;
 +
printf("CComBSTR %s\n",printstr);
 +
  }
 +
 +
  _tprintf(_T("\n文字列の型変換char→CStringA\n"));
 +
  CStringA cstringa[(sizeof(pcStrMoto)/sizeof(*pcStrMoto))];
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
cstringa[i] = pcStrMoto[i];//代入するだけ
 +
std::cout << cstringa[i] << std::endl;
 +
printf("CStringA %s\n",cstringa[i]);
 +
  }
 +
 +
  _tprintf(_T("\n文字列の型変換char→CStringW\n"));
 +
  CStringW cstringw[(sizeof(pcStrMoto)/sizeof(*pcStrMoto))];
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
cstringw[i] = pcStrMoto[i];//代入するだけ
 +
std::wcout << (LPCTSTR)cstringw[i] << std::endl;
 +
_tprintf(_T("CStringW %s\n"),(LPCTSTR)cstringw[i]);
 +
  }
 +
 +
  _tprintf(_T("\n文字列の型変換char→string\n"));
 +
  string basicstring[(sizeof(pcStrMoto)/sizeof(*pcStrMoto))];
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
basicstring[i] = pcStrMoto[i];//代入するだけ
 +
cout << basicstring[i] << endl;
 +
printf("string %s\n",basicstring[i].c_str());
 +
  }
 +
 +
  _tprintf(_T("\n文字列の型変換char→SystemString\n"));
 +
 
 +
  array<String^> ^systemstring = gcnew array<String^>(sizeof(pcStrMoto)/sizeof(*pcStrMoto));
 +
  for(int i = 0; i < (sizeof(pcStrMoto)/sizeof(*pcStrMoto)); i++){
 +
char* pcStrTemp = new char[strlen(pcStrMoto[i]) + 1];
 +
strcpy_s(pcStrTemp,strlen(pcStrMoto[i]) + 1,pcStrMoto[i]);
 +
System::IntPtr ptr(pcStrTemp);//この関数がconst charの変換に対応していないので、上の2行でconst無しの変数に移し替えた。
 +
systemstring[i] = Marshal::PtrToStringAnsi(ptr);//IntPtrポインタを引数として変換するメソッド。
 +
Console::WriteLine("{0}", systemstring[i]);
 +
delete[] pcStrTemp;
 +
  }
 +
}
 +
</syntaxhighlight2>
 +
上から<br />
 +
char(LPSTR)→TCHAR(LPTSTR)<br />
 +
TCHAR(LPTSTR)→char(LPSTR)<br />
 +
の変換ここでは#ifndef UNICODEディレクティブによりTCHARの扱いをプロジェクトでどのように定義したか?によって動作が切り替わるように処理を組み込んでいます。以前に記述したサンプル[[C 日本語文字列#マルチバイト文字列、ワイド文字列の相互変換]]では、そこまでは言及していませんでした。プロジェクトの設定の文字セットでunicode文字セットを使用するに設定していれば、上側の#ifndef UNICODEから#elseまでに囲まれた部分が処理される。変換が必要かどうか?確認するのがよいです。<br />
 +
その次に<br />
 +
charから_bstr_tやCComBSTRやCStringA、CStringWのような変換について記述しています。このあたりの変数はchar型のポインタを代入するだけで変換をしてくれます。但し、出力するときには少し工夫が必要になります。これはどちらかというと、独自の文字列クラスの仕様によるものなので、それぞれの文字クラスについて学習を進める必要があります。先に示したリンクからそれぞれのクラスについて学習してみて下さい。こちらのサイトでもいつかは触れていきたいですが、まだまだ先になりそうです。<br />
 +
それから、<br />
 +
charからstring、System::Stringへの変換について記述しています。<br />
 +
System::Stringは共通言語ランタイムですので、動作させるにはプロジェクトの設定を変更しないといけません。<br />
 +
しかも、設定を変更しても従来のC言語の記法と共通言語ランタイムの記法を混同させるとVisual C++のコードインテリジェンス機能が完全停止しますのでコード編集が大変になりますので、このサンプルのような混同したプリプロセッサ定義をして無理やり、いろいろな変換のサンプルを記述するのは良くないです。
 +
 +
[[file:IntelliSenseOff.png]]
 +
 +
上記の図のようなエラーになります。共通言語ランタイムとプリプロセッサの混同に関する詳細な条件もまた後程調査ですかね。ほんとに調べるのかは定かでありませんが…
 +
 +
※コードインテリセンスは、例えばにstrcpyのようなよく使う関数を使うときに引数には何を定義すればよいのか、ヒントを与える機能です strcpy( までタイプすると第一引数には char* 型のコピー先の変数、第二引数にはコピー元のchar* 型の変数、第三引数にはコピーする文字の配列の長さを指定するべきだとポップアップ表示がされます。クラス変数や構造体変数を使う場合にも 変数名. あるいは変数名-> までタイプするとメンバ変数や、メソッドのリストが表示されます。メソッドの引数のヒントも関数と同様にポップアップ表示されます。
 +
 +
複数の文字列プリプロセッサを混同しないのが本来のやりかたになります。System::Stringへのchar変数の代入だけは複数の処理ステップが必要になります。System::String用に準備されているメソッドがconst char*の引数に対応していなかったり、独自の仕組みでしか引数をとることができないからです。ちなみに、文字列の配列でなければ、もう少し簡単に変換ができて、<br />
 +
System::String ^systemstring = gcnew String(char*型変数);<br />
 +
のように記述するだけで、コンストラクタの初期値によって変換自体は完了させることができます。と、ここまでchar型からの変換だけで、ずいぶんと長い説明になってしまいました。このあたりの配列を使った場合の文字列変換についてまとめている文書は意外と少ないと思います。次は逆変換ですかね。こっちのほうが大変なんだよね。そしたら次はTCHARからの変換か…で、その逆変換。ふむー。先は長い。普段こんなに変換ばっかりやんないので、この記事キツイっすね。なんでこんなん書いてるんやろ。役に立つんか?ほんまに…
 +
 +
マネージコードを利用するために実施した設定変更<br />
 +
C/C++ <br />
 +
全般<br />
 +
 デバッグ情報の形式      プログラムデータベース /Zi ← エディットコンティニュのプログラムデータベース /ZI<br />
 +
 共通言語ランタイム サポート 共通言語ランタイムサポート /clr ←共通言語ランタイムをサポートしない<br />
 +
コード生成<br />
 +
 最小リビルドを有効にする。 いいえ /Gm-  ←はい /Gm<br />
 +
 C++の例外を有効にする    はい SEHの例外あり /EHa ← はい /EHsc<br />
 +
 基本ランタイムチェック   規定 ← 両方 /RTC1<br />
 +
 +
VisualStudioのコードインテリセンスを有効にしたままC++とC++/CLI(共通言語)の勉強したい場合は、C++/CLIプロジェクトでもC++言語は使えるので、プロジェクトの作成からやりなおしてみると良いです。
 +
 +
 +
更に変換を続けたのものが以下になります。
 +
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
_tsetlocale(LC_ALL, _T("Japanese"));
 +
_locale_t locale;
 +
locale = _create_locale(LC_ALL, "Japanese");
 +
 +
const char *pcStrMoto[] ={"char型の変数 配列要素1","char型の変数 配列要素2"};
 +
const LPSTR pLPSTRStrMoto[] = {"LPSTR型の変数 配列要素1","LPSTR型の変数 配列要素2"};
 +
 +
const TCHAR *ptcStrMoto[] = {_T("TCHAR型の変数 要素1"),_T("TCHAR型の変数 要素2")};
 +
const LPTSTR pLPTSTRStrMoto[] = {_T("LPTSTR型の変数 要素1"),_T("LPTSTR型の変数 要素2")};
 +
 +
size_t *sizeReturnValue;
 +
sizeReturnValue = new size_t;
 +
 +
int *pnStrArrayElement;
 +
pnStrArrayElement = new int;
 +
 +
*pnStrArrayElement = sizeof(ptcStrMoto)/sizeof(*ptcStrMoto);
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・TCHAR→char変換
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("文字列の型変換TCHAR→char\n"));
 +
 +
char **ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
LPSTR *ppLPSTRStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
#ifdef UNICODE
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
wcstombs_s(sizeReturnValue, NULL, 0,ptcStrMoto[i], 0);
 +
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
ppLPSTRStrCnv[i] = new char[*sizeReturnValue];
 +
 +
wcstombs_s(sizeReturnValue, ppcStrCnv[i], *sizeReturnValue, ptcStrMoto[i], *sizeReturnValue);
 +
wcstombs_s(sizeReturnValue, ppLPSTRStrCnv[i], *sizeReturnValue, ptcStrMoto[i], *sizeReturnValue);
 +
 +
}
 +
#else
 +
//無変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
ppLPSTRStrCnv[i] = new char[*sizeReturnValue];
 +
 +
_tcscpy_s(ppcStrCnv[i], _tcslen(ptcStrMoto[i]) + 1, ptcStrMoto[i]);
 +
_tcscpy_s(ppLPSTRStrCnv[i], _tcslen(ptcStrMoto[i]) + 1, ptcStrMoto[i]);
 +
 +
}
 +
#endif
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
//LPSTR出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppLPSTRStrCnv + i));
 +
}
 +
 +
printf("%d\n", sizeof(**ppcStrCnv));
 +
printf("%d\n", sizeof(*ppcStrCnv));
 +
printf("%d\n", sizeof(ppcStrCnv));//動的に確保した配列の大きさは取得できない。
 +
 +
printf("%d\n", sizeof(**ptcStrMoto));
 +
printf("%d\n", sizeof(*ptcStrMoto));
 +
printf("%d\n", sizeof(ptcStrMoto));
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
delete[] *(ppLPSTRStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
delete[] ppLPSTRStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→char
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→char\n"));
 +
 +
const _bstr_t bstrtOrigin[] = {_T("_bstr_t型の変数 配列要素1"),_T("_bstr_t型の変数 配列要素2"),_T("_bstr_t型の変数 配列要素3")};
 +
 +
printf("%d\n", sizeof(*bstrtOrigin));
 +
printf("%d\n", sizeof(bstrtOrigin));
 +
 +
*pnStrArrayElement = sizeof(bstrtOrigin)/sizeof(*bstrtOrigin);
 +
 +
ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
*sizeReturnValue = strlen((char*)bstrtOrigin[i]) + 1;
 +
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
 +
strcpy_s(ppcStrCnv[i], *sizeReturnValue, (char*)bstrtOrigin[i]);
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→TCHAR
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→TCHAR\n"));
 +
 +
TCHAR **pptcStrCnv = new TCHAR*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
*sizeReturnValue = _tcslen((TCHAR*)bstrtOrigin[i]) + 1;
 +
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, (TCHAR*)bstrtOrigin[i]);
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
_tprintf(_T("%s\n"),*(pptcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(pptcStrCnv + i);
 +
}
 +
delete[] pptcStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→CComBSTR(マルチバイト文字ワイド文字両対応 プロジェクト設定に従う)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→CComBSTR\n"));
 +
 +
CComBSTR *pccombstr_StrCnv = new CComBSTR[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pccombstr_StrCnv[i] = (char*)bstrtOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
CW2A printstr(*(pccombstr_StrCnv + i));
 +
printf("%s\n",printstr);
 +
//無変換出力
 +
_tprintf(_T("%s\n"),*(pccombstr_StrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pccombstr_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→CStringA(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→CStringA\n"));
 +
 +
CStringA *pcstringa_StrCnv = new CStringA[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringa_StrCnv[i] = (char*)bstrtOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pcstringa_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringa_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→CStringW(ワイド文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→CStringW\n"));
 +
 +
CStringW *pcstringw_StrCnv = new CStringW[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringw_StrCnv[i] = (char*)bstrtOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//wchar_t出力
 +
wprintf(L"%s\n",pcstringw_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringw_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→string(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→string\n"));
 +
 +
string *pstring_StrCnv = new string[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pstring_StrCnv[i] = (char*)bstrtOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pstring_StrCnv[i].c_str());
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pstring_StrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・_bstr_t→SystemString(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→SystemString\n"));
 +
 +
array<String^> ^psysstring_StrCnv = gcnew array<String^>(*pnStrArrayElement);
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
char* pcStrTemp = new char[strlen((char*)bstrtOrigin[i]) + 1];
 +
strcpy_s(pcStrTemp,strlen((char*)bstrtOrigin[i]) + 1,(char*)bstrtOrigin[i]);
 +
 +
System::IntPtr ptr(pcStrTemp);
 +
psysstring_StrCnv[i] = Marshal::PtrToStringAnsi(ptr);
 +
delete[] pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",psysstring_StrCnv[i]);
 +
//TCHAR変換出力
 +
#ifdef UNICODE
 +
_tprintf(_T("%s\n"),PtrToStringChars(psysstring_StrCnv[i]));
 +
#else
 +
_tprintf(_T("%s\n"),psysstring_StrCnv[i]);
 +
#endif
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] psysstring_StrCnv;
 +
 +
 +
 +
delete[] sizeReturnValue;
 +
delete[] pnStrArrayElement;
 +
</syntaxhighlight2>
 +
 +
_bstr_t型からの変換に関するサンプルを追加しました。
 +
 +
型変換とは関係ない部分になりますが、配列のサイズ確保処理について補足しておきますと、文字列配列の大きさは動的に生成した文字列配列からは取得することはできません。動的に生成したときの大きさをプログラマ自身が管理する必要があります。そのことを知ることができるのが上記の64行目のprintf文です。ここで動的に生成した文字列配列の大きさをsizeof関数で表示していますが、配列の大きさは32bitアプリならば、要素数2つなので4byte*2[配列要素数]=8byte(4byte=32bitでひとつのアドレス ※8bit=1byte)になるはずですが、4byteになっています。これはポインタ変数の大きさ、アドレス記憶変数ひとつ分の大きさになっていて、実際の配列サイズが返ってこないことが確認できます。
 +
 +
話は戻って…
 +
 +
上記のように変換を進めていて気づくことですが、それぞれの型は取り扱える文字コード長が異なります。_bstr_tやCComBSTRはマルチバイト文字とワイド文字の両方に対応していて、プロジェクト設定にしたがって記憶する文字型を切り替えています。CStringAはマルチバイト文字、CStringWはワイド文字です。stringとSystem::Stringはマルチバイト文字を扱うようになっています。したがって、変換時にはマルチバイト文字、ワイド文字変換が必要になるケースと必要ないケース。あるいは、プロジェクトの設定によって決まるケースがあるわけです。そのことから、_bstr_tやCComBSTを利用しておくという、ある程度、文字列の世界を熟知している人だけが選ぶ道があるようにも思えるわけです。マイクロソフトの用意したものを使うにしても賢い選択というのが、その時代、時代によって存在することになります。
 +
 +
開発するプログラムの枠組みによってはマルチバイトやワイド文字といった切り替えは気にしないという人もいるのかもしれません。具体的にどのように変換処理を記述するかについても、そのときそのときで違ってくることもあるのかもしれませんね。
 +
 +
変換の種類がたくさんありますが、wchar_tとcharの変換をおぼえれば、それぞれの特殊な型をchar型に変換する手法とcharからそれぞれの型に変換する手法をマスターすれば、変換手順は長くなる可能性があるものの、とにかくすべてを網羅できるわけです。特殊な型から特殊な型へのダイレクトな変換は覚えなくてもなんとかなる。覚えた方が楽になる。そんな感じです。それぞれの人の考え方にあわせて、覚える量を調節すれば済む話です。
 +
 +
マイクロソフトの説明書にも簡単な変換に関する文書があります。
 +
http://msdn.microsoft.com/ja-jp/library/ms235631(v=vs.110).aspx
 +
 +
ここに記述している内容とさほど差はありません。わかりやすい方を参考にしてみて下さい。
 +
 +
では引き続き、変換のサンプルを…
 +
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→char
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→char\n"));
 +
 +
const CComBSTR ccombstrOrigin[] = {_T("CComBSTR型の変数 配列要素1"),_T("CComBSTR型の変数 配列要素2"),_T("CComBSTR型の変数 配列要素3")};
 +
 +
printf("%d\n", sizeof(*ccombstrOrigin));
 +
printf("%d\n", sizeof(ccombstrOrigin));
 +
 +
*pnStrArrayElement = sizeof(ccombstrOrigin)/sizeof(*ccombstrOrigin);
 +
 +
ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
*sizeReturnValue = strlen(strtemp) + 1;
 +
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
 +
strcpy_s(ppcStrCnv[i], *sizeReturnValue, strtemp);
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→TCHAR
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→TCHAR\n"));
 +
 +
pptcStrCnv = new TCHAR*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
#ifdef UNICODE
 +
*sizeReturnValue = _tcslen(ccombstrOrigin[i]) + 1;
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, ccombstrOrigin[i]);
 +
#else
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
*sizeReturnValue = strlen(strtemp) + 1;
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, strtemp);
 +
#endif
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
_tprintf(_T("%s\n"),*(pptcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(pptcStrCnv + i);
 +
}
 +
delete[] pptcStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→_bstr_t(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換_bstr_t→CComBSTR\n"));
 +
 +
_bstr_t *pbstrt_StrCnv = new _bstr_t[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
pbstrt_StrCnv[i] = strtemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//無変換出力
 +
printf("%s\n",(char*)pbstrt_StrCnv[i]);
 +
_tprintf(_T("%s\n"),(wchar_t*)pbstrt_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pbstrt_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→CStringA(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→CStringA\n"));
 +
 +
pcstringa_StrCnv = new CStringA[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
pcstringa_StrCnv[i] = strtemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pcstringa_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringa_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→CStringW(ワイド文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→CStringW\n"));
 +
 +
pcstringw_StrCnv = new CStringW[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
pcstringw_StrCnv[i] = strtemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//wchar_t出力
 +
wprintf(L"%s\n",pcstringw_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringw_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→string(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→string\n"));
 +
 +
pstring_StrCnv = new string[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
pstring_StrCnv[i] = strtemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pstring_StrCnv[i].c_str());
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pstring_StrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→SystemString(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→SystemString\n"));
 +
 +
psysstring_StrCnv = gcnew array<String^>(*pnStrArrayElement);
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
 +
System::IntPtr ptr(strtemp);
 +
psysstring_StrCnv[i] = Marshal::PtrToStringAnsi(ptr);
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",psysstring_StrCnv[i]);
 +
//TCHAR変換出力
 +
#ifdef UNICODE
 +
_tprintf(_T("%s\n"),PtrToStringChars(psysstring_StrCnv[i]));
 +
#else
 +
_tprintf(_T("%s\n"),psysstring_StrCnv[i]);
 +
#endif
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] psysstring_StrCnv;
 +
</syntaxhighlight2>
 +
 +
引き続き、変換のサンプルを記述していきます。残るはCComBSTR、CStringA、CStringW、string、System::String基準の変換ですね。
 +
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→char
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→char\n"));
 +
 +
const CStringA cstringaOrigin[] = {_T("CStringA型の変数 配列要素1"),_T("CStringA型の変数 配列要素2"),_T("CStringA型の変数 配列要素3")};
 +
 +
printf("%d\n", sizeof(*cstringaOrigin));
 +
printf("%d\n", sizeof(cstringaOrigin));
 +
 +
*pnStrArrayElement = sizeof(cstringaOrigin)/sizeof(*cstringaOrigin);
 +
 +
ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
*sizeReturnValue = strlen(cstringaOrigin[i]) + 1;
 +
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
 +
strcpy_s(ppcStrCnv[i], *sizeReturnValue, cstringaOrigin[i]);
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→TCHAR
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→TCHAR\n"));
 +
 +
pptcStrCnv = new TCHAR*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
#ifdef UNICODE
 +
mbstowcs_s(sizeReturnValue, NULL, 0,cstringaOrigin[i], 0);
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
mbstowcs_s(sizeReturnValue, pptcStrCnv[i], *sizeReturnValue,cstringaOrigin[i], *sizeReturnValue);
 +
#else
 +
*sizeReturnValue = strlen(cstringaOrigin[i]) + 1;
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, cstringaOrigin[i]);
 +
#endif
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
_tprintf(_T("%s\n"),*(pptcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(pptcStrCnv + i);
 +
}
 +
delete[] pptcStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→_bstr_t(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→CComBSTR\n"));
 +
 +
pbstrt_StrCnv = new _bstr_t[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pbstrt_StrCnv[i] = cstringaOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//無変換出力
 +
printf("%s\n",(char*)pbstrt_StrCnv[i]);
 +
_tprintf(_T("%s\n"),(wchar_t*)pbstrt_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pbstrt_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CComBSTR→CStringA(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CComBSTR→CStringA\n"));
 +
 +
pcstringa_StrCnv = new CStringA[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
CW2A strtemp(ccombstrOrigin[i]);
 +
pcstringa_StrCnv[i] = strtemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pcstringa_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringa_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→CStringW(ワイド文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→CStringW\n"));
 +
 +
pcstringw_StrCnv = new CStringW[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringw_StrCnv[i] = cstringaOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//wchar_t出力
 +
wprintf(L"%s\n",pcstringw_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringw_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→string(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→string\n"));
 +
 +
pstring_StrCnv = new string[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pstring_StrCnv[i] = cstringaOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pstring_StrCnv[i].c_str());
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pstring_StrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→SystemString(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→SystemString\n"));
 +
 +
psysstring_StrCnv = gcnew array<String^>(*pnStrArrayElement);
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
char* pcStrTemp = new char[strlen(cstringaOrigin[i]) + 1];
 +
strcpy_s(pcStrTemp,strlen(cstringaOrigin[i]) + 1,cstringaOrigin[i]);
 +
System::IntPtr ptr(pcStrTemp);
 +
psysstring_StrCnv[i] = Marshal::PtrToStringAnsi(ptr);
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",psysstring_StrCnv[i]);
 +
//TCHAR変換出力
 +
#ifdef UNICODE
 +
_tprintf(_T("%s\n"),PtrToStringChars(psysstring_StrCnv[i]));
 +
#else
 +
_tprintf(_T("%s\n"),psysstring_StrCnv[i]);
 +
#endif
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] psysstring_StrCnv;
 +
</syntaxhighlight2>
 +
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringW→char
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringW→char\n"));
 +
 +
const CStringW cstringwOrigin[] = {_T("CStringW型の変数 配列要素1"),_T("CStringW型の変数 配列要素2"),_T("CStringW型の変数 配列要素3")};
 +
 +
printf("%d\n", sizeof(*cstringwOrigin));
 +
printf("%d\n", sizeof(cstringwOrigin));
 +
 +
*pnStrArrayElement = sizeof(cstringwOrigin)/sizeof(*cstringwOrigin);
 +
 +
ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
wcstombs_s(sizeReturnValue, NULL, 0,cstringwOrigin[i], 0);
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, ppcStrCnv[i], *sizeReturnValue,cstringwOrigin[i], *sizeReturnValue);
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringW→TCHAR
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringW→TCHAR\n"));
 +
 +
pptcStrCnv = new TCHAR*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
#ifdef UNICODE
 +
*sizeReturnValue = _tcslen(cstringwOrigin[i]) + 1;
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, cstringwOrigin[i]);
 +
#else
 +
wcstombs_s(sizeReturnValue, NULL, 0,cstringwOrigin[i], 0);
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, ppcStrCnv[i], *sizeReturnValue,cstringwOrigin[i], *sizeReturnValue);
 +
#endif
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
_tprintf(_T("%s\n"),*(pptcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(pptcStrCnv + i);
 +
}
 +
delete[] pptcStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringW→_bstr_t(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→CComBSTR\n"));
 +
 +
pbstrt_StrCnv = new _bstr_t[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pbstrt_StrCnv[i] = cstringwOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//無変換出力
 +
printf("%s\n",(char*)pbstrt_StrCnv[i]);
 +
_tprintf(_T("%s\n"),(wchar_t*)pbstrt_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pbstrt_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringW→CStringA(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringW→CStringA\n"));
 +
 +
pcstringa_StrCnv = new CStringA[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringa_StrCnv[i] = cstringwOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pcstringa_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringa_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringA→CStringW(ワイド文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringA→CStringW\n"));
 +
 +
pcstringw_StrCnv = new CStringW[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringw_StrCnv[i] = cstringaOrigin[i];
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//wchar_t出力
 +
wprintf(L"%s\n",pcstringw_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringw_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringW→string(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringW→string\n"));
 +
 +
pstring_StrCnv = new string[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
wcstombs_s(sizeReturnValue, NULL, 0,cstringwOrigin[i], 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue,cstringwOrigin[i], *sizeReturnValue);
 +
pstring_StrCnv[i] = pcStrTemp;
 +
delete[] pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pstring_StrCnv[i].c_str());
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pstring_StrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・CStringW→SystemString(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換CStringW→SystemString\n"));
 +
 +
psysstring_StrCnv = gcnew array<String^>(*pnStrArrayElement);
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
wcstombs_s(sizeReturnValue, NULL, 0,cstringwOrigin[i], 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue,cstringwOrigin[i], *sizeReturnValue);
 +
System::IntPtr ptr(pcStrTemp);
 +
psysstring_StrCnv[i] = Marshal::PtrToStringAnsi(ptr);
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",psysstring_StrCnv[i]);
 +
//TCHAR変換出力
 +
#ifdef UNICODE
 +
_tprintf(_T("%s\n"),PtrToStringChars(psysstring_StrCnv[i]));
 +
#else
 +
_tprintf(_T("%s\n"),psysstring_StrCnv[i]);
 +
#endif
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] psysstring_StrCnv;
 +
</syntaxhighlight2>
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→char
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→char\n"));
 +
 +
const string stringOrigin[] = {"string型の変数 配列要素1","string型の変数 配列要素2","string型の変数 配列要素3"};
 +
 +
printf("%d\n", sizeof(*stringOrigin));
 +
printf("%d\n", sizeof(stringOrigin));
 +
 +
*pnStrArrayElement = sizeof(stringOrigin)/sizeof(*stringOrigin);
 +
 +
ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
*sizeReturnValue = strlen(stringOrigin[i].c_str()) + 1;
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
strcpy_s(ppcStrCnv[i], *sizeReturnValue, stringOrigin[i].c_str());
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→TCHAR
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→TCHAR\n"));
 +
 +
pptcStrCnv = new TCHAR*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
#ifdef UNICODE
 +
mbstowcs_s(sizeReturnValue, NULL, 0,stringOrigin[i].c_str(), 0);
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
mbstowcs_s(sizeReturnValue, pptcStrCnv[i], *sizeReturnValue,stringOrigin[i].c_str(), *sizeReturnValue);
 +
#else
 +
*sizeReturnValue = strlen(stringOrigin[i].c_str()) + 1;
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, stringOrigin[i].c_str());
 +
#endif
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
_tprintf(_T("%s\n"),*(pptcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(pptcStrCnv + i);
 +
}
 +
delete[] pptcStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→_bstr_t(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→_bstr_t\n"));
 +
 +
pbstrt_StrCnv = new _bstr_t[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pbstrt_StrCnv[i] = stringOrigin[i].c_str();
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//無変換出力
 +
printf("%s\n",(char*)pbstrt_StrCnv[i]);
 +
_tprintf(_T("%s\n"),(wchar_t*)pbstrt_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pbstrt_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→CComBSTR(マルチバイト文字ワイド文字両対応 プロジェクト設定に従う)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→CComBSTR\n"));
 +
 +
pccombstr_StrCnv = new CComBSTR[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pccombstr_StrCnv[i] = stringOrigin[i].c_str();
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
CW2A printstr(*(pccombstr_StrCnv + i));
 +
printf("%s\n",printstr);
 +
//無変換出力
 +
_tprintf(_T("%s\n"),*(pccombstr_StrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pccombstr_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→CStringA(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→CStringA\n"));
 +
 +
pcstringa_StrCnv = new CStringA[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringa_StrCnv[i] = stringOrigin[i].c_str();
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pcstringa_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringa_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→CStringW(ワイド文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→CStringW\n"));
 +
 +
pcstringw_StrCnv = new CStringW[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pcstringw_StrCnv[i] = stringOrigin[i].c_str();
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//wchar_t出力
 +
wprintf(L"%s\n",pcstringw_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringw_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・string→SystemString(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→SystemString\n"));
 +
 +
psysstring_StrCnv = gcnew array<String^>(*pnStrArrayElement);
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
char* pcStrTemp = new char[strlen(stringOrigin[i].c_str()) + 1];
 +
strcpy_s(pcStrTemp,strlen(stringOrigin[i].c_str()) + 1,stringOrigin[i].c_str());
 +
System::IntPtr ptr(pcStrTemp);
 +
psysstring_StrCnv[i] = Marshal::PtrToStringAnsi(ptr);
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",psysstring_StrCnv[i]);
 +
//TCHAR変換出力
 +
#ifdef UNICODE
 +
_tprintf(_T("%s\n"),PtrToStringChars(psysstring_StrCnv[i]));
 +
#else
 +
_tprintf(_T("%s\n"),psysstring_StrCnv[i]);
 +
#endif
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] psysstring_StrCnv;
 +
</syntaxhighlight2>
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→char
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換string→char\n"));
 +
 +
array<String^> ^sysstringOrigin = gcnew array<String^>{"SystemString型の変数 配列要素1","SystemString型の変数 配列要素2","SystemString型の変数 配列要素3"};
 +
 +
printf("%d\n", sysstringOrigin->Length);
 +
 +
*pnStrArrayElement = sysstringOrigin->Length;
 +
 +
ppcStrCnv = new char*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
ppcStrCnv[i] = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, ppcStrCnv[i], *sizeReturnValue, wch, *sizeReturnValue);
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
printf("%s\n",*(ppcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(ppcStrCnv + i);
 +
}
 +
delete[] ppcStrCnv;
 +
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→TCHAR
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換SystemString→TCHAR\n"));
 +
 +
pptcStrCnv = new TCHAR*[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
 +
#ifdef UNICODE
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
*sizeReturnValue = _tcslen(wch) + 1;
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
_tcscpy_s(pptcStrCnv[i], *sizeReturnValue, wch);
 +
#else
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
pptcStrCnv[i] = new TCHAR[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pptcStrCnv[i], *sizeReturnValue, wch, *sizeReturnValue);
 +
#endif
 +
}
 +
 +
//char出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
_tprintf(_T("%s\n"),*(pptcStrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
for(int i = 0;i < *pnStrArrayElement ;i++){
 +
delete[] *(pptcStrCnv + i);
 +
}
 +
delete[] pptcStrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→_bstr_t(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換SystemString→_bstr_t\n"));
 +
 +
pbstrt_StrCnv = new _bstr_t[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue, wch, *sizeReturnValue);
 +
pbstrt_StrCnv[i] = pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//無変換出力
 +
printf("%s\n",(char*)pbstrt_StrCnv[i]);
 +
_tprintf(_T("%s\n"),(wchar_t*)pbstrt_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pbstrt_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→CComBSTR(マルチバイト文字ワイド文字両対応 プロジェクト設定に従う)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換SystemString→CComBSTR\n"));
 +
 +
pccombstr_StrCnv = new CComBSTR[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue, wch, *sizeReturnValue);
 +
pccombstr_StrCnv[i] = pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
CW2A printstr(*(pccombstr_StrCnv + i));
 +
printf("%s\n",printstr);
 +
//無変換出力
 +
_tprintf(_T("%s\n"),*(pccombstr_StrCnv + i));
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pccombstr_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→CStringA(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換SystemString→CStringA\n"));
 +
 +
pcstringa_StrCnv = new CStringA[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue, wch, *sizeReturnValue);
 +
pcstringa_StrCnv[i] = pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pcstringa_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringa_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→CStringW(ワイド文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換SystemString→CStringW\n"));
 +
 +
pcstringw_StrCnv = new CStringW[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue, wch, *sizeReturnValue);
 +
pcstringw_StrCnv[i] = pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//wchar_t出力
 +
wprintf(L"%s\n",pcstringw_StrCnv[i]);
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pcstringw_StrCnv;
 +
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
//・SystemString→string(マルチバイト文字)
 +
//★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
_tprintf(_T("\n文字列の型変換SystemString→string\n"));
 +
 +
pstring_StrCnv = new string[*pnStrArrayElement];//要素数分の大きさ+1を確保
 +
 +
//変換
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
pin_ptr<const wchar_t> wch = PtrToStringChars(sysstringOrigin[i]);
 +
wcstombs_s(sizeReturnValue, NULL, 0,wch, 0);
 +
char* pcStrTemp = new char[*sizeReturnValue];
 +
wcstombs_s(sizeReturnValue, pcStrTemp, *sizeReturnValue, wch, *sizeReturnValue);
 +
pstring_StrCnv[i] = pcStrTemp;
 +
}
 +
 +
//出力
 +
for(int i = 0; i < *pnStrArrayElement; i++){
 +
//char変換出力
 +
printf("%s\n",pstring_StrCnv[i].c_str());
 +
}
 +
 +
//動的確保変数の解放
 +
delete[] pstring_StrCnv;
 +
</syntaxhighlight2>
 +
 +
と、こんな感じです。もっと効率の良い変換があったらごめんなさい。動的に必要最小限のメモリを確保させながらの処理だとこんな感じになるよっていう例になっていると思います。プログラムによっては、配列の大きさを固定したっていいわけです。その方がコーディングや変数管理が楽になる場合もあります。この章に関しては以上です。既に準備されている型の変換なんてのは、変換するための関数が準備されているので、比較的簡単な技術になります。全角半角変換や文字コード変換処理を実際に組む方が難しいかもしれません。それもおいおい記述したいと思います。
 +
 +
※2014/09/21 ここまでで、疲れたから、また暫くオヤスミ。次に気が向くのはいつになるのか、誰も知らない。
  
 
=='''文字列文字コード変換'''==
 
=='''文字列文字コード変換'''==
 +
文字コード変換は、標準関数だけでは実現できない変換になっています。自分で変換関数を作るのもありですが、既にきちんと作られた変換ライブラリが無償で配布されています。変換処理自体を作成するには、文字コードの体系の理解やエンコーディングの理解が必要です。そして、それに対応する変換処理を作るわけです。ShiftJIS CP932とUnicode UTF-16はマルチバイトとワイド文字の変換によって実現できますので、UTF-8やEUCあるいはJISといった変換には変換処理の作成が必要になってきます。更に同じUnicodeでもUTF-16やUTF-32ではリトルエンディアン方式、ビッグエンディアン方式さらにはBOM(ByteOrderMark)の付加といった変換を考慮する必要もあります。UTF-16やUTF-32では常に複数Byteで一文字が表現され、その複数バイト塊のメモリアドレスの番地の小さい方から文字コードの上位バイトの情報をいれるビッグエンディアンと番地の小さい方に下位バイトの情報をいれていくリトルエンディアンがあり、その文字コードファイルの先頭2ByteにBOMという符号で、どっちの方式が使われているのかを示すものです。先頭アドレスからFF FE と格納されていればビッグエンディアン、FE FF と格納されていればリトルエンディアンであることを示します。あえてBOMを付与しないで、プログラムがどっちの文字コードが使われているか解析する方法や文書を閲覧する都度、ユーザが選択する方法もあります。UTF-8では、複数バイト使われるときには徐々にバイト数が大きくなる可変長の方式をとっていて、リトルエンディアンとかビッグエンディアンという概念がないため、BOMは不要ですが、付与するパターンもゆるされており、BOMありで統一してテキストを作成している人もいることから無意味なBOM付きファイルも存在します。また、このBOMが原因でファイルの読み取りに失敗してしまうUTF-8採用のプログラムも多いようです。どっちのファイルも読み取れるプログラムを作るのが良いですが、BOMありでは動作しないものと割りきって、BOM付きUTF-8を切り捨てていくプログラム作成者もいるように思います。こうすることでBOM付きUTF-8を撲滅することになっているのかもしれません。自分もUTF-8にはBOMは不要だと感じています。あえてBOMを付けれる出力のサポートも必要だと思うし、読み取れるようにもしときたいものですね。そんなプログラム作ったことないですけど…。
 +
 +
 +
ちなみにVisualStudioのコード編集エディタはデフォルトでは、ShiftJIS CP932が利用されます。変更するには、メニューのファイル(F)-保存オプションの詳細設定のエンコード欄の値を変えることで実現できます。行の終わり欄で改行コードも変更できます。特別にテキストの中で特定の文字コードセットのリテラルを使う必要がある以外は基本はShiftJIS CP932でいいのではないでしょうか?L""リテラルでUnicodeも使えますし。
 +
 +
 +
こういった文字コードの変換は、自分のプログラムだけで動作するのではなく、外部におかれた情報を読み込む、あるいは書き換えるといった動作をする場合に必要になってきます。固定の外部ファイルとのやりとりであれば、変換が発生しないように構築すると必要ないし、変換が必要であっても1種類の変換で済みます。ありとあらゆる場所からテキストを読むこむようなプログラムになると、この文字コード変換を網羅しないと利便性が損なわれる結果になります。文字コードの掃出し処理が間違っていると、文字コード破壊プログラムになってしまう可能性もありますので、自分で変換処理を作って、書き出すプログラムを作るのはかなりの知識を必要とします。実績のある変換処理ライブラリを使った方が安全です。速度改善の必要があるような人は自分で変換処理作りに挑むのもよいのかもしれません。ここでは、既存の変換処理ライブラリを使う方法を示し、時間があれば具体的な変換処理の作成について触れたいと思います。
 +
 +
 +
例によって、全部のサンプルを記事に書き起こすまでに相当な時間がかかると思いますので、すこしづつ進めていくことになると思います。
 +
 +
 +
C++/CLIだとEncodingというライブラリを使うことで変換ができますが、C++以下の範囲で扱う場合はIBM社が作成したオープンソースICU(International Components for Unicode)、GNUプロジェクトによって作られLGPLのICONVというライブラリがあります。ほかにも有志によって作られたフリーソフトnkf.dllというライブラリを使う方法もあります。ここではICUを使った方法について記述します。GNUは自由に使うことのできるUnixとしてのOSであるLinuxの開発プロジェクトで、GNU's Not Unixという意味だそうです。そうすると先頭にまたGNUが出てくるから、それは何の意味?ってなるとまたGNUはGNU's Not Unixって略語だよっていう風になる再帰的な略語です。GNUのGの意味は思考を停止しない限り永遠に再帰されます。LGPL(Lesser General Public License)は簡単に表現するとコンパイルするプログラムの配布には関与しないライセンスですが、ライブラリそのものや、制限に関するライセンスの詳細な意味についてはGNUプロジェクトによる説明で解釈して下さい。
 +
 +
 +
ICUはC++(Cpp)の技術を含むプロジェクトですので、C言語の領域からは外れます。C言語だけで、文字コード変換をやろうとすると、このようなライブラリがないために、もっと基礎的なコード変換技術を身に着ける必要があります。根本的な言語でやる方が敷居が高いというのはアセンブラ含めて、同様の事だと言えると思います。ここではそのような基礎的な技術は紹介しないので、C言語だけで実現する必要がある場合には、ICUプロジェクトのソースを解析するなりして、クラスやC++で登場する構文をを使わない形式で実現できるように挑戦してみると良いです。とても大変なことだと思います。
 +
 +
 +
ICUのWebSite<br />
 +
http://site.icu-project.org/<br />
 +
まずここから最新のソースファイルをダウンロードします。<br />
 +
執筆時点'14/09ではICU Versionは5.4で、VisualStudio2012を使っている分には、現在のICU4CのソースはCygwinも必要とせずにビルドができます。VisualStudio2010で作られているので、初回のソューションファイルオープンでプロジェクトの変換が必要になります。ビルド後VisualStudioの設定も以下のとおり実施する必要があります。ICUが利用している開発環境よりも新しいものなら楽にビルドできそうです。
 +
 +
 +
*ビルドの手順
 +
:1.環境変数PATHに[icu配置パス]\icu\bin を追加。x64プロジェクトをビルドするときは[icu配置パス]\icu\bin64っすかね。
 +
:2.[icu配置パス]\icu\source\allinone\allinone.sln を開く(プロジェクト変換ダイアログ表示されたらOKで変換する)
 +
::注)icu配置パスを決めてからビルドをしないと駄目です。ビルド時に生成されるファイルで絶対パスで管理されるDATAがあるため、ビルド後に移動させると動かなくなります。
 +
:3.メニューの[ビルド]-[バッチビルド]を選択し、表示されたダイアログで、Win32かx64のプロジェクトを選択してから→[ビルド]で、ひたすら待つ。全部でおそらく15分(Corei7 3610QM 2.3GHz)くらい
 +
::次のプロジェクト設定Win32 or x64をビルドするときには手順1に戻ることになります。
 +
:4.コマンドプロンプトでテストプログラムを動かす。テストコマンドの引数4種類全部確かめるなら以下4つのコマンド全部実行。それか自分の目的のテストだけ実施。あるいはテストはやらないのもひとつの選択肢。
 +
::*[icu配置パス]\icu\source\allinone\allinone.bat x86 Debug
 +
::*[icu配置パス]\icu\source\allinone\allinone.bat x86 Release
 +
::*[icu配置パス]\icu\source\allinone\allinone.bat x64 Debug
 +
::*[icu配置パス]\icu\source\allinone\allinone.bat x64 Release
 +
 +
 +
ソースを見ることができるのですが、とにかく巨大なプロジェクトで、ソースを見るのも勉強になるかもしれません。巨大プロジェクトならではのアイデア満載かなぁと思います。ワーニングもいっぱいだけど、まぁ気にしない。バグもあるみたいで、同時に配布されるテストプログラムをビルド後に動作させてみるのですが、うまく動かない関数もありました。今回の目的にはあまり関係してこない部分のバグだと思うので、このまま使ってみます。
 +
 +
 +
以下、テスト時のエラーログです。ひょっとしたら自分だけなのかもしれませんが、既知のバグみたいな?いやテストだけで出るエラーみたいな感じなので気にしないことにします。え?ホントにそれでいいのか?調べるのも面倒だし、放置。
 +
<syntaxhighlight2 lang="text">
 +
KNOWN ISSUES
 +
#11217 <http://bugs.icu-project.org/trac/ticket/11217>
 +
  /tsutil/cldrtest/TestExemplarSet
 +
    "Fix result of uscript_getCode for yi: USCRIPT_YI -> USCRIPT_HEBREW"
 +
  /tsutil/cldrtest/VerifyTranslation
 +
    "Fix result of uscript_getCode for yi: USCRIPT_YI -> USCRIPT_HEBREW"
 +
(To run suppressed tests, use the -K option.)
 +
 +
 +
SUMMARY:
 +
******* [Total error count:    590]
 +
Errors in
 +
[/tsconv/nucnvtst/TestISO_2022_JP]
 +
[/tsconv/nucnvtst/TestJIS]
 +
[/tsconv/nucnvtst/TestISO_2022_JP_1]
 +
[/tsconv/nucnvtst/TestISO_2022_JP_2]
 +
[/tsconv/nucnvtst/TestHZ]
 +
[/tsconv/nucnvtst/TestJitterbug2346]
 +
[/tsconv/nccbtst/TestSkipCallBack]
 +
[/tsconv/nccbtst/TestSubWithValueCallBack]
 +
[/tsconv/ncnvtst/TestResetBehaviour]
 +
</syntaxhighlight2>
 +
表:icucheck.bat Win32 Release のテスト結果でのエラー
 +
 +
 +
あらゆる文字コードの変換だけでなく、大文字小文字相互変換、全角半角相互変換、ひらがなカタカナ相互変換、他にもひらがなやカタカナからのローマ字相互変換といった複雑な変換も提供しています。そのほかにも通貨フォーマットや時間表記変換といった面白い変換も組み込まれています。ここでは文字コード変換のみを取り上げます。文字コードをファイルに出力するのはもっとあとで説明する予定なので、ここでは、サンプルとなる文字列をその文字コード体系に合わせて16進数で表現した配列として扱い、それを基に変換後の文字コード配列が生成されるのを確かめます。変換後の文字コードがUNICODEやShiftJIS以外になる場合も同じく16進数で表現される配列で示します、逆に異なる文字コードから基に戻す変換も確認します。
 +
 +
 +
*プロジェクトの設定
 +
:1.Win32プロジェクトなら[icu配置パス]\icu\bin、x64プロジェクトなら[icu配置パス]\icu\bin64という絶対パスを、プロジェクト毎にプロジェクトの設定の中(ALT+F7キーで表示されるダイアログの構成プロパティの中)にあるVCディレクトリの実行可能ファイルディレクトリにパスを設定する。Win32プロジェクトとx64プロジェクトとでパスは異なるためプロジェクト毎に毎回設定した方が良いでしょう。文字コード変換を必要とするプロジェクトを作成する都度、設定しましょう。面倒な人でWin32プロジェクトしか作らないX54しか作らないという人は、どちらかの環境変数PATHに入れてもいいでしょう。でも結局、この次にlibファイルやincludeファイルの設定もしないといけないし、やっぱりプロジェクト毎に設定しましょう。一見、面倒そうだけど、そんなにたくさんプロジェクト作る人ってあんまりいないと思います。小さなサンプルコードプロジェクトをたくさん作って、それで変換テストしまくる人は大変かもしれませんね。自分は基本Win32のプロジェクトで遊んでるので、環境変数PATHにWin32プロジェクト用の実行パスを登録しています。X64をビルドするときに、また切り替えます。このとき、新しいパス変数を作ってPATH32=[icu配置パス]\icu\bin;(他のSDKの実行パス);…;…でPATH64=[icu配置パス]\icu\bin64;(他のSDKの実行パス);…;…として、環境変数PATHにはPATH=(既存パス1);(既存パス2);%PATH32%;(既存パスn)みたいに登録するといろいろなSDKをまとめて切り替えられます。64に変えればいいんだもんね。
 +
:2.Win32プロジェクトなら[icu配置パス]\icu\lib、x64プロジェクトなら[icu配置パス]\icu\lib64という絶対パスをプロジェクト毎にプロジェクトの設定の中にあるVCディレクトリのライブラリディレクトリにパスを設定する。これも実行パス同様に管理して環境変数LIB32とLIB64を作って、環境変数LIB=%LIB32%とかにすると、プロジェクトの設定にはライブラリの欄に$(LIB)と入力するだけでよくなります。
 +
:3.Win32,x64共通ですが、[icu配置パス]\icu\includeをプロジェクト毎にプロジェクトの設定の中にあるVCディレクトリのインクルードディレクトリに設定します。自分はこれも環境変数INCLUDEを作っていて、$(INCLUDE)と設定しています。
 +
:4.デバッグプロジェクトならicuucd.lib、リリースプロジェクトならicuuc.libという追加するべきライブラリ名をプロジェクト毎にプロジェクトの設定の中にあるリンカー-入力の追加の依存ファイル欄に追記します。
 +
 +
 +
このICUはC++/CLIプロジェクトのような/clrオプションコンパイルには対応していません。UConverterという構造体が実態が未定義のまま利用されていますが、このような宣言がされているだけのものをビルドするとリンカーエラーが発生し、プログラムは動作しません。対処方法はあると思いますが、ICUはとてつもなく大きなプロジェクトファイルです。C++/CLIで使っていくには、現在のバージョンを永続的に使っていくのか?メンテしきれるか?どうかも含めた検討が必要になります。
 +
 +
 +
リンカー ツールの警告 LNK4248 http://msdn.microsoft.com/ja-jp/library/h8027ys9.aspx
 +
 +
 +
プロジェクトの設定は以上です。以下が実際の変換サンプルになります。これまでのサンプルもそうですが、実際にはサポートクラスを作って、毎回新しく変数定義しているものは、クラスを呼ぶたびにまとめて生成されるようなセットを作るべきです。変換サポートクラスの作り方については、クラスに関する記述を掘り下げるセクションで触れたいと思いますが、ここでは例のごとく直線的なプログラムになっています。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#include "stdafx.h"
 +
#include <unicode/ucnv.h>
 +
#include <stdlib.h>
 +
#include <string>
 +
#include <mbstring.h>
 +
#include <iostream>
 +
#include <locale>
 +
#include <tchar.h>
 +
#include "atlstr.h"//CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "cstringt.h"//CStringTの定義プリプロセッサ
 +
#include "atlbase.h"
 +
#include "comutil.h"
 +
using namespace std;
 +
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese"));
 +
 +
 +
 +
  // "JIS文字列" のJIS(iso-2022-jp)表現↓
 +
  string jis = "\x4A\x49\x53\x1B\x24\x42\x4A\x38\x3B\x7A\x4E\x73\x1B\x28\x42";
 +
  wstring wstr = L"JIS文字列";
 +
 +
 +
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // JIS → UNICODE
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  UConverter* ucnvTest;
 +
  UErrorCode uerrorNum;
 +
  int nStrSize;
 +
  int nStrResultSize;
 +
  nStrSize = jis.size();
 +
 +
  std::wstring stringCnvResult(nStrSize, L'\0');
 +
 +
  ucnvTest = ucnv_open("iso-2022-jp", &uerrorNum);
 +
  nStrResultSize = ucnv_toUChars(
 +
    ucnvTest,
 +
    &stringCnvResult[0], stringCnvResult.size(), // 変換先のポインタとサイズ
 +
    &jis[0], nStrSize, // 変換元のポインタとサイズ
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  _tprintf(_T("%s\n"), stringCnvResult.c_str());  
 +
 
 +
 +
  wchar_t* pwcStr = new wchar_t[_tcslen(stringCnvResult.c_str()) + 1];
 +
  _tcscpy_s(pwcStr,_tcslen(stringCnvResult.c_str()) + 1,stringCnvResult.c_str());
 +
  for(int i = 0;i < (int)_tcslen(stringCnvResult.c_str());i++){
 +
    printf("%04x:",*(pwcStr + i));
 +
  }
 +
    printf("\n");
 +
 +
 +
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // UNICODE → JIS
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  ucnvTest = ucnv_open("iso-2022-jp", &uerrorNum);
 +
 +
  nStrSize = wstr.size();
 +
  std::string stringCnvResult2(ucnv_getMaxCharSize(ucnvTest) * nStrSize , L'\0');
 +
 +
 +
  nStrResultSize = ucnv_fromUChars(
 +
    ucnvTest,
 +
    &stringCnvResult2[0], stringCnvResult2.size(), // 変換先のポインタとサイズ
 +
    &wstr[0], nStrSize, // 変換元のポインタとサイズ
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult2.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  _tprintf(_T("%s\n"), stringCnvResult2.c_str());  
 +
 +
 +
  char* pcStr = new char[strlen(stringCnvResult2.c_str()) + 1];
 +
  strcpy_s(pcStr,strlen(stringCnvResult2.c_str()) + 1,stringCnvResult2.c_str());
 +
  for(int i = 0;i < (int)strlen(stringCnvResult2.c_str());i++){
 +
    printf("%02x:",*(pcStr + i));
 +
  }
 +
    printf("\n");
 +
 +
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // UNICODE → SJIS
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  ucnvTest = ucnv_open("shift_jis", &uerrorNum);
 +
 +
  nStrSize = wstr.size();
 +
  std::string stringCnvResult3(ucnv_getMaxCharSize(ucnvTest) * nStrSize , L'\0');
 +
 +
 +
  nStrResultSize = ucnv_fromUChars(
 +
    ucnvTest,
 +
    &stringCnvResult3[0], stringCnvResult3.size(), // 変換先のポインタとサイズ
 +
    &wstr[0], nStrSize, // 変換元のポインタとサイズ
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult3.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  printf("%s\n", stringCnvResult3.c_str());  
 +
 +
 +
  char* pcStr2 = new char[strlen(stringCnvResult3.c_str()) + 1];
 +
  strcpy_s(pcStr2,strlen(stringCnvResult3.c_str()) + 1,stringCnvResult3.c_str());
 +
  for(int i = 0;i < (int)strlen(stringCnvResult3.c_str());i++){
 +
    printf("%02x:",0x000000ff & *(pcStr2 + i));
 +
  }
 +
    printf("\n");
 +
 +
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
という具合に変換すると結果として
 +
<syntaxhighlight2 lang="text">
 +
JIS文字列
 +
004a:0049:0053:6587:5b57:5217:
 +
????稻獎?B
 +
4a:49:53:1b:24:42:4a:38:3b:7a:4e:73:1b:28:42:
 +
JIS文字列
 +
4a:49:53:95:b6:8e:9a:97:f1:
 +
 +
</syntaxhighlight2>
 +
のようなものが得られます。
 +
 +
 +
これですべての変換が出来そうな気分ですが、実際にはshift_jisコード上で展開される携帯電話各社の絵文字があったり、UNICODE上での文字の重複による変換先の最適化、UNICODEにしかない文字の変換があった場合の処理など実際のプログラミング技術が、ここをスタート地点として、広がっています。auとDocomoは絵文字を統一させたんだったかも…ソフトバンクはかなり独自の体系を維持。ウィルコム。イーモバ…ふむ、どうなってるんだろ。んで、UNICODEにも少し絵文字が追加されてたり…。でも結局、それを表示するのはその文字コードのグリフをもったフォントファイルなわけです。やれる範囲。結構、限られてます。特殊文字には、年号とかもあります。次の年号の文字コードとかも、後で変更追加になるに違いない。㍻。←平成を一文字で表した環境依存文字。文字コードの世界が今のようになった歴史を知るのも面白いですし、これからの文字コードはどうあるべきかを議論する国際的なワーキンググループも活動しています。絶賛迷走中あるいは理想形へ向かって進行中です。メールで半角カタカナが使えないのはJISコード iso-2022-jpのおかげです。更にはメールはBase64という変換方式もあり、バイナリーコードや文字列コードを先頭から6ビットずつ4セットにしていくエンコードがあります。こうやってメールはおくられているんだなと感心したものです。http://ja.wikipedia.org/wiki/Base64
 +
 +
 +
上記のサンプルですが、動作しますが、ucnv_openでエラーコードが返ってきています。-122だそうで調べてみるとAMBIGUOUS_ALIAS_WARNING(-122) This converter alias can go to different converter implementations.とのことです。ワーニングレベルと認識できますが、他の方法で実装できるよだって。どういうこと?
 +
 +
 +
対応している変換は以下の文字コードになります。一番左が基本文字セット名で、その横にエイリアス名の個数、★の横にスペース区切りで全エイリアス名(別名)を記載しました。ucnv_open関数などの第一引数にはこのエイリアス名を大文字小文字の区別なく記載することができるようです。
 +
 +
 +
shift_jisは41行目と42行目でダブって登場しますね。ibm-943も。どっちが使われる?調べるの?いやいや、調べきれそうもないです。よくみかけるコード名でいくと上側が使われるべきなんでしょうけど。どっちもそれほど変わらないのか、それとも、これが俗にいうマイクロソフトsjisとsjisの違いなのか?Windowsなら上で、それ以外は純粋なShift_JISってことなのか。AMBIGUOUS_ALIAS_WARNINGの原因にはあいまいな変換がされたことに由来するらしいが、どうも、指定方法の問題ではないらしい。謎は謎のままに。謎というよりはICUの英語を理解できないだけだが…。だからどうしろとは言わない説明書がうらめしい。
 +
 +
 +
ibm-943_P15A-2003 19 ★ibm-943_P15A-2003 ibm-943 '''Shift_JIS''' MS_Kanji csShiftJIS windows-31j csWindows31J x-sjis x-ms-cp932 '''cp932''' windows-93cp943c IBM-943C ms932 pck '''sjis''' ibm-943_VSUB_VPUA x-MS932_0213 x-JISAutoDetect
 +
 +
ibm-943_P130-1999 7 ★ibm-943_P130-1999 ibm-943 '''Shift_JIS''' cp943 943 ibm-943_VASCII_VSUB_VPUA x-IBM943
 +
<syntaxhighlight2 lang="text" line start="1">
 +
UTF-8 14 ★UTF-8 ibm-1208 ibm-1209 ibm-5304 ibm-5305 ibm-13496 ibm-13497 ibm-17592 ibm-17593 windows-65001 cp1208 x-UTF_8J unicode-1-1-utf unicode-2-0-utf-8
 +
UTF-16 7 ★UTF-16 ISO-10646-UCS-2 ibm-1204 ibm-1205 unicode csUnicode ucs-2
 +
UTF-16BE 21 ★UTF-16BE x-utf-16be UnicodeBigUnmarked ibm-1200 ibm-1201 ibm-13488 ibm-13489 ibm-17584 ibm-17585 ibm-21680 ibm-21681 ibm-257 ibm-25777 ibm-29872 ibm-29873 ibm-61955 ibm-61956 windows-1201 cp1200 cp1201 UTF16_BigEndian
 +
UTF-16LE 17 ★UTF-16LE x-utf-16le UnicodeLittleUnmarked ibm-1202 ibm-1203 ibm-13490 ibm-13491 ibm-17586 ibm-17587 ibm-21682 ibm-21683 ibm-778 ibm-25779 ibm-29874 ibm-29875 UTF16_LittleEndian windows-1200
 +
UTF-32 6 ★UTF-32 ISO-10646-UCS-4 ibm-1236 ibm-1237 csUCS4 ucs-4
 +
UTF-32BE 5 ★UTF-32BE UTF32_BigEndian ibm-1232 ibm-1233 ibm-9424
 +
UTF-32LE 4 ★UTF-32LE UTF32_LittleEndian ibm-1234 ibm-1235
 +
UTF16_PlatformEndian 1 ★UTF16_PlatformEndian
 +
UTF16_OppositeEndian 1 ★UTF16_OppositeEndian
 +
UTF32_PlatformEndian 1 ★UTF32_PlatformEndian
 +
UTF32_OppositeEndian 1 ★UTF32_OppositeEndian
 +
UTF-16BE,version=1 2 ★UTF-16BE,version=1 UnicodeBig
 +
UTF-16LE,version=1 3 ★UTF-16LE,version=1 UnicodeLittle x-UTF-16LE-BOM
 +
UTF-16,version=1 1 ★UTF-16,version=1
 +
UTF-16,version=2 1 ★UTF-16,version=2
 +
UTF-7 4 ★UTF-7 windows-65000 unicode-1-1-utf-7 unicode-2-0-utf-7
 +
IMAP-mailbox-name 1 ★IMAP-mailbox-name
 +
SCSU 3 ★SCSU ibm-1212 ibm-1213
 +
BOCU-1 4 ★BOCU-1 csBOCU-1 ibm-1214 ibm-1215
 +
CESU-8 2 ★CESU-8 ibm-9400
 +
ISO-8859-1 11 ★ISO-8859-1 ibm-819 IBM819 cp819 latin1 8859_1 csISOLatin1 iso-ir-100 ISO_8859-1:1987 l1 819
 +
US-ASCII 16 ★US-ASCII ASCII ANSI_X3.4-1968 ANSI_X3.4-1986 ISO_646.irv:1991 iso_646.irv:1983 ISO646-US us csASCII iso-ir-6 cp367 ascii7 64
 +
windows-20127 ibm-367 IBM367
 +
gb18030 4 ★gb18030 ibm-1392 windows-54936 GB18030
 +
ibm-912_P100-1995 12 ★ibm-912_P100-1995 ibm-912 ISO-8859-2 ISO_8859-2:1987 latin2 csISOLatin2 iso-ir-101 l2 8859_2 cp912 912 windows-2859
 +
ibm-913_P100-2000 12 ★ibm-913_P100-2000 ibm-913 ISO-8859-3 ISO_8859-3:1988 latin3 csISOLatin3 iso-ir-109 l3 8859_3 cp913 913 windows-2859
 +
ibm-914_P100-1995 12 ★ibm-914_P100-1995 ibm-914 ISO-8859-4 latin4 csISOLatin4 iso-ir-110 ISO_8859-4:1988 l4 8859_4 cp914 914 windows-2859
 +
ibm-915_P100-1995 11 ★ibm-915_P100-1995 ibm-915 ISO-8859-5 cyrillic csISOLatinCyrillic iso-ir-144 ISO_8859-5:1988 8859_5 cp915 915 window28595
 +
ibm-1089_P100-1995 16 ★ibm-1089_P100-1995 ibm-1089 ISO-8859-6 arabic csISOLatinArabic iso-ir-127 ISO_8859-6:1987 ECMA-114 ASMO-708 8859_6p1089 1089 windows-28596 ISO-8859-6-I ISO-8859-6-E x-ISO-8859-6S
 +
ibm-9005_X110-2007 13 ★ibm-9005_X110-2007 ibm-9005 ISO-8859-7 8859_7 greek greek8 ELOT_928 ECMA-118 csISOLatinGreek iso-ir-126 ISO_8859-7987 windows-28597 sun_eu_greek
 +
ibm-813_P100-1995 4 ★ibm-813_P100-1995 ibm-813 cp813 813
 +
ibm-5012_P100-1999 12 ★ibm-5012_P100-1999 ibm-5012 ISO-8859-8 hebrew csISOLatinHebrew iso-ir-138 ISO_8859-8:1988 ISO-8859-8-I ISO-8859-8-8859_8 windows-28598 hebrew8
 +
ibm-916_P100-1995 4 ★ibm-916_P100-1995 ibm-916 cp916 916
 +
ibm-920_P100-1995 15 ★ibm-920_P100-1995 ibm-920 ISO-8859-9 latin5 csISOLatin5 iso-ir-148 ISO_8859-9:1989 l5 8859_9 cp920 920 windows-2859ECMA-128 turkish8 turkish
 +
iso-8859_10-1998 7 ★iso-8859_10-1998 ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6
 +
iso-8859_11-2001 4 ★iso-8859_11-2001 ISO-8859-11 thai8 x-iso-8859-11
 +
ibm-921_P100-1995 8 ★ibm-921_P100-1995 ibm-921 ISO-8859-13 8859_13 windows-28603 cp921 921 x-IBM921
 +
iso-8859_14-1998 7 ★iso-8859_14-1998 ISO-8859-14 iso-ir-199 ISO_8859-14:1998 latin8 iso-celtic l8
 +
ibm-923_P100-1998 13 ★ibm-923_P100-1998 ibm-923 ISO-8859-15 Latin-9 l9 8859_15 latin0 csisolatin0 csisolatin9 iso8859_15_fdis cp923 923 wdows-28605
 +
ibm-942_P12A-1999 10 ★ibm-942_P12A-1999 ibm-942 ibm-932 cp932 shift_jis78 sjis78 ibm-942_VSUB_VPUA ibm-932_VSUB_VPUA x-IBM942 x-IBM942C
 +
ibm-943_P15A-2003 19 ★ibm-943_P15A-2003 ibm-943 Shift_JIS MS_Kanji csShiftJIS windows-31j csWindows31J x-sjis x-ms-cp932 cp932 windows-93cp943c IBM-943C ms932 pck sjis ibm-943_VSUB_VPUA x-MS932_0213 x-JISAutoDetect
 +
ibm-943_P130-1999 7 ★ibm-943_P130-1999 ibm-943 Shift_JIS cp943 943 ibm-943_VASCII_VSUB_VPUA x-IBM943
 +
ibm-33722_P12A_P12A-2009_U2 5 ★ibm-33722_P12A_P12A-2009_U2 ibm-33722 ibm-5050 ibm-33722_VPUA IBM-eucJP
 +
ibm-33722_P120-1999 9 ★ibm-33722_P120-1999 ibm-33722 ibm-5050 cp33722 33722 ibm-33722_VASCII_VPUA x-IBM33722 x-IBM33722A x-IBM33722C
 +
ibm-954_P101-2007 4 ★ibm-954_P101-2007 ibm-954 x-IBM954 x-IBM954C
 +
euc-jp-2007 7 ★euc-jp-2007 EUC-JP Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese X-EUC-JP eucjis ujis
 +
ibm-1373_P100-2002 3 ★ibm-1373_P100-2002 ibm-1373 windows-950
 +
windows-950-2000 7 ★windows-950-2000 Big5 csBig5 windows-950 x-windows-950 x-big5 ms950
 +
ibm-950_P110-1999 5 ★ibm-950_P110-1999 ibm-950 cp950 950 x-IBM950
 +
ibm-1375_P100-2008 5 ★ibm-1375_P100-2008 ibm-1375 Big5-HKSCS big5hk HKSCS-BIG5
 +
ibm-5471_P100-2006 7 ★ibm-5471_P100-2006 ibm-5471 Big5-HKSCS MS950_HKSCS hkbig5 big5-hkscs:unicode3.0 x-MS950-HKSCS
 +
ibm-1386_P100-2001 5 ★ibm-1386_P100-2001 ibm-1386 cp1386 windows-936 ibm-1386_VSUB_VPUA
 +
windows-936-2000 5 ★windows-936-2000 GBK CP936 MS936 windows-936
 +
ibm-1383_P110-1999 10 ★ibm-1383_P110-1999 ibm-1383 GB2312 csGB2312 cp1383 1383 EUC-CN ibm-eucCN hp15CN ibm-1383_VPUA
 +
ibm-5478_P100-1995 8 ★ibm-5478_P100-1995 ibm-5478 GB_2312-80 chinese iso-ir-58 csISO58GB231280 gb2312-1980 GB2312.1980-0
 +
euc-tw-2014 2 ★euc-tw-2014 EUC-TW
 +
ibm-964_P110-1999 8 ★ibm-964_P110-1999 ibm-964 ibm-eucTW cns11643 cp964 964 ibm-964_VPUA x-IBM964
 +
ibm-949_P110-1999 6 ★ibm-949_P110-1999 ibm-949 cp949 949 ibm-949_VASCII_VSUB_VPUA x-IBM949
 +
ibm-949_P11A-1999 6 ★ibm-949_P11A-1999 ibm-949 cp949c ibm-949_VSUB_VPUA x-IBM949C IBM-949C
 +
ibm-970_P110_P110-2006_U2 13 ★ibm-970_P110_P110-2006_U2 ibm-970 EUC-KR KS_C_5601-1987 windows-51949 csEUCKR ibm-eucKR KSC_5601 5601 cp97070 ibm-970_VPUA x-IBM970
 +
ibm-971_P100-1995 4 ★ibm-971_P100-1995 ibm-971 ibm-971_VPUA x-IBM971
 +
ibm-1363_P11B-1998 14 ★ibm-1363_P11B-1998 ibm-1363 KS_C_5601-1987 KS_C_5601-1989 KSC_5601 csKSC56011987 korean iso-ir-149 cp1363 5601 kscindows-949 ibm-1363_VSUB_VPUA x-IBM1363C
 +
ibm-1363_P110-1997 4 ★ibm-1363_P110-1997 ibm-1363 ibm-1363_VASCII_VSUB_VPUA x-IBM1363
 +
windows-949-2000 10 ★windows-949-2000 windows-949 KS_C_5601-1987 KS_C_5601-1989 KSC_5601 csKSC56011987 korean iso-ir-149 ms949 x-KSC5601
 +
windows-874-2000 5 ★windows-874-2000 TIS-620 windows-874 MS874 x-windows-874
 +
ibm-874_P100-1995 8 ★ibm-874_P100-1995 ibm-874 ibm-9066 cp874 TIS-620 tis620.2533 eucTH x-IBM874
 +
ibm-1162_P100-1999 2 ★ibm-1162_P100-1999 ibm-1162
 +
ibm-437_P100-1995 7 ★ibm-437_P100-1995 ibm-437 IBM437 cp437 437 csPC8CodePage437 windows-437
 +
ibm-720_P100-1997 5 ★ibm-720_P100-1997 ibm-720 windows-720 DOS-720 x-IBM720
 +
ibm-737_P100-1997 7 ★ibm-737_P100-1997 ibm-737 IBM737 cp737 windows-737 737 x-IBM737
 +
ibm-775_P100-1996 7 ★ibm-775_P100-1996 ibm-775 IBM775 cp775 csPC775Baltic windows-775 775
 +
ibm-850_P100-1995 7 ★ibm-850_P100-1995 ibm-850 IBM850 cp850 850 csPC850Multilingual windows-850
 +
ibm-851_P100-1995 6 ★ibm-851_P100-1995 ibm-851 IBM851 cp851 851 csPC851
 +
ibm-852_P100-1995 7 ★ibm-852_P100-1995 ibm-852 IBM852 cp852 852 csPCp852 windows-852
 +
ibm-855_P100-1995 8 ★ibm-855_P100-1995 ibm-855 IBM855 cp855 855 csIBM855 csPCp855 windows-855
 +
ibm-856_P100-1995 6 ★ibm-856_P100-1995 ibm-856 IBM856 cp856 856 x-IBM856
 +
ibm-857_P100-1995 7 ★ibm-857_P100-1995 ibm-857 IBM857 cp857 857 csIBM857 windows-857
 +
ibm-858_P100-1997 8 ★ibm-858_P100-1997 ibm-858 IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro cp858 windows-858
 +
ibm-860_P100-1995 6 ★ibm-860_P100-1995 ibm-860 IBM860 cp860 860 csIBM860
 +
ibm-861_P100-1995 8 ★ibm-861_P100-1995 ibm-861 IBM861 cp861 861 cp-is csIBM861 windows-861
 +
ibm-862_P100-1995 8 ★ibm-862_P100-1995 ibm-862 IBM862 cp862 862 csPC862LatinHebrew DOS-862 windows-862
 +
ibm-863_P100-1995 6 ★ibm-863_P100-1995 ibm-863 IBM863 cp863 863 csIBM863
 +
ibm-864_X110-1999 5 ★ibm-864_X110-1999 ibm-864 IBM864 cp864 csIBM864
 +
ibm-865_P100-1995 6 ★ibm-865_P100-1995 ibm-865 IBM865 cp865 865 csIBM865
 +
ibm-866_P100-1995 7 ★ibm-866_P100-1995 ibm-866 IBM866 cp866 866 csIBM866 windows-866
 +
ibm-867_P100-1998 3 ★ibm-867_P100-1998 ibm-867 x-IBM867
 +
ibm-868_P100-1995 7 ★ibm-868_P100-1995 ibm-868 IBM868 CP868 868 csIBM868 cp-ar
 +
ibm-869_P100-1995 8 ★ibm-869_P100-1995 ibm-869 IBM869 cp869 869 cp-gr csIBM869 windows-869
 +
ibm-878_P100-1996 7 ★ibm-878_P100-1996 ibm-878 KOI8-R koi8 csKOI8R windows-20866 cp878
 +
ibm-901_P100-1999 2 ★ibm-901_P100-1999 ibm-901
 +
ibm-902_P100-1999 2 ★ibm-902_P100-1999 ibm-902
 +
ibm-922_P100-1999 6 ★ibm-922_P100-1999 ibm-922 IBM922 cp922 922 x-IBM922
 +
ibm-1168_P100-2002 4 ★ibm-1168_P100-2002 ibm-1168 KOI8-U windows-21866
 +
ibm-4909_P100-1999 2 ★ibm-4909_P100-1999 ibm-4909
 +
ibm-5346_P100-1998 4 ★ibm-5346_P100-1998 ibm-5346 windows-1250 cp1250
 +
ibm-5347_P100-1998 5 ★ibm-5347_P100-1998 ibm-5347 windows-1251 cp1251 ANSI1251
 +
ibm-5348_P100-1997 4 ★ibm-5348_P100-1997 ibm-5348 windows-1252 cp1252
 +
ibm-5349_P100-1998 4 ★ibm-5349_P100-1998 ibm-5349 windows-1253 cp1253
 +
ibm-5350_P100-1998 4 ★ibm-5350_P100-1998 ibm-5350 windows-1254 cp1254
 +
ibm-9447_P100-2002 4 ★ibm-9447_P100-2002 ibm-9447 windows-1255 cp1255
 +
ibm-9448_X100-2005 5 ★ibm-9448_X100-2005 ibm-9448 windows-1256 cp1256 x-windows-1256S
 +
ibm-9449_P100-2002 4 ★ibm-9449_P100-2002 ibm-9449 windows-1257 cp1257
 +
ibm-5354_P100-1998 4 ★ibm-5354_P100-1998 ibm-5354 windows-1258 cp1258
 +
ibm-1250_P100-1995 3 ★ibm-1250_P100-1995 ibm-1250 windows-1250
 +
ibm-1251_P100-1995 3 ★ibm-1251_P100-1995 ibm-1251 windows-1251
 +
ibm-1252_P100-2000 3 ★ibm-1252_P100-2000 ibm-1252 windows-1252
 +
ibm-1253_P100-1995 3 ★ibm-1253_P100-1995 ibm-1253 windows-1253
 +
ibm-1254_P100-1995 3 ★ibm-1254_P100-1995 ibm-1254 windows-1254
 +
ibm-1255_P100-1995 2 ★ibm-1255_P100-1995 ibm-1255
 +
ibm-5351_P100-1998 3 ★ibm-5351_P100-1998 ibm-5351 windows-1255
 +
ibm-1256_P110-1997 2 ★ibm-1256_P110-1997 ibm-1256
 +
ibm-5352_P100-1998 3 ★ibm-5352_P100-1998 ibm-5352 windows-1256
 +
ibm-1257_P100-1995 2 ★ibm-1257_P100-1995 ibm-1257
 +
ibm-5353_P100-1998 3 ★ibm-5353_P100-1998 ibm-5353 windows-1257
 +
ibm-1258_P100-1997 3 ★ibm-1258_P100-1997 ibm-1258 windows-1258
 +
macos-0_2-10.2 7 ★macos-0_2-10.2 macintosh mac csMacintosh windows-10000 macroman x-macroman
 +
macos-6_2-10.4 5 ★macos-6_2-10.4 x-mac-greek windows-10006 macgr x-MacGreek
 +
macos-7_3-10.2 7 ★macos-7_3-10.2 x-mac-cyrillic windows-10007 mac-cyrillic maccy x-MacCyrillic x-MacUkraine
 +
macos-29-10.2 7 ★macos-29-10.2 x-mac-centraleurroman windows-10029 x-mac-ce macce maccentraleurope x-MacCentralEurope
 +
macos-35-10.2 5 ★macos-35-10.2 x-mac-turkish windows-10081 mactr x-MacTurkish
 +
ibm-1051_P100-1995 7 ★ibm-1051_P100-1995 ibm-1051 hp-roman8 roman8 r8 csHPRoman8 x-roman8
 +
ibm-1276_P100-1995 4 ★ibm-1276_P100-1995 ibm-1276 Adobe-Standard-Encoding csAdobeStandardEncoding
 +
ibm-1006_P100-1995 6 ★ibm-1006_P100-1995 ibm-1006 IBM1006 cp1006 1006 x-IBM1006
 +
ibm-1098_P100-1995 6 ★ibm-1098_P100-1995 ibm-1098 IBM1098 cp1098 1098 x-IBM1098
 +
ibm-1124_P100-1996 5 ★ibm-1124_P100-1996 ibm-1124 cp1124 1124 x-IBM1124
 +
ibm-1125_P100-1997 3 ★ibm-1125_P100-1997 ibm-1125 cp1125
 +
ibm-1129_P100-1997 2 ★ibm-1129_P100-1997 ibm-1129
 +
ibm-1131_P100-1997 3 ★ibm-1131_P100-1997 ibm-1131 cp1131
 +
ibm-1133_P100-1997 2 ★ibm-1133_P100-1997 ibm-1133
 +
ISO_2022,locale=ja,version=0 5 ★ISO_2022,locale=ja,version=0 ISO-2022-JP csISO2022JP x-windows-iso2022jp x-windows-50220
 +
ISO_2022,locale=ja,version=1 7 ★ISO_2022,locale=ja,version=1 ISO-2022-JP-1 JIS_Encoding csJISEncoding ibm-5054 JIS x-windows-50221
 +
ISO_2022,locale=ja,version=2 3 ★ISO_2022,locale=ja,version=2 ISO-2022-JP-2 csISO2022JP2
 +
ISO_2022,locale=ja,version=3 2 ★ISO_2022,locale=ja,version=3 JIS7
 +
ISO_2022,locale=ja,version=4 2 ★ISO_2022,locale=ja,version=4 JIS8
 +
ISO_2022,locale=ko,version=0 3 ★ISO_2022,locale=ko,version=0 ISO-2022-KR csISO2022KR
 +
ISO_2022,locale=ko,version=1 2 ★ISO_2022,locale=ko,version=1 ibm-25546
 +
ISO_2022,locale=zh,version=0 4 ★ISO_2022,locale=zh,version=0 ISO-2022-CN csISO2022CN x-ISO-2022-CN-GB
 +
ISO_2022,locale=zh,version=1 2 ★ISO_2022,locale=zh,version=1 ISO-2022-CN-EXT
 +
ISO_2022,locale=zh,version=2 3 ★ISO_2022,locale=zh,version=2 ISO-2022-CN-CNS x-ISO-2022-CN-CNS
 +
HZ 2 ★HZ HZ-GB-2312
 +
x11-compound-text 3 ★x11-compound-text COMPOUND_TEXT x-compound-text
 +
ISCII,version=0 6 ★ISCII,version=0 x-ISCII91 x-iscii-de windows-57002 iscii-dev ibm-4902
 +
ISCII,version=1 6 ★ISCII,version=1 x-iscii-be windows-57003 iscii-bng windows-57006 x-iscii-as
 +
ISCII,version=2 4 ★ISCII,version=2 x-iscii-pa windows-57011 iscii-gur
 +
ISCII,version=3 4 ★ISCII,version=3 x-iscii-gu windows-57010 iscii-guj
 +
ISCII,version=4 4 ★ISCII,version=4 x-iscii-or windows-57007 iscii-ori
 +
ISCII,version=5 4 ★ISCII,version=5 x-iscii-ta windows-57004 iscii-tml
 +
ISCII,version=6 4 ★ISCII,version=6 x-iscii-te windows-57005 iscii-tlg
 +
ISCII,version=7 4 ★ISCII,version=7 x-iscii-ka windows-57008 iscii-knd
 +
ISCII,version=8 4 ★ISCII,version=8 x-iscii-ma windows-57009 iscii-mlm
 +
LMBCS-1 3 ★LMBCS-1 lmbcs ibm-65025
 +
ibm-37_P100-1995 13 ★ibm-37_P100-1995 ibm-37 IBM037 ibm-037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl csIBM037 cp037 037 cpibm3cp37
 +
ibm-273_P100-1995 7 ★ibm-273_P100-1995 ibm-273 IBM273 CP273 csIBM273 ebcdic-de 273
 +
ibm-277_P100-1995 9 ★ibm-277_P100-1995 ibm-277 IBM277 cp277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 ebcdic-dk 277
 +
ibm-278_P100-1995 9 ★ibm-278_P100-1995 ibm-278 IBM278 cp278 ebcdic-cp-fi ebcdic-cp-se csIBM278 ebcdic-sv 278
 +
ibm-280_P100-1995 7 ★ibm-280_P100-1995 ibm-280 IBM280 CP280 ebcdic-cp-it csIBM280 280
 +
ibm-284_P100-1995 8 ★ibm-284_P100-1995 ibm-284 IBM284 CP284 ebcdic-cp-es csIBM284 cpibm284 284
 +
ibm-285_P100-1995 9 ★ibm-285_P100-1995 ibm-285 IBM285 CP285 ebcdic-cp-gb csIBM285 cpibm285 ebcdic-gb 285
 +
ibm-290_P100-1995 6 ★ibm-290_P100-1995 ibm-290 IBM290 cp290 EBCDIC-JP-kana csIBM290
 +
ibm-297_P100-1995 8 ★ibm-297_P100-1995 ibm-297 IBM297 cp297 ebcdic-cp-fr csIBM297 cpibm297 297
 +
ibm-420_X120-1999 7 ★ibm-420_X120-1999 ibm-420 IBM420 cp420 ebcdic-cp-ar1 csIBM420 420
 +
ibm-424_P100-1995 7 ★ibm-424_P100-1995 ibm-424 IBM424 cp424 ebcdic-cp-he csIBM424 424
 +
ibm-500_P100-1995 8 ★ibm-500_P100-1995 ibm-500 IBM500 CP500 ebcdic-cp-be csIBM500 ebcdic-cp-ch 500
 +
ibm-803_P100-1999 3 ★ibm-803_P100-1999 ibm-803 cp803
 +
ibm-838_P100-1995 8 ★ibm-838_P100-1995 ibm-838 IBM838 IBM-Thai csIBMThai cp838 838 ibm-9030
 +
ibm-870_P100-1995 7 ★ibm-870_P100-1995 ibm-870 IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870
 +
ibm-871_P100-1995 8 ★ibm-871_P100-1995 ibm-871 IBM871 ebcdic-cp-is csIBM871 CP871 ebcdic-is 871
 +
ibm-875_P100-1995 6 ★ibm-875_P100-1995 ibm-875 IBM875 cp875 875 x-IBM875
 +
ibm-918_P100-1995 6 ★ibm-918_P100-1995 ibm-918 IBM918 CP918 ebcdic-cp-ar2 csIBM918
 +
ibm-930_P120-1999 8 ★ibm-930_P120-1999 ibm-930 ibm-5026 IBM930 cp930 930 x-IBM930 x-IBM930A
 +
ibm-933_P110-1995 5 ★ibm-933_P110-1995 ibm-933 cp933 933 x-IBM933
 +
ibm-935_P110-1999 5 ★ibm-935_P110-1999 ibm-935 cp935 935 x-IBM935
 +
ibm-937_P110-1999 5 ★ibm-937_P110-1999 ibm-937 cp937 937 x-IBM937
 +
ibm-939_P120-1999 9 ★ibm-939_P120-1999 ibm-939 ibm-931 ibm-5035 IBM939 cp939 939 x-IBM939 x-IBM939A
 +
ibm-1025_P100-1995 5 ★ibm-1025_P100-1995 ibm-1025 cp1025 1025 x-IBM1025
 +
ibm-1026_P100-1995 6 ★ibm-1026_P100-1995 ibm-1026 IBM1026 CP1026 csIBM1026 1026
 +
ibm-1047_P100-1995 5 ★ibm-1047_P100-1995 ibm-1047 IBM1047 cp1047 1047
 +
ibm-1097_P100-1995 5 ★ibm-1097_P100-1995 ibm-1097 cp1097 1097 x-IBM1097
 +
ibm-1112_P100-1995 5 ★ibm-1112_P100-1995 ibm-1112 cp1112 1112 x-IBM1112
 +
ibm-1122_P100-1999 5 ★ibm-1122_P100-1999 ibm-1122 cp1122 1122 x-IBM1122
 +
ibm-1123_P100-1995 5 ★ibm-1123_P100-1995 ibm-1123 cp1123 1123 x-IBM1123
 +
ibm-1130_P100-1997 2 ★ibm-1130_P100-1997 ibm-1130
 +
ibm-1132_P100-1998 2 ★ibm-1132_P100-1998 ibm-1132
 +
ibm-1137_P100-1999 2 ★ibm-1137_P100-1999 ibm-1137
 +
ibm-4517_P100-2005 2 ★ibm-4517_P100-2005 ibm-4517
 +
ibm-1140_P100-1997 7 ★ibm-1140_P100-1997 ibm-1140 IBM01140 CCSID01140 CP01140 cp1140 ebcdic-us-37+euro
 +
ibm-1141_P100-1997 7 ★ibm-1141_P100-1997 ibm-1141 IBM01141 CCSID01141 CP01141 cp1141 ebcdic-de-273+euro
 +
ibm-1142_P100-1997 8 ★ibm-1142_P100-1997 ibm-1142 IBM01142 CCSID01142 CP01142 cp1142 ebcdic-dk-277+euro ebcdic-no-277+euro
 +
ibm-1143_P100-1997 8 ★ibm-1143_P100-1997 ibm-1143 IBM01143 CCSID01143 CP01143 cp1143 ebcdic-fi-278+euro ebcdic-se-278+euro
 +
ibm-1144_P100-1997 7 ★ibm-1144_P100-1997 ibm-1144 IBM01144 CCSID01144 CP01144 cp1144 ebcdic-it-280+euro
 +
ibm-1145_P100-1997 7 ★ibm-1145_P100-1997 ibm-1145 IBM01145 CCSID01145 CP01145 cp1145 ebcdic-es-284+euro
 +
ibm-1146_P100-1997 7 ★ibm-1146_P100-1997 ibm-1146 IBM01146 CCSID01146 CP01146 cp1146 ebcdic-gb-285+euro
 +
ibm-1147_P100-1997 7 ★ibm-1147_P100-1997 ibm-1147 IBM01147 CCSID01147 CP01147 cp1147 ebcdic-fr-297+euro
 +
ibm-1148_P100-1997 7 ★ibm-1148_P100-1997 ibm-1148 IBM01148 CCSID01148 CP01148 cp1148 ebcdic-international-500+euro
 +
ibm-1149_P100-1997 7 ★ibm-1149_P100-1997 ibm-1149 IBM01149 CCSID01149 CP01149 cp1149 ebcdic-is-871+euro
 +
ibm-1153_P100-1999 4 ★ibm-1153_P100-1999 ibm-1153 IBM1153 x-IBM1153
 +
ibm-1154_P100-1999 2 ★ibm-1154_P100-1999 ibm-1154
 +
ibm-1155_P100-1999 2 ★ibm-1155_P100-1999 ibm-1155
 +
ibm-1156_P100-1999 2 ★ibm-1156_P100-1999 ibm-1156
 +
ibm-1157_P100-1999 2 ★ibm-1157_P100-1999 ibm-1157
 +
ibm-1158_P100-1999 2 ★ibm-1158_P100-1999 ibm-1158
 +
ibm-1160_P100-1999 2 ★ibm-1160_P100-1999 ibm-1160
 +
ibm-1164_P100-1999 2 ★ibm-1164_P100-1999 ibm-1164
 +
ibm-1364_P110-2007 3 ★ibm-1364_P110-2007 ibm-1364 x-IBM1364
 +
ibm-1371_P100-1999 3 ★ibm-1371_P100-1999 ibm-1371 x-IBM1371
 +
ibm-1388_P103-2001 4 ★ibm-1388_P103-2001 ibm-1388 ibm-9580 x-IBM1388
 +
ibm-1390_P110-2003 3 ★ibm-1390_P110-2003 ibm-1390 x-IBM1390
 +
ibm-1399_P110-2003 3 ★ibm-1399_P110-2003 ibm-1399 x-IBM1399
 +
ibm-5123_P100-1999 2 ★ibm-5123_P100-1999 ibm-5123
 +
ibm-8482_P100-1999 2 ★ibm-8482_P100-1999 ibm-8482
 +
ibm-16684_P110-2003 3 ★ibm-16684_P110-2003 ibm-16684 ibm-20780
 +
ibm-4899_P100-1998 2 ★ibm-4899_P100-1998 ibm-4899
 +
ibm-4971_P100-1999 2 ★ibm-4971_P100-1999 ibm-4971
 +
ibm-9067_X100-2005 2 ★ibm-9067_X100-2005 ibm-9067
 +
ibm-12712_P100-1998 3 ★ibm-12712_P100-1998 ibm-12712 ebcdic-he
 +
ibm-16804_X110-1999 3 ★ibm-16804_X110-1999 ibm-16804 ebcdic-ar
 +
ibm-37_P100-1995,swaplfnl 2 ★ibm-37_P100-1995,swaplfnl ibm-37-s390
 +
ibm-1047_P100-1995,swaplfnl 3 ★ibm-1047_P100-1995,swaplfnl ibm-1047-s390 IBM1047_LF
 +
ibm-1140_P100-1997,swaplfnl 2 ★ibm-1140_P100-1997,swaplfnl ibm-1140-s390
 +
ibm-1141_P100-1997,swaplfnl 3 ★ibm-1141_P100-1997,swaplfnl ibm-1141-s390 IBM1141_LF
 +
ibm-1142_P100-1997,swaplfnl 2 ★ibm-1142_P100-1997,swaplfnl ibm-1142-s390
 +
ibm-1143_P100-1997,swaplfnl 2 ★ibm-1143_P100-1997,swaplfnl ibm-1143-s390
 +
ibm-1144_P100-1997,swaplfnl 2 ★ibm-1144_P100-1997,swaplfnl ibm-1144-s390
 +
ibm-1145_P100-1997,swaplfnl 2 ★ibm-1145_P100-1997,swaplfnl ibm-1145-s390
 +
ibm-1146_P100-1997,swaplfnl 2 ★ibm-1146_P100-1997,swaplfnl ibm-1146-s390
 +
ibm-1147_P100-1997,swaplfnl 2 ★ibm-1147_P100-1997,swaplfnl ibm-1147-s390
 +
ibm-1148_P100-1997,swaplfnl 2 ★ibm-1148_P100-1997,swaplfnl ibm-1148-s390
 +
ibm-1149_P100-1997,swaplfnl 2 ★ibm-1149_P100-1997,swaplfnl ibm-1149-s390
 +
ibm-1153_P100-1999,swaplfnl 2 ★ibm-1153_P100-1999,swaplfnl ibm-1153-s390
 +
ibm-12712_P100-1998,swaplfnl 2 ★ibm-12712_P100-1998,swaplfnl ibm-12712-s390
 +
ibm-16804_X110-1999,swaplfnl 2 ★ibm-16804_X110-1999,swaplfnl ibm-16804-s390
 +
ebcdic-xml-us 1 ★ebcdic-xml-us
 +
</syntaxhighlight2>
 +
 +
 +
ICU4Cを使ったプログラムをリリースするときは必要なDLLも一緒にexeファイルと同じディレクトリに置いて配布する必要があります。Win32プロジェクトなら[ICU配置パス]\icu\bin\icuuc**.dllが必要になります。x64プロジェクトなら[ICU配置パス]\icu\bin64\icuuc**.dllが必要になります。プロジェクト設定によりbin or bin64\追加libファイル名+バージョン番号.dllという具合にライブラリと対になってると思っていいです。できれば配布する前に開発環境が導入されていない通常のPCで動作チェックするのがよいです。環境が準備できないなら誰かに人柱になってもらって、確認がとれてから正式リリースとか、そういう風にした方がよいです。自分は以前に配布するべきファイルセットを間違えて、迷惑をかけたことがありますので、チェックするようにしています。
 +
 
=='''文字列大文字小文字変換'''==
 
=='''文字列大文字小文字変換'''==
 +
これは、まぁ関数がありますので簡単に実現できます。
 +
aBcdEfgに書かれているものをABCDEFGに変換したり、あるいはabcdifgに変換したりできます。AbCDeFGみたいに入れ替えたり、英語の自然表記のため文章の始めの文字を探したり、略語や固有名詞の先頭文字を大文字にし、そのほかを小文字にするのはまた別の話になります。入れ替えくらいなら機械的な操作なのでやれると思います。大文字と小文字を同一視する必要のある検索の一致や大文字と小文字を区別しないメールアドレスやドメイン名の文字列変換に利用することもあります。この変換にも先述したICUを利用することができますが、この程度であれば標準関数を利用した方がよいです。DLLファイルを配ったり、プロジェクトにLibライブラリを読み込んだりINCLUDEファイルを設定したり、大きな実行ファイル群を要することになります。どうせ配布するならICUを使った方がよかったりする場合もありますので、ケースバイケースでしょうか?
 +
 +
 +
とりあえずは、ICUの方の変換を記載しておきます。大文字、小文字変換の他に日本語ひらがなとカタカナとローマ字の相互変換についてもサンプルを示しました。ICUを使えば、簡単に変換してくれます。完璧ではなさそうなので、一括変換する場合は注意して使う必要はありそうです。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
//#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 +
 +
using namespace std;
 +
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese"));
 +
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 全角 → 半角変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  UErrorCode errorNum = U_ZERO_ERROR;
 +
  int nStrSize;
 +
 
 +
  //変換元となる全角リテラル
 +
  std::wstring wstringResult = L"あいうえおアイウエオABCDE@;:*+/";
 +
  UnicodeString str(wstringResult.c_str());//変換関数にはUnicodeString型を使うので初期値関数を使って初期化。strは変更可能な変数である必要がある。ココでconstは駄目。
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 半角 → 全角変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"あいうえおアイウエオABCDE@;:*+/";
 +
  Transliterator *myTrans = myTrans->createInstance(L"Halfwidth-Fullwidth", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  printf("★半角 → 全角変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 小文字 → 大文字変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"AbcDefGhiJKlmloPQRsTUvWxYzabcDeFgHiJkLmNoPQRstuvwxyZ";
 +
  //delete[] myTrans;
 +
  myTrans = myTrans->createInstance(L"lt-Upper", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  printf("★小文字 → 大文字変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 大文字 → 小文字変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"AbcDefGhiJKlmloPQRsTUvWxYzabcDeFgHiJkLmNoPQRstuvwxyZ";
 +
  //delete[] myTrans;
 +
  myTrans = myTrans->createInstance(L"lt-Lower", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  printf("★大文字 → 小文字変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // カタカナ → ひらがな変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"あいうえおアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★カタカナ → ひらがな\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Katakana-Hiragana", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // ひらがな → カタカナ変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"あいうえおぎゃぎゅぎょアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★ひらがな → カタカナ\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Hiragana-Katakana", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // ひらがな → カタカナ→半角変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"あいうえおぎゃぎゅぎょアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★ひらがな → カタカナ→半角変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Hiragana-Katakana", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  myTrans = myTrans->createInstance(L"Fullwidth-Halfwidth", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // ひらがな → ローマ字変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"あいうえおぎゃぎゅぎょアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★ひらがな → ローマ字変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Hiragana-Latin", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // カタカナ → ローマ字変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"あいうえおアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★カタカナ → ローマ字変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Katakana-Latin", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // ローマ字 → ひらがな変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"aiueogyagyugyochachuchepyapyupyovuzazishikemeアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★ローマ字 → ひらがな変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Latin-Hiragana", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // ローマ字 → カタカナ変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"aiueogyagyugyochachuchepyapyupyovuzazishikemeアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★ローマ字 → カタカナ変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Latin-Katakana", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // ローマ字 → カタカナ→半角変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  str = L"aiueogyagyugyochachuchepyapyupyovuzazishikemeアイウエオギャギュギョアイウエオABCDE@;:*+/";
 +
  //delete[] myTrans;
 +
  printf("★ローマ字 → カタカナ→半角変換\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  myTrans = myTrans->createInstance(L"Latin-Katakana", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  myTrans = myTrans->createInstance(L"Fullwidth-Halfwidth", UTRANS_FORWARD, errorNum);
 +
  myTrans->transliterate(str);
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 +
}
 +
 +
</syntaxhighlight2>
 +
 +
出力結果
 +
<syntaxhighlight2 lang="text">
 +
★小文字 → 大文字変換
 +
ABCDEFGHIJKLMLOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ:
 +
 +
★大文字 → 小文字変換
 +
abcdefghijklmlopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:
 +
 +
★カタカナ → ひらがな
 +
あいうえおアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
あいうえおあいうえおぎゃぎゅぎょあいうえおABCDE@;:*+/:
 +
 +
★ひらがな → カタカナ
 +
あいうえおぎゃぎゅぎょアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
アイウエオギャギュギョアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
 +
★ひらがな → カタカナ→半角変換
 +
あいうえおぎゃぎゅぎょアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
アイウエオギャギュギョアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
 +
★ひらがな → ローマ字変換
 +
あいうえおぎゃぎゅぎょアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
aiueogyagyugyoアイウエオg~ャg~ュg~ョアイウエオABCDE@;:*+/:
 +
 +
★カタカナ → ローマ字変換
 +
あいうえおアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
あいうえおaiueogyagyugyoaiueoABCDE@;:*+/:
 +
 +
★ひらがな → ひらがな変換
 +
aiueogyagyugyochachuchepyapyupyovuzazishikemeアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
あいうえおぎゃぎゅぎょちゃちゅちぇぴゃぴゅぴょヴざぜぃしけめアイウエオギャギュギョアイウエオあぶくで@;:*+/:
 +
 +
★ひらがな → カタカナ変換
 +
aiueogyagyugyochachuchepyapyupyovuzazishikemeアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
アイウエオギャギュギョチャチュチェピャピュピョヴザゼィシケメアイウエオギャギュギョアイウエオアブクデ@;:*+/:
 +
 +
★ひらがな → カタカナ→半角変換
 +
aiueogyagyugyochachuchepyapyupyovuzazishikemeアイウエオギャギュギョアイウエオABCDE@;:*+/:
 +
アイウエオギャギュギョチャチュチェピャピュピョヴザゼィシケメアイウエオギャギュギョアイウエオアブクデ@;:*+/:
 +
 +
</syntaxhighlight2>
 +
ひらがな→ローマ字変換が残念な結果になっているようでして、ひらがなと一緒に記述していたカタカナのギャギュギョをg~ャg~ュg~ョと変換してしまったようです。こんな変換をプログラムで提供することは稀れだと思いますが、ICUのバグのようですので、注意して使いましょう。ひらがなローマ字変換とか変換遊びの範囲まで来てるような気がします。やってみようとするところは凄いと思います。ほかにもたくさんの変換マップがあるようです。テキストエディタで特殊な変換を提供してみるのもおもしろいのかもしれません。使いこなせるユーザの方が少なさそうです。半角全角変換も同じような要領で実施できます。これらの変換は基本的にはUnicodeの中で実施され、その後、Unicodeから違う文字コードへの変換をするといった作業にで文字コードへの対応を実現します。次の項目では、これらの変換と同時に文字コードの変換を行う手法についても触れています。
 +
 +
 +
と、その前に、ICUを使わない大文字小文字変換もあるのでそのサンプルを記述します。利用する関数は
 +
 +
 +
大文字→小文字変換
 +
 +
_strlwr、_wcslwr、_mbslwr、_strlwr_l、_wcslwr_l、_mbslwr_l
 +
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/hkxwh33z.aspx
 +
 +
_strlwr_s、_strlwr_s_l、_mbslwr_s、_mbslwr_s_l、_wcslwr_s、_wcslwr_s_l
 +
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/y889wzfw.aspx
 +
 +
<nowiki>***</nowiki>lwr***系の関数になります。例によって_str***に_wcs***、_mbs***と接尾句に****_sや****_lそして****_s_lがつくものの組み合わせが存在しています。
 +
 +
 +
小文字→大文字変換
 +
 +
_strupr、_strupr_l、_mbsupr、_mbsupr_l、_wcsupr_l、_wcsupr
 +
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/sch3dy08.aspx
 +
 +
_strupr_s、_strupr_s_l、_mbsupr_s、_mbsupr_s_l、_wcsupr_s、_wcsupr_s_l
 +
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/sae941fh.aspx
 +
 +
<nowiki>***</nowiki>upr***系の関数になります。こちらも_str***に_wcs***、_mbs***と接尾句に****_sや****_lそして****_s_lがつくものの組み合わせが存在しています。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 +
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 +
 +
#include "UnicodeConverter.h"
 +
 +
 +
using namespace std;
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
int nSizeValue;
 +
 +
_wsetlocale( LC_ALL, L"Japanese");
 +
const char *ppcStr[]={"abCdefG","HijKLmn","OpQRSTu","vWxyZ"};
 +
 +
nSizeValue = sizeof(ppcStr)/sizeof(*ppcStr);
 +
 +
char** ppcStrConv = new char*[nSizeValue];
 +
 +
    printf("★大文字→小文字変換\n");
 +
for(int i = 0; i < nSizeValue; i++){
 +
*(ppcStrConv + i) = new char[strlen(*(ppcStr + i)) + 1];
 +
strcpy_s(*(ppcStrConv + i),strlen(*(ppcStr + i)) + 1, (*(ppcStr + i)));
 +
    _strlwr_s(*(ppcStrConv + i), strlen(*(ppcStrConv + i)) + 1);
 +
}
 +
 +
for(int i = 0; i < nSizeValue; i++){
 +
    printf("%s\n",*(ppcStrConv + i));
 +
}
 +
 +
for(int i = 0; i < nSizeValue; i++){
 +
    delete[] *(ppcStrConv + i);
 +
}
 +
 +
 +
    printf("★小文字→大文字変換\n");
 +
for(int i = 0; i < nSizeValue; i++){
 +
*(ppcStrConv + i) = new char[strlen(*(ppcStr + i)) + 1];
 +
strcpy_s(*(ppcStrConv + i),strlen(*(ppcStr + i)) + 1, (*(ppcStr + i)));
 +
    _strupr_s(*(ppcStrConv + i), strlen(*(ppcStrConv + i)) + 1);
 +
}
 +
 +
for(int i = 0; i < nSizeValue; i++){
 +
    printf("%s\n",*(ppcStrConv + i));
 +
}
 +
 +
for(int i = 0; i < nSizeValue; i++){
 +
    delete[] *(ppcStrConv + i);
 +
}
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
出力結果
 +
<syntaxhighlight2 lang="text">
 +
★大文字→小文字変換
 +
abcdefg
 +
hijklmn
 +
opqrstu
 +
vwxyz
 +
★小文字→大文字変換
 +
ABCDEFG
 +
HIJKLMN
 +
OPQRSTU
 +
VWXYZ
 +
</syntaxhighlight2>
 +
上記のように変換できます。余談になりますが、配列はppcStr[i]のように記述できますが、結局のところ *(ppcStr + i)のように書き直すことができます。配列を宣言したときに、その変数は既にポインタ変数になっているので、宣言したときから、配列変数であることを示すプレフィックス(接頭句)としてpをつけておくのもよいですね。ポインタの配列はppと接頭句が付けられますし、char型ならppcという具合の接頭句の規則を自分は使っています。intはiじゃなくてnを接頭句に使うんですけど。面倒になって接頭句を付け忘れたりもします。そうするとしばらくして、これ何の変数だっけ?という具合になるおじいちゃんぶりを発揮します。たぶん、こうなってくると、「さっき食べたでしょ?おじいちゃん(^_^)。」って言われると、もう断食状態になります。やばいです。人が書いたプログラムと合わせると、また接頭句の規則が乱れて、自分自身では理解ができなくなってくるのです。たぶん自分は大きなプログラムを作るのには向いていませんね。せめて個人的に作っているプログラムの範囲では、規則どおりにやって間違いを減らしたいと思います。チームでやるときは、今までにつちかってきた規則と基盤を胸にきざみつつも応用力が試されます。int nSize[] = {10,20,30};みたいに宣言したときも実はnSizeってのは、この配列の先頭アドレスを保有する変数になってるわけだから、int pnSize[] = {10,20,30};として宣言して、*(pnSize + i) みたいにして、使うのもいいし、pnSize[i]として配列のように使うのもいい。ポインタ変数をあつかってるんだなぁって意識できてるだけマシ。プロになると、まぁそんな細かい事いわなくても自然と意識できるんでしょう。ただ、構造体やらクラスの配列だとpSize[i].mValueとかpSize[i].mFunc()みたいにできるものでも *(pSize + i).xxxとはできず、(*(pSize + i)).mValue のように全体をカッコでくくらないと駄目です。そして、アロー演算子は(*(ポインタ変数)).mValueのようなメンバ変数や関数の参照をおきかえるものでしたから、配列を[]を使わないで表現できることをしっていれば、(pSize + i)->mValueと記述を切り替えるのもたやすいですね。
 +
 +
<nowiki>***</nowiki>upr***や***lwr***関数のように与えられたポインタの実体を置き換える関数では、引数にconstやリテラルを与えることはできないのが常です。確保するメモリ領域を十分に考慮した実体化されたポインタ変数にコピーを作成して、それを引数にしなければなりません。関数によっては、実体の大きさを再定義して別のメモリ空間にさしかえてアドレスをポインタに格納して値を返却してくれます。こういった操作が多いので、動的にメモリを確保したりする手法を知っておくのは大事な知識となります。リテラルを使わないで変数宣言して十分な要素を確保してから、その変数のアドレスをポインタ変数に入れるという手法もありますが、文字数がどうなるかわからないプログラムでは、動的に確保するやり方をマスタしておかないと無駄にメモリを確保しなければならない場面が多くなってしまいます。配列や文字列を活用するには、動的なメモリ確保のやり方を把握しておいた方がいいですね。
 +
 
=='''文字列半角文字全角文字変換'''==
 
=='''文字列半角文字全角文字変換'''==
=='''文字列ファイルパス操作'''==
+
これは、標準関数では対応できませんが、ABCD…UVWXYZ@…abc…xyzをABCD…UVWXYZ@…abc…xyzに変換するような作業です。文字コードによっても求める結果や操作が違うので、ICUを使うのが手っ取り早いでしょう。自分で作成できる範囲の変換処理でもあります。
=='''文字列ファイル名操作'''==
+
 
=='''文字列の検索と置換'''==
+
 
 +
以下はICUを利用した全角→半角変換です。
 +
 
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
 
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
 
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 
 +
 
 +
using namespace std;
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese"));
 +
 
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 全角 → 半角変換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  UConverter* ucnv;
 +
  UErrorCode errorNum = U_ZERO_ERROR;
 +
  int nStrSize;
 +
 
 +
  //変換元となる全角リテラル
 +
  std::wstring wstringResult = L"あいうえおアイウエオABCDE@;:*+/";
 +
  UnicodeString str(wstringResult.c_str());//変換関数にはUnicodeString型を使うので初期値関数を使って初期化。strは変更可能な変数である必要がある。ココでconstは駄目。
 +
 
 +
  //正しい変換結果確認用のリテラル
 +
  std::wstring wstringResult2 = L"あいうえおアイウエオABCDE@;:*+/";
 +
 
 +
  //変換処理の核となる部分
 +
  //変換タイプリテラル
 +
  const UnicodeString convert_type(L"Fullwidth-Halfwidth");
 +
  Transliterator *myTrans = myTrans->createInstance(convert_type, UTRANS_FORWARD, errorNum);//変換方法を設定
 +
  myTrans->transliterate(str);//変換
 +
 
 +
  ucnv = ucnv_open("shift_jis", &errorNum);
 +
  std::string stringResult(str.length() * ucnv_getMaxCharSize(ucnv),'\0');//shift_jisの最大文字サイズと文字数で仮のメモリ確保
 +
  ucnv_close(ucnv);
 +
 
 +
  //UnicodeStringクラスを使った変換例。Unicode→任意の文字コード。
 +
  //但しchar型へしか格納できない変数なのでUnicode→Unicodeのような無意味な変換には適さない。やれるけど…
 +
  nStrSize = str.extract(0, str.length(), &stringResult[0], "shift_jis");//stringResultにShift_JISに変換した内容を保管。
 +
  stringResult.resize(nStrSize);//変換によって判明したメモリサイズに再設定
 +
 
 +
 
 +
  //UnicodeStringのwchar_w型文字列を格納している先頭アドレスを取得できるメンバ関数。
 +
  printf("★UnicodeString変数の出力サンプル\n");
 +
  wprintf(L"%s:\n",str.getTerminatedBuffer());
 +
  printf("\n");
 +
 
 +
  //★半角変換+shift_jis変換のバイトコード表示にためにchar型へ代入して出力
 +
  printf("★半角変換+shift_jis変換\n");
 +
  char* pcStr2 = new char[strlen(stringResult.c_str()) + 1];
 +
  strcpy_s(pcStr2,strlen(stringResult.c_str()) + 1,stringResult.c_str());
 +
  printf("%s %d:\n",stringResult.c_str(),strlen(stringResult.c_str()) + 1);
 +
  for(int i = 0;i < (int)strlen(stringResult.c_str()) + 1;i++){
 +
    printf("%02x:",0x000000FF & *(pcStr2 + i));
 +
  }
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
 
 +
  //★無変換のバイトコード表示にためにw_char型へ代入して出力
 +
  printf("★全角無変換\n");
 +
  wchar_t* pcStr = new wchar_t[wcslen(wstringResult.c_str()) + 1];
 +
  wcscpy_s(pcStr,wcslen(wstringResult.c_str()) + 1,wstringResult.c_str());
 +
  wprintf(L"%s %d:\n",wstringResult.c_str(),wcslen(wstringResult.c_str()) + 1);
 +
  for(int i = 0;i < (int)wcslen(wstringResult.c_str()) + 1;i++){
 +
    printf("%02x:",0x0000FFFF & *(pcStr + i));
 +
  }
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
 
 +
  //★変換後確認用の手動変換リテラルのバイトコード表示にためにw_char型へ代入して出力
 +
  printf("★手動変換(確認用)\n");
 +
  wchar_t* pcStr3 = new wchar_t[wcslen(wstringResult2.c_str()) + 1];
 +
  wcscpy_s(pcStr3,wcslen(wstringResult2.c_str()) + 1,wstringResult2.c_str());
 +
  wprintf(L"%s %d:\n",wstringResult2.c_str(),wcslen(wstringResult2.c_str()) + 1);
 +
  for(int i = 0;i < (int)wcslen(wstringResult2.c_str()) + 1;i++){
 +
    printf("%02x:",0x0000FFFF & *(pcStr3 + i));
 +
  }
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  //★変換処理をしたUnicodeのバイトコード表示にためにw_char型へ代入して出力
 +
  printf("★半角変換Unicode版\n");
 +
  wchar_t* pcStr4 = new wchar_t[wcslen(str.getTerminatedBuffer()) + 1];
 +
  wcscpy_s(pcStr4,wcslen(str.getTerminatedBuffer()) + 1,str.getTerminatedBuffer());
 +
  wprintf(L"%s %d:\n",str.getTerminatedBuffer(),wcslen(str.getTerminatedBuffer()) + 1);
 +
  for(int i = 0;i < (int)wcslen(str.getTerminatedBuffer()) + 1;i++){
 +
    printf("%02x:",0x0000FFFF & *(pcStr4 + i));
 +
  }
 +
  printf("\n");
 +
  printf("\n");
 +
 
 +
  retuen 0;
 +
}
 +
</syntaxhighlight2>
 +
出力結果
 +
<syntaxhighlight2 lang="text">
 +
★UnicodeString変数の出力サンプル
 +
あいうえおアイウエオABCDE@;:*+/:
 +
 
 +
★半角変換+shift_jis変換
 +
あいうえおアイウエオABCDE@;:*+/ 27:
 +
82:a0:82:a2:82:a4:82:a6:82:a8:b1:b2:b3:b4:b5:41:42:43:44:45:40:3b:3a:2a:2b:2f:00:
 +
 
 +
★全角無変換
 +
あいうえおアイウエオABCDE@;:*+/ 22:
 +
3042:3044:3046:3048:304a:30a2:30a4:30a6:30a8:30aa:ff21:ff22:ff23:ff24:ff25:ff20:ff1b:ff1a:ff0a:ff0b:ff0f:0000:
 +
 
 +
★手動変換(確認用)
 +
あいうえおアイウエオABCDE@;:*+/ 22:
 +
3042:3044:3046:3048:304a:ff71:ff72:ff73:ff74:ff75:0041:0042:0043:0044:0045:0040:003b:003a:002a:002b:002f:0000:
 +
 
 +
★半角変換Unicode版
 +
あいうえおアイウエオABCDE@;:*+/ 22:
 +
3042:3044:3046:3048:304a:ff71:ff72:ff73:ff74:ff75:0041:0042:0043:0044:0045:0040:003b:003a:002a:002b:002f:0000:
 +
</syntaxhighlight2>
 +
という感じに変換ができます。ICUの使い方さえわかれば、いろいろできますね。記事を書きながら、自分もようやくわかってきた感じ。ぉぃ。
 +
 
 +
 
 +
サンプルプログラムのコメントを読んでいただければ、理解できると思います。逆の変換はconverttypeを書き換えるだけです。
 +
 
 +
 
 +
createInstanceで指定できる変換タイプ名は以下のとおりです。
 +
<syntaxhighlight2 lang="text">
 +
Arabic-Latin
 +
Arabic-Latin/BGN
 +
Armenian-Latin
 +
Armenian-Latin/BGN
 +
Azerbaijani-Latin/BGN
 +
Belarusian-Latin/BGN
 +
Bengali-Devanagari
 +
Bengali-Gujarati
 +
Bengali-Gurmukhi
 +
Bengali-Kannada
 +
Bengali-Latin
 +
Bengali-Malayalam
 +
Bengali-Oriya
 +
Bengali-Tamil
 +
Bengali-Telugu
 +
Bopomofo-Latin
 +
Bulgarian-Latin/BGN
 +
Cyrillic-Latin
 +
Devanagari-Bengali
 +
Devanagari-Gujarati
 +
Devanagari-Gurmukhi
 +
Devanagari-Kannada
 +
Devanagari-Latin
 +
Devanagari-Malayalam
 +
Devanagari-Oriya
 +
Devanagari-Tamil
 +
Devanagari-Telugu
 +
Digit-Tone
 +
Fullwidth-Halfwidth
 +
Georgian-Latin
 +
Georgian-Latin/BGN
 +
Greek-Latin
 +
Greek-Latin/BGN
 +
Greek-Latin/UNGEGN
 +
Gujarati-Bengali
 +
Gujarati-Devanagari
 +
Gujarati-Gurmukhi
 +
Gujarati-Kannada
 +
Gujarati-Latin
 +
Gujarati-Malayalam
 +
Gujarati-Oriya
 +
Gujarati-Tamil
 +
Gujarati-Telugu
 +
Gurmukhi-Bengali
 +
Gurmukhi-Devanagari
 +
Gurmukhi-Gujarati
 +
Gurmukhi-Kannada
 +
Gurmukhi-Latin
 +
Gurmukhi-Malayalam
 +
Gurmukhi-Oriya
 +
Gurmukhi-Tamil
 +
Gurmukhi-Telugu
 +
Halfwidth-Fullwidth
 +
Han-Latin
 +
Han-Latin/Names
 +
Hangul-Latin
 +
Hans-Hant
 +
Hant-Hans
 +
Hebrew-Latin
 +
Hebrew-Latin/BGN
 +
Hiragana-Katakana
 +
Hiragana-Latin
 +
IPA-XSampa
 +
Jamo-Latin
 +
Kannada-Bengali
 +
Kannada-Devanagari
 +
Kannada-Gujarati
 +
Kannada-Gurmukhi
 +
Kannada-Latin
 +
Kannada-Malayalam
 +
Kannada-Oriya
 +
Kannada-Tamil
 +
Kannada-Telugu
 +
Katakana-Hiragana
 +
Katakana-Latin
 +
Katakana-Latin/BGN
 +
Kazakh-Latin/BGN
 +
Kirghiz-Latin/BGN
 +
Korean-Latin/BGN
 +
Latin-ASCII
 +
Latin-Arabic
 +
Latin-Armenian
 +
Latin-Bengali
 +
Latin-Bopomofo
 +
Latin-Cyrillic
 +
Latin-Devanagari
 +
Latin-Georgian
 +
Latin-Greek
 +
Latin-Greek/UNGEGN
 +
Latin-Gujarati
 +
Latin-Gurmukhi
 +
Latin-Hangul
 +
Latin-Hebrew
 +
Latin-Hiragana
 +
Latin-Jamo
 +
Latin-Kannada
 +
Latin-Katakana
 +
Latin-Malayalam
 +
Latin-NumericPinyin
 +
Latin-Oriya
 +
Latin-Syriac
 +
Latin-Tamil
 +
Latin-Telugu
 +
Latin-Thaana
 +
Latin-Thai
 +
Macedonian-Latin/BGN
 +
Malayalam-Bengali
 +
Malayalam-Devanagari
 +
Malayalam-Gujarati
 +
Malayalam-Gurmukhi
 +
Malayalam-Kannada
 +
Malayalam-Latin
 +
Malayalam-Oriya
 +
Malayalam-Tamil
 +
Malayalam-Telugu
 +
Maldivian-Latin/BGN
 +
Mongolian-Latin/BGN
 +
NumericPinyin-Latin
 +
NumericPinyin-Pinyin
 +
Oriya-Bengali
 +
Oriya-Devanagari
 +
Oriya-Gujarati
 +
Oriya-Gurmukhi
 +
Oriya-Kannada
 +
Oriya-Latin
 +
Oriya-Malayalam
 +
Oriya-Tamil
 +
Oriya-Telugu
 +
Pashto-Latin/BGN
 +
Persian-Latin/BGN
 +
Pinyin-NumericPinyin
 +
Publishing-Any
 +
Russian-Latin/BGN
 +
Serbian-Latin/BGN
 +
Simplified-Traditional
 +
Syriac-Latin
 +
Tamil-Bengali
 +
Tamil-Devanagari
 +
Tamil-Gujarati
 +
Tamil-Gurmukhi
 +
Tamil-Kannada
 +
Tamil-Latin
 +
Tamil-Malayalam
 +
Tamil-Oriya
 +
Tamil-Telugu
 +
Telugu-Bengali
 +
Telugu-Devanagari
 +
Telugu-Gujarati
 +
Telugu-Gurmukhi
 +
Telugu-Kannada
 +
Telugu-Latin
 +
Telugu-Malayalam
 +
Telugu-Oriya
 +
Telugu-Tamil
 +
Thaana-Latin
 +
Thai-Latin
 +
Tone-Digit
 +
Traditional-Simplified
 +
Turkmen-Latin/BGN
 +
Ukrainian-Latin/BGN
 +
Uzbek-Latin/BGN
 +
XSampa-IPA
 +
az-Lower
 +
az-Title
 +
az-Upper
 +
ch-ch_FONIPA
 +
cs-cs_FONIPA
 +
cs-ja
 +
cs-ko
 +
cs_FONIPA-ja
 +
cs_FONIPA-ko
 +
dsb-dsb_FONIPA
 +
el-Lower
 +
el-Title
 +
el-Upper
 +
es-am
 +
es-es_FONIPA
 +
es-ja
 +
es-zh
 +
es_419-ja
 +
es_419-zh
 +
es_FONIPA-am
 +
es_FONIPA-es_419_FONIPA
 +
es_FONIPA-ja
 +
es_FONIPA-zh
 +
it-am
 +
it-ja
 +
ja_Latn-ko
 +
ja_Latn-ru
 +
la-la_FONIPA
 +
lt-Lower
 +
lt-Title
 +
lt-Upper
 +
nl-Title
 +
pl-ja
 +
pl-pl_FONIPA
 +
pl_FONIPA-ja
 +
ro-ja
 +
ro-ro_FONIPA
 +
ro_FONIPA-ja
 +
ru-ja
 +
ru-zh
 +
sk-ja
 +
sk-sk_FONIPA
 +
sk_FONIPA-ja
 +
tlh-tlh_FONIPA
 +
tr-Lower
 +
tr-Title
 +
tr-Upper
 +
uz_Cyrl-uz_Latn
 +
uz_Latn-uz_Cyrl
 +
yo-yo_BJ
 +
zh_Latn_PINYIN-ru
 +
Any-Null
 +
Any-Lower
 +
Any-Upper
 +
Any-Title
 +
Any-Name
 +
Name-Any
 +
Any-Remove
 +
Any-Hex/Unicode
 +
Any-Hex/Java
 +
Any-Hex/C
 +
Any-Hex/XML
 +
Any-Hex/XML10
 +
Any-Hex/Perl
 +
Any-Hex
 +
Hex-Any/Unicode
 +
Hex-Any/Java
 +
Hex-Any/C
 +
Hex-Any/XML
 +
Hex-Any/XML10
 +
Hex-Any/Perl
 +
Hex-Any
 +
Any-NFC
 +
Any-NFKC
 +
Any-NFD
 +
Any-NFKD
 +
Any-FCD
 +
Any-FCC
 +
Any-ch_FONIPA
 +
Any-Latin
 +
Any-Telugu
 +
Any-Gurmukhi
 +
Any-Gujarati
 +
Any-Malayalam
 +
Any-Oriya
 +
Any-Devanagari
 +
Any-Kannada
 +
Any-Tamil
 +
Any-cs_FONIPA
 +
Any-ru
 +
Any-Bengali
 +
Any-uz_Latn
 +
Any-Katakana
 +
Any-ro_FONIPA
 +
Any-zh
 +
Any-yo_BJ
 +
Any-am
 +
Any-es_419_FONIPA
 +
Any-es_FONIPA
 +
Any-sk_FONIPA
 +
Any-Hant
 +
Any-Hans
 +
Any-Hiragana
 +
Any-la_FONIPA
 +
Any-dsb_FONIPA
 +
Any-Syriac
 +
Any-Greek
 +
Any-Greek/UNGEGN
 +
Any-Cyrillic
 +
Any-Hangul
 +
Any-Bopomofo
 +
Any-Arabic
 +
Any-Thai
 +
Any-Armenian
 +
Any-Thaana
 +
Any-Georgian
 +
Any-Hebrew
 +
Any-uz_Cyrl
 +
</syntaxhighlight2>
 +
 
 +
=='''文字列の検索と置換・正規表現'''==
 +
文字列の検索と置換は、メモ帳でCtrl+Fとかで検索するようなものや置換する処理と同じように目的の文字列を探す方法とファイルの検索のようにワイルドカードを使う方法があり、検索して一致した文字列を置き換えるという処理も同じみですが、もうひとつの検索と置換のやり方として、正規表現(Regular Expresion)という手法があります。これはワイルドカードによる指定にさらに文字列の先頭にある特定の文字列があって、さらに特定の文字列にはさまれた部分があって、文字列の最後尾にも特定の文字があったら、その挟まれた文字の先頭グループ1、グループ2、…グループnとして、順次、変換法則にしたがって変換といった複雑な指定が可能になる手法です。正規表現は複雑なこともできるし、単純なこともできる。できるだけ複雑なモノを単純にしてから操作をする手法など、検索と置換には多岐にわたる手法が存在します。また、検索効率をあげる手法もありかなり文字列操作の中でも奥深い技術を必要とする操作です。まずは単純な検索と置換。それと簡単な正規表現にチャレンジしてみましょう。正規表現の使い方をここでは取り上げて、正規表現による問題解決手法は、ここ以外での説明にしたいと思います。
 +
 
 +
以下、ICUのRegexを使った検索と置換の正規表現による処理のサンプルです。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
 
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 
 +
 
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
 
 +
using namespace std;
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
 
 +
  _tsetlocale(LC_ALL, _T("Japanese"));
 +
 
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 正規表現分割
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  UParseError error;
 +
  UErrorCode  status = U_ZERO_ERROR;
 +
  int nFindCnt = 0;
 +
 +
 
 +
  printf("★正規表現検索\n");
 +
  UnicodeString regex = L"[,/とやも]";//正規表現検索文字
 +
  RegexPattern* pattern = RegexPattern::compile(regex, error, status);//パターンを登録(コンパイル)
 +
  assert( U_SUCCESS(status) );
 +
 +
  UnicodeString input = L"リンゴとミカン/ナシとモモ,ごはんやおかず/おさけもつまみ,programと技術";
 +
  assert( U_SUCCESS(status) );
 +
  RegexMatcher* matcher = pattern->matcher(input, status);//入力値での正規表現検索処理をmatcherへ格納
 +
 
 +
 
 +
  printf("★パターンマッチ結果出力\n");
 +
  while ( matcher->find() ) {
 +
  //それぞれのマッチグループの出力。パターンに部分一致(.)が無い場合はつねにグループは1で要素0番のみ
 +
  for ( int32_t i = 0; i <= matcher->groupCount(); i++ ) {
 +
      std::wcout << L"[" << matcher->start(i,status)
 +
                << L"," << matcher->end(i,status)
 +
                << L"]" << matcher->group(i,status).getTerminatedBuffer()
 +
                << std::endl;
 +
      assert( U_SUCCESS(status) );
 +
    }
 +
    //whileループ回数をカウントして分割数を記録
 +
    nFindCnt++;
 +
    std::wcout << std::endl;
 +
  }
 +
 +
  //分割した回数のUnicodeString変数の配列を確保して分割結果を配列に格納。
 +
  printf("★検索された分割文字トークンの数\n");
 +
  std::wcout << nFindCnt << std::endl;
 +
  printf("\n");
 +
 
 +
  UnicodeString* pfruits = new UnicodeString[nFindCnt + 1];
 +
  int32_t splits = pattern->split(input, pfruits, nFindCnt + 1, status);//登録されたパターンで分割処理
 +
  //splitの引数には入力文字列,要素が確保された出力文字列配列変数,分割数,実行結果
 +
 +
  assert( U_SUCCESS(status) );
 +
  printf("★分割抽出した配列の出力\n");
 +
  //分割によりそれぞれに格納された文字を文字列配列の全出力で確認
 +
  for ( int32_t i = 0; i < splits; i++ ) {
 +
    std::wcout << pfruits[i].getTerminatedBuffer() << std::endl;
 +
    //std::wcout << (*(pfruits + i)).getTerminatedBuffer() << std::endl;こうやって表現しても同じ。
 +
  }
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 正規表現置換
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  UnicodeString replacement = L"+";
 +
 
 +
 +
  /*
 +
  * 先頭置換 : replaceFirst
 +
  */
 +
  printf("★先頭置換\n");
 +
  UnicodeString result = matcher->replaceFirst(replacement, status);
 +
  assert( U_SUCCESS(status) );
 +
  std::wcout << result.getTerminatedBuffer() << std::endl;
 +
 +
  /*
 +
  * 一括置換 : replaceAll
 +
  */
 +
  printf("★一括置換\n");
 +
  result = matcher->replaceAll(replacement, status);
 +
  assert( U_SUCCESS(status) );
 +
  std::wcout << result.getTerminatedBuffer() << std::endl;
 +
 +
  /*
 +
  * 追記置換 : appendReplacement/appendAll 前方から逐次置換してresultに追加していく方式
 +
  */
 +
  printf("★追記置換\n");
 +
  result = L"";
 +
  matcher->reset();
 +
  while ( matcher->find() ) {
 +
    matcher->appendReplacement(result, replacement, status);
 +
    assert( U_SUCCESS(status) );
 +
    //最後の置換完了状態で一時出力
 +
    std::wcout << result.getTerminatedBuffer() << std::endl;
 +
  }
 +
 +
 +
  //最後の置換以降の残った文字列を追加
 +
  matcher->appendTail(result);
 +
  std::wcout << result.getTerminatedBuffer() << std::endl;
 +
 +
  printf("\n");
 +
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  // 部分一致
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  /*
 +
  * 部分マッチ"(.)"の置換
 +
  */
 +
  regex = L"(.)([,/とやも]|$)";//正規表現検索文字 区切り文字or終端の一文字手前 $1を置換 区切り文字or終端は $2
 +
  replacement = L"★";//伏字に置換
 +
  result = input;
 +
 
 +
  pattern = RegexPattern::compile(regex, error, status);
 +
  matcher = pattern->matcher(input, status);
 +
 
 +
 
 +
  printf("★パターンマッチ結果出力\n");
 +
  while ( matcher->find() ) {
 +
  //それぞれのマッチグループの出力。パターンに部分一致(.)が無い場合はつねにグループは1で要素0番のみ
 +
  for ( int32_t i = 0; i <= matcher->groupCount(); i++ ) {
 +
      std::wcout << L"[" << matcher->start(i,status)
 +
                << L"," << matcher->end(i,status)
 +
                << L"]" << matcher->group(i,status).getTerminatedBuffer()
 +
                << std::endl;
 +
      assert( U_SUCCESS(status) );
 +
    }
 +
    //whileループ回数をカウントして分割数を記録
 +
    nFindCnt++;
 +
    std::wcout << std::endl;
 +
  }
 +
 
 +
 
 +
  typedef std::pair<int32_t,int32_t> range_type;
 +
  std::vector<range_type> matches;
 +
 
 +
 
 +
  matcher->reset();
 +
  while ( matcher->find() ) {
 +
    // 第一グループを保存する 条件:$1 が存在して、検索の開始文字位置と終了文字位置が0以上なら保存
 +
if(matcher->groupCount() >= 1 && matcher->start(1,status) > 0 && matcher->end(1,status) > 0 ){
 +
      matches.push_back(range_type(matcher->start(1,status), matcher->end(1,status)));
 +
      assert( U_SUCCESS(status) );
 +
}
 +
  }
 +
  // 末尾から置換
 +
  while ( !matches.empty() ) {
 +
    range_type range = matches.back();
 +
    matches.pop_back();
 +
    result.replace(range.first, range.second - range.first, replacement);
 +
  }
 +
  printf("★部分一致パターンの置換結果出力\n");
 +
  std::wcout << result.getTerminatedBuffer() << std::endl;
 +
 
 +
  delete[] pfruits;
 +
  delete matcher;
 +
  delete pattern;
 +
 
 +
 
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
出力結果
 +
<syntaxhighlight2 lang="text">
 +
★正規表現検索
 +
★パターンマッチ結果出力
 +
[3,4]と
 +
 
 +
[7,8]/
 +
 
 +
[10,11]と
 +
 
 +
[13,14],
 +
 
 +
[17,18]や
 +
 
 +
[21,22]/
 +
 
 +
[25,26]も
 +
 
 +
[29,30],
 +
 
 +
[37,38]と
 +
 
 +
★検索された分割文字トークンの数
 +
9
 +
 
 +
★分割抽出した配列の出力
 +
リンゴ
 +
ミカン
 +
ナシ
 +
モモ
 +
ごはん
 +
おかず
 +
おさけ
 +
つまみ
 +
program
 +
技術
 +
 
 +
★先頭置換
 +
リンゴ+ミカン/ナシとモモ,ごはんやおかず/おさけもつまみ,programと技術
 +
★一括置換
 +
リンゴ+ミカン+ナシ+モモ+ごはん+おかず+おさけ+つまみ+program+技術
 +
★追記置換
 +
リンゴ+
 +
リンゴ+ミカン+
 +
リンゴ+ミカン+ナシ+
 +
リンゴ+ミカン+ナシ+モモ+
 +
リンゴ+ミカン+ナシ+モモ+ごはん+
 +
リンゴ+ミカン+ナシ+モモ+ごはん+おかず+
 +
リンゴ+ミカン+ナシ+モモ+ごはん+おかず+おさけ+
 +
リンゴ+ミカン+ナシ+モモ+ごはん+おかず+おさけ+つまみ+
 +
リンゴ+ミカン+ナシ+モモ+ごはん+おかず+おさけ+つまみ+program+
 +
リンゴ+ミカン+ナシ+モモ+ごはん+おかず+おさけ+つまみ+program+技術
 +
 
 +
★パターンマッチ結果出力
 +
[2,4]ゴと
 +
[2,3]ゴ
 +
[3,4]と
 +
 
 +
[6,8]ン/
 +
[6,7]ン
 +
[7,8]/
 +
 
 +
[9,11]シと
 +
[9,10]シ
 +
[10,11]と
 +
 
 +
[12,14]モ,
 +
[12,13]モ
 +
[13,14],
 +
 
 +
[16,18]んや
 +
[16,17]ん
 +
[17,18]や
 +
 
 +
[20,22]ず/
 +
[20,21]ず
 +
[21,22]/
 +
 
 +
[24,26]けも
 +
[24,25]け
 +
[25,26]も
 +
 
 +
[28,30]み,
 +
[28,29]み
 +
[29,30],
 +
 
 +
[36,38]mと
 +
[36,37]m
 +
[37,38]と
 +
 
 +
[39,40]術
 +
[39,40]術
 +
[40,40]
 +
 
 +
★部分一致パターンの置換結果出力
 +
リン★とミカ★/ナ★とモ★,ごは★やおか★/おさ★もつま★,progra★と技★
 +
</syntaxhighlight2>
 +
149行目以降に記述した部分一致からのプログラムはやや複雑な表記になっていますが、これはICUに準備された関数だけでは部分一致の処理ができないために自分で工夫をしなければならないことに起因しています。
 +
 
 +
 
 +
169行目のtypedef関数は宣言を置き換えるための命令文になります。std::pair<int32_t,int32_t>という構造体定義をrange_typeに置き換えるということを意味しています。
 +
またpairの後ろにある<int32_t,int32_t>というのはpairという構造体がテンプレート構造体として準備されていて、二つの型名を引数にとる必要がありここではint32_tという型を2つ指定して、pairというテンプレート構造体で使う2つの型はどちらもint型で使いますというテンプレート構造体の利用方法を記述している部分になります。pair構造体は2つの変数を対にして記憶するための構造体になっています。
 +
 
 +
 
 +
170行目のvectorという関数もテンプレートクラスになっていて、要するにstd::vector< std::pair<int32_t,int32_t> >という宣言をしたのと同じことで、vectorクラスはstd::pair<int32_t,int32_t>という型で使いますという準備をした上でその変数として、matchesというものを使うという定義になります。vecotrは動的にメモリを確保するのを支援してくれるクラスで、push_backという関数の引数にstd::pair<int32_t,int32_t>(int型の数値,int型の数値)という構造体が持つコンストラクタによって返されるpair構造体型のポインタを記録しています。引数には検索した文字の開始位置と終了位置を入れています。vectorのbackという関数で最後に格納したポインタを返してくれるので、range_typeつまりstd::pair<int32_t,int32_t>型のrangeというポインタ変数にコピーしています。std::pairのメンバ変数firstにコンストラクタで使用した一つ目引数の数値が取得でき、メンバ変数secondで二つ目の引数の数値が取得できます。vecotorクラスのpop_back()という関数の呼び出しによって最後に格納したポインタを消すという処理をしてくれます。こうやってfind()で検索するすべての検索位置をvectorクラスの中にpair構造体でセットした2つのint型整数で検索された文字の開始位置と終了位置を記憶する仕組みです。テンプレートクラスやテンプレート構造体やクラスについて理解する必要があります。vectorのempty()関数は格納されたものが無くなったらtrueを返す関数で、while文のループ条件として!matches.empty()のようにして、空っぽではないあいだ繰り返すという処理になっています。
 +
 
 +
 
 +
部分一致の処理は難しいので、typedef関数とクラスと構造体のコンストラクタとテンプレートクラスとクラスのメンバ関数およびクラスのメンバ変数、更には標準クラスであるvectorクラスとpair構造体について理解してから戻ってくるとよいかもしれません。
 +
 
 +
 
 +
ICUを使わない文字列検索としてはstrchrのような***chr系の一文字検索関数があります。見つかった位置のByte数を返してくれます。ICUの正規表現に比べると機能性は低いです。一文字を引数にするとき符号なし整数型にしなければいけないあたりは、初期値を与えての検索は楽ですが、実際に一文字の文字列から検索しようとすると大変なのかもしれません。実際に数えてみないと、一文字あたりが、1バイトなのか2バイトなのかわからないし…。こういう一文字検索だけを行う関数って使う人いるんだろか?って思う。やっぱstrstr系使うよね。
 +
 
 +
 
 +
以下のサンプルでは文字列の検索をするもので、以下の関数も使っています。
 +
_strinc、_wcsinc、_mbsinc、_mbsinc_l のようなポインタ変数を1文字を進める関数。文字列の先頭を示していたものが次の文字になります。大元の文字列のポインタ変数を操作すると先頭文字を見失うので、通常は、同じアドレスを指し示すポインタ変数を複製して、複製したポインタ変数で操作します。
 +
詳細は、以下のアドレスのとおりです。
 +
 
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/ex0hs2ad.aspx
 +
 
 +
_strdec、_wcsdec、_mbsdec、_mbsdec_l 一文字戻るにはこのような関数があります。
 +
 
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/cf10bexy.aspx
 +
 
 +
 
 +
そして、strchr、wcschr、_mbschr、_mbschr_l は以下のような関数があって、ここでは_mbschrのサンプルを作りました。
 +
 
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/b34ccac3.aspx
 +
 
 +
 
 +
後方から検索するものとしては、strrchr、wcsrchr、_mbsrchr、_mbsrchr_lがあり、ここでは_mbsrchrを使っています。
 +
 
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/ftw0heb9.aspx
 +
 
 +
 
 +
更に文字列中を文字列で検索するものとしては、strstr、wcsstr、_mbsstr、_mbsstr_lがあり、ここでは_mbsstrを使っています。
 +
 
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/z9da80kz.aspx
 +
 
 +
 
 +
マルチバイト文字の1文字を数値として取得する関数として
 +
 
 +
_strnextc、_wcsnextc、_mbsnextc、_mbsnextc_lがあり、ここでは_mbsnetcを使いました。その下に関数を使わない場合の数値の取得方法についても処理を記述しました。1文字バイト構成を羅列したときの整数値に変換した数値を抜き出したいという特殊な用途に応える関数になっています。自分で計算するのは面倒な手続きが必要になりそうなことがサンプルからわかると思います。
 +
 
 +
http://msdn.microsoft.com/ja-jp/library/vstudio/5zsfy4ab.aspx
 +
 
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 
 +
 
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
 
 +
using namespace std;
 +
 
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
 
 +
  int SingleChr = 'r';
 +
  unsigned int mbSingleString; 
 +
  unsigned int mbSingleStringNextC;
 +
  unsigned int nKeta;
 +
 
 +
  char pcSingleStr[] = "列";
 +
  char pcStr[] = "文字列";
 +
 
 +
  char pcString[] = "日本語文字の検索用文字列です。The quick brown dog jumps over the lazy fox";
 +
  char fmt1[] =  "        1        2        3        4        5        6";
 +
  char fmt2[] =  "123456789012345678901234567890123456789012345678901234567890123456789";
 +
 
 +
  char *pcPos;
 +
  unsigned char *pucPos;
 +
  unsigned char *pucRusultPos;
 +
 
 +
  int result;
 +
  int result2;
 +
 
 +
  printf_s( "文字列検索:\n\n      %s\n", pcString );
 +
  printf_s( "      %s\n      %s\n\n", fmt1, fmt2 );
 +
 
 +
 
 +
 
 +
  //★マルチバイト対応1文字の文字列で検索。
 +
  printf_s( "★マルチバイト対応検索\n");
 +
 
 +
  pucPos = (unsigned char*)pcSingleStr;
 +
 
 +
  mbSingleStringNextC = _mbsnextc(pucPos);
 +
  printf_s( "MultiByteString検索文字 SigngleWord:%04x(%s)\n", mbSingleStringNextC, pcSingleStr);
 +
 
 +
  pucPos = _mbsinc(pucPos);//一文字分ポインタを進める関数
 +
  result = (int)(pucPos - (unsigned char*)pcSingleStr);
 +
  mbSingleString = 0;
 +
  nKeta = 1;
 +
  for(int n = 0; n < result; n++){
 +
    mbSingleString = mbSingleString + (*(pucPos - (n + 1))) * (nKeta);
 +
    printf_s( "%02x \n", (*(pucPos - (n + 1))));
 +
nKeta = nKeta * 0x100;
 +
  }
 +
 
 +
  //printf_s( "%02x%02x\n", *(pucPos - 2), *(pucPos - 1));このカタチをunsigned int の変数に変形したのが mbSingleString
 +
  //unsigned int mbstringString = '';とかでも検索できますが、strcpy関数とかでコピーしてきた一文字の文字列でサンプル
 +
 
 +
  printf_s( "MultiByteString検索文字 SigngleWord:%04x(%s)\n", mbSingleString, pcSingleStr);
 +
  printf_s( "incriment:%d[Byte]\n\n",result);
 +
 
 +
  pucRusultPos = _mbschr((unsigned char*)pcString, mbSingleString);
 +
  result2 = (int)(pucRusultPos - (unsigned char*)pcString + 1);
 +
  if ( pucRusultPos != NULL )
 +
    printf_s( "検索結果:  最初の %04x(%s) が見つかった位置は %d[Byte]目\n", mbSingleString, pcSingleStr, result2 );
 +
  else
 +
    printf_s( "検索結果:  %s not found\n\n", pcSingleStr );
 +
 
 +
 
 +
  //★シングルバイト文字検索。
 +
  printf_s( "\n\n");
 +
  printf_s( "★シングルバイト文字の初期値による検索\n");
 +
  printf_s( "検索文字:  %c\n", SingleChr );
 +
 
 +
 
 +
  //前方検索
 +
  pcPos = strchr( pcString, SingleChr );
 +
  result = (int)(pcPos - pcString + 1);
 +
  if ( pcPos != NULL )
 +
    printf_s( "検索結果:  最初の %c が見つかった位置は %d[Byte]目\n", SingleChr, result );
 +
  else
 +
    printf_s( "検索結果:  %c not found\n", SingleChr );
 +
 
 +
 
 +
  //後方検索
 +
  pcPos = strrchr( pcString, SingleChr );
 +
  result = (int)(pcPos - pcString + 1);
 +
  if ( pcPos != NULL )
 +
    printf_s( "検索結果:  最後に %c が見つかった位置は %d[Byte]目\n", SingleChr, result );
 +
  else
 +
    printf_s( "検索結果:\t%c not found\n", SingleChr );
 +
 
 +
 
 +
  //★文字列への文字列検索。
 +
  printf_s( "\n\n");
 +
  printf_s( "★文字列への文字列検索\n");
 +
  printf_s( "検索文字:  %s\n", pcStr );
 +
 
 +
  pucRusultPos = _mbsstr((unsigned char*)pcString, (unsigned char*)pcStr);
 +
  result2 = (int)(pucRusultPos - (unsigned char*)pcString + 1);
 +
  if ( pucRusultPos != NULL )
 +
    printf_s( "検索結果:  最初の (%s) が見つかった位置は %d[Byte]目\n", pcStr, result2 );
 +
  else
 +
    printf_s( "検索結果:  %s not found\n\n", pcSingleStr ); 
 +
  return 0;
 +
}
 +
 
 +
 
 +
</syntaxhighlight2>
 +
出力結果 等幅フォントに設定したテキストエディタに張り付けると、もう少し見やすくなります。
 +
 
 +
文字列検索:
 +
 
 +
      日本語文字の検索用文字列です。The quick brown dog jumps over the lazy fox
 +
                1        2        3        4        5        6
 +
      123456789012345678901234567890123456789012345678901234567890123456789
 +
 +
★マルチバイト対応検索
 +
MultiByteString検索文字 SigngleWord:97f1(列)
 +
f1
 +
97
 +
MultiByteString検索文字 SigngleWord:97f1(列)
 +
incriment:2[Byte]
 +
 +
検索結果:  最初の 97f1(列) が見つかった位置は 23[Byte]目
 +
 +
 +
★シングルバイト文字の初期値による検索
 +
検索文字:  r
 +
検索結果:  最初の r が見つかった位置は 42[Byte]目
 +
検索結果:  最後に r が見つかった位置は 60[Byte]目
 +
 +
 +
★文字列への文字列検索
 +
検索文字:  文字列
 +
検索結果:  最初の (文字列) が見つかった位置は 19[Byte]目
 +
 
 +
文字列全体の一致による検索の関数はstrstr関数で、***str系の関数です。他にも文字セット検索なるものはあります。
 +
 
 
=='''文字列ファイルへの入出力'''==
 
=='''文字列ファイルへの入出力'''==
*比較
+
ここまで、やってきた手法で文字列をファイルに保存することをやってみます。文字列はかならずしもテキストファイルとして保管されるものではありません。DBに格納されるもの、バイナリファイルに格納されるもの、圧縮されるもの、様々です。ここでは一般的なテキストファイルとして保管し、簡単なテキストDBとしての操作について作業します。
*一致
+
 
*区切り文字分割
+
 
*探索
+
まずは、テキストから文字列の読み込みのサンプルをぺたぺたとしたいのですが、一応、標準の関数でサポートされている範囲の文字コードはShiftJISとUTF-8とUTF-16でVisualStudio2005からfopenやwfopen関数が拡張されて、2番目の引数ファイルオープンモード文字列に ccs=UTF-8とかccs=UTF-16LEと記載することで、ファイルポインタをつかってのストリーム入力時fgetws関数でワイド文字(UNICODE)に変換してくれます。テキストは自分で作るといいのですが、自分は以下のような簡単なテキストを文字コード別に準備したので、参考にリンクを張っておきます。なんてことないテキストファイルなので、無価値なのものです。
*正規表現 regex_match
+
 
*文字列の型変換
+
[[メディア:文字列操作サンプル用文字コード4種セット.lzh | 文字列操作サンプル用文字コード4種セット.lzh]]
*文字コード変換
+
 
*大文字小文字変換
+
JISやEUCといったサポートされていない文字コードのテキストファイルの場合はバイナリモードでファイルを読み込む必要があり、1バイトづつ処理をして、文字列として変換したりすることで、文字列操作を行います。変換そのものは先に紹介した文字コード変換で対応することが可能ですので、とりこんだバイナリコードをどうやって変換関数のなかに収めるかというのが課題になると思います。その例はのちほど考えるとして、まずはオーソドックスなファイルの読み込みからやってみます。
*半角文字全角文字変換
+
 
*ファイルパス操作
+
<syntaxhighlight2 lang="cpp" line start="1">
*ファイル名操作
+
#pragma once
*拡張子取得
+
#include "stdafx.h"
*文字列の検索と置換
+
#include <stdlib.h>
*ファイルへの入出力
+
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 
 +
#include <sys/timeb.h>  //Timeb型構造体
 +
 
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
 
 +
using namespace std;
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese")); //ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 
 +
_locale_t localeJpanease;
 +
localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 
 +
  FILE* pfileText;
 +
  errno_t errNo;
 +
  size_t* psizeRuturnValue = new size_t;
 +
  int nCloseCnt;
 +
  wchar_t pwcStrFilePathNewTexttoBinary[] = L"C:\\...\\...\\...\\new_test_t2b.txt";//...\\...\\...には正確なパスを指定。
 +
  wchar_t pwcStrFilePathNewUTF16LE[]      = L"C:\\...\\...\\...\\new_test_utf16b.txt";
 +
  wchar_t pwcStrFilePathNewUTF8[]        = L"C:\\...\\...\\...\\new_test_utf8b.txt";
 +
  wchar_t pwcStrFilePathNewUTF8BOM[]      = L"C:\\...\\...\\...\\new_test_utf8bomb.txt";
 +
  wchar_t pwcStrFilePathShiftJIS[]        = L"C:\\...\\...\\...\\test.txt";
 +
  wchar_t pwcStrFilePathJIS[]            = L"C:\\...\\...\\...\\test_jis.txt";
 +
  wchar_t pwcStrFilePathEUC[]            = L"C:\\...\\...\\...\\test_euc.txt";
 +
  wchar_t pwcStrFilePathUtf8Bom[]        = L"C:\\...\\...\\...\\test_utf8.txt";
 +
  wchar_t pwcStrFilePathUtf8[]            = L"C:\\...\\...\\...\\test_utf8N.txt";
 +
  wchar_t pwcStrFilePathUtf16LE[]        = L"C:\\...\\...\\...\\test_utf16LE.txt";
 +
 
 +
  wchar_t pwcStrGohan[] = L"ごはんを食べたよ。\r\n";//\r\n = CR LF = 0x0D 0x0A
 +
  char* pcStrStream;
 +
  wchar_t* pwcStrStream;
 +
  char* pcStrErr;
 +
  wchar_t* pwcStrErr;
 +
 
 +
  pcStrStream = new char[1024];
 +
  pwcStrStream = new wchar_t[1024];
 +
  pcStrErr = new char[1024];
 +
  pwcStrErr = new wchar_t[1024];
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF8のBOM無しテキストの読み込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  //※読み込みバッファを1024文字にしているので、1024文字以上の行を一続きにさせたい場合は、工夫が必要。それは後で考えます。
 +
  //※行ごとにバッファの文字数を動的に確保したい場合、
 +
  // 一文字づつスキャンして改行コードが現れるところまでのバイト長を確保するという手法もありそう。
 +
 
 +
  fpos_t* fposPos = new fpos_t;
 +
 
 +
  printf("★UTF8のBOM無しテキストの読み込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathUtf8, L"r,ccs=UTF-8");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\n", *fposPos); //ファイルを開いた時点でのポジションの確認。BOM無しだと0文字目。
 +
 
 +
  //Unicodeサンプル文字 1行目
 +
  printf("文字コードUTF-16->");
 +
  for(int i=0; i < (int)wcslen(pwcStrGohan) + 1; i++){
 +
    printf("%04x:",*(pwcStrGohan + i));
 +
  }
 +
  printf("\n");
 +
 
 +
  printf("utf8N.txtテキストファイルの中身とその他の情報出力\n");
 +
  while(!feof(pfileText)){
 +
 
 +
    pwcStrErr = fgetws(pwcStrStream,1024,pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
                                                    //先頭からUTF-8→UTF16形式で文字列を取得する。
 +
    wprintf(L"%s(%s)\n", pwcStrStream, pwcStrErr);//UTF-16のpwcStrStreamをSJIS(Locale設定)で書き出し。UTF-16のままだと文字化けする。
 +
   
 +
    printf("文字コードUTF-16->");
 +
    for(int i=0 ;i < 20 ;i++){ //Unicodeに変換された文字コードを先頭20文字だけ出力。
 +
      printf("%04x:",*(pwcStrStream + i));
 +
    }
 +
 
 +
    fgetpos(pfileText, fposPos);
 +
    printf("fpos-> %04d\n", *fposPos); 
 +
  }
 +
  printf("[EOF]");
 +
  printf("\n");
 +
 
 +
  nCloseCnt = fclose(pfileText);
 +
  printf("nCloseErr->%d\n", nCloseCnt);
 +
 
 +
  nCloseCnt = _fcloseall();
 +
  printf("nCloseCnt->%d\n", nCloseCnt);
 +
  printf("\n");
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF8のBOM有りテキストの読み込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  printf("★UTF8のBOM有りテキストの読み込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathUtf8Bom, L"r,ccs=UTF-8");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\n", *fposPos); //ファイルを開いた時点でのポジションの確認。BOM無しだと3(0からカウントなので実際は4byte目)。
 +
 
 +
  printf("utf8.txtテキストファイルの中身\n");
 +
  while(!feof(pfileText)){
 +
 
 +
    pwcStrErr = fgetws(pwcStrStream,1024,pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
                                                    //UTF-8(BOMはEF BB BFなので4バイト目)からUTF16形式で文字列を取得する。
 +
                                                    //※FE FFをUTF-8でエンコードするとEF BB BF
 +
                                                    //※FE FF = 1111 1110 1111 1111 を
 +
                                                    //                1111    11  10  11    11  1111 を
 +
                                                    //          1110 (XXXX) 10(XX) (XX)(YY) 10(YY) (YYYY)と割り当て
 +
                                                    //1110 1111 1011 1011 1011 1111 = EF BB BF
 +
 
 +
    if(pwcStrErr != NULL ){                       
 +
      wprintf(L"%s", pwcStrStream);//UTF-16LEのpwcStrStreamをSJIS(Locale設定)で書き出し。UTF-16LEのままだと文字化けする。
 +
    }
 +
  }
 +
  printf("[EOF]");
 +
  printf("\n");
 +
 
 +
  nCloseCnt = fclose(pfileText);
 +
  printf("nCloseErr->%d\n", nCloseCnt);
 +
  printf("\n");
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF16のBOM有りテキストの読み込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  printf("★UTF16LEのBOM有りテキストの読み込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathUtf16LE, L"r,ccs=UTF-16LE");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\n", *fposPos); //ファイルを開いた時点でのポジションの確認。BOM有りで2(0からカウントなので実際は3byte目)。
 +
 
 +
  printf("utf8.txtテキストファイルの中身\n");
 +
  while(!feof(pfileText)){
 +
 
 +
    pwcStrErr = fgetws(pwcStrStream,1024,pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
    if(pwcStrErr != NULL ){                        //UTF-16(BOMはFE FFなので3バイト目)からUTF16形式で文字列を取得する。
 +
      wprintf(L"%s", pwcStrStream);//UTF-16のpwcStrStreamをSJIS(Locale設定)で書き出し。UTF-16のままだと文字化けする。
 +
    }
 +
  }
 +
  printf("[EOF]");
 +
  printf("\n");
 +
 
 +
  nCloseCnt = fclose(pfileText);
 +
  printf("nCloseErr->%d\n", nCloseCnt);
 +
  printf("\n");
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★ShiftJISテキストの読み込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  printf("★ShiftJISテキストの読み込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathShiftJIS, L"r");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\n", *fposPos); //ファイルを開いた時点でのポジションの確認。
 +
 
 +
  printf("test.txtテキストファイルの中身\n");
 +
  while(!feof(pfileText)){
 +
   
 +
    pcStrErr = fgets(pcStrStream, 1024, pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
    if(pcStrErr != NULL ){                     
 +
      printf("%s", pcStrStream);
 +
    }
 +
  }
 +
  printf("[EOF]");
 +
  printf("\n");
 +
 
 +
  nCloseCnt = fclose(pfileText);
 +
  printf("nCloseErr->%d\n", nCloseCnt);
 +
  printf("\n");
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★JISテキストの読み込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  //int型でchar配列のサイズを動的に確保ができるので、int型の範囲のファイルなら
 +
  //一度に格納できるプログラムになっています。intの範囲を超えると動的メモリ確保で
 +
  //失敗します。その先の工夫はまた別途考える必要があります。少し筒変換したり…。
 +
 
 +
  int nSize = 0;
 +
  int nFeedCnt = 0;
 +
 
 +
  char* pcStrFile;
 +
  fpos_t* pfposStartPos = new fpos_t;
 +
  printf("★JISテキストの読み込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathJIS, L"rb");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\n", *fposPos); //ファイルを開いた時点でのポジションの確認。
 +
 
 +
  printf("test_jis.txtテキストファイルの中身\n");
 +
  fgetpos(pfileText, pfposStartPos);
 +
  while(!feof(pfileText)){
 +
    nSize = nSize + nFeedCnt * 1024;
 +
    nFeedCnt++;
 +
    *psizeRuturnValue = fread(pcStrStream, sizeof(char), 1024, pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
      fgetpos(pfileText, fposPos);                 
 +
      for(int i = 0; i < *fposPos; i++){
 +
        printf("%02x:",0x000000FF & *(pcStrStream + i));
 +
      }
 +
  }
 +
  printf("[EOF]");
 +
  printf("\n");
 +
 
 +
  nSize = nSize + (int)*fposPos - ((nFeedCnt - 1) * 1024);
 +
  fsetpos(pfileText, pfposStartPos);
 +
  pcStrFile = new char[nSize + 1];
 +
  while(!feof(pfileText)){
 +
    *psizeRuturnValue = fread(pcStrFile, sizeof(char), nSize + 1, pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
      for(int i = 0; i < nSize; i++){
 +
        printf("%02x:",0x000000FF & *(pcStrFile + i));
 +
      }
 +
  }
 +
 
 +
  printf("[EOF]");
 +
  printf("\n");
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\npReturnValue-> %04d\n", *fposPos, *psizeRuturnValue); //ファイルを開いた時点でのポジションの確認。
 +
 
 +
 
 +
  nCloseCnt = fclose(pfileText);
 +
  printf("nCloseErr->%d\n", nCloseCnt);
 +
  printf("\n");
 +
 
 +
  UConverter* ucnvTest;
 +
  UErrorCode uerrorNum;
 +
  int nStrSize;
 +
  int nStrResultSize;
 +
  nStrSize = nSize;
 +
 
 +
  std::wstring stringCnvResult(nStrSize, L'\0');
 +
 
 +
  ucnvTest = ucnv_open("iso-2022-jp", &uerrorNum);
 +
  nStrResultSize = ucnv_toUChars(
 +
    ucnvTest,
 +
    &stringCnvResult[0], stringCnvResult.size(), // 変換先のポインタとサイズ
 +
    &pcStrFile[0], nStrSize,         // 変換元のポインタとサイズ
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  _tprintf(_T("%s\n"), stringCnvResult.c_str());
 +
  printf("\n");
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
出力結果
 +
<syntaxhighlight2 lang="text">
 +
★UTF8のBOM無しテキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
文字コードUTF-16LE->3054:306f:3093:3092:98df:3079:305f:3088:3002:000d:000a:0000:
 +
utf8N.txtテキストファイルの中身とその他の情報出力
 +
ごはんを食べたよ。
 +
(ごはんを食べたよ。
 +
)
 +
文字コードUTF-16LE->3054:306f:3093:3092:98df:3079:305f:3088:3002:000a:0000:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:fpos-> 0029
 +
 
 +
(
 +
)
 +
文字コードUTF-16LE->000a:0000:3093:3092:98df:3079:305f:3088:3002:000a:0000:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:fpos-> 0031
 +
 
 +
(
 +
)
 +
文字コードUTF-16LE->000a:0000:3093:3092:98df:3079:305f:3088:3002:000a:0000:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:fpos-> 0033
 +
それだけだよ。
 +
(それだけだよ。
 +
)
 +
文字コードUTF-16LE->305d:308c:3060:3051:3060:3088:3002:000a:0000:000a:0000:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:fpos-> 0056
 +
それだけだよ。
 +
((null))
 +
文字コードUTF-16LE->305d:308c:3060:3051:3060:3088:3002:000a:0000:000a:0000:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:cdcd:fpos-> 0056
 +
[EOF]
 +
nCloseErr->0
 +
nCloseCnt->0
 +
 
 +
★UTF8NのBOM有りテキストの読み込み
 +
Error?->0
 +
fpos-> 0003
 +
utf8.txtテキストファイルの中身
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
nCloseErr->0
 +
 
 +
★UTF16LEのBOM有りテキストの読み込み
 +
Error?->0
 +
fpos-> 0002
 +
utf8.txtテキストファイルの中身
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
nCloseErr->0
 +
 
 +
★ShiftJISテキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
test.txtテキストファイルの中身
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
nCloseErr->0
 +
 
 +
★JISテキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
test_jis.txtテキストファイルの中身
 +
1b:24:42:24:34:24:4f:24:73:24:72:3f:29:24:59:24:3f:24:68:21:23:1b:28:4a:0d:0a:0d:0a:0d:0a:1b:24:42:24:3d:24:6c:24:40:24:31:24:40:24:68:21:23
 +
:1b:28:4a:0d:0a:[EOF]
 +
1b:24:42:24:34:24:4f:24:73:24:72:3f:29:24:59:24:3f:24:68:21:23:1b:28:4a:0d:0a:0d:0a:0d:0a:1b:24:42:24:3d:24:6c:24:40:24:31:24:40:24:68:21:23
 +
:1b:28:4a:0d:0a:[EOF]
 +
fpos-> 0052
 +
pReturnValue-> 0000
 +
nCloseErr->0
 +
 
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
 
 +
</syntaxhighlight2>
 +
という感じです。ごはんを食べたよ それだけだよ。というサンプルの文字列に特に深い意味はありませんが、Windowsは改行コードにCR LFを使うのが一般的です。しかしながら、ファイルから取り込んできた文字列にでは\r 0x0dは無くなって\nにあたる0x0aだけが残る仕様になっています。これらの改行復帰コードを厳密に扱う場合には書き込みするときや、文字列操作時に工夫が必要になります。文字コードがどんなふうに扱われているのか、厳密にどうなっているのか調べるためにも、時々は文字コードそのものを出力して確かめるのも大事なのではないかと思います。人間様にわかる文字だけを出力していたのでは、コンピュータを正確にあやつることは難しいです。JISの変換ではファイルオープン時にバイナリで開いています。これをchar型の変数に格納して、ICUのJIS→UNICODE変換を実施しています。
 +
 
 +
 
 +
テキストファイルをバイナリで読み込む場合には区切りが大事です。動的に生成できる文字列配列の大きさはint型の範囲が限界ですので、ひとつだけで扱おうとするのは無理がありますし、int型くらい大きいサイズのメモリ確保は無理があります。もう少し小さい単位で文字列を扱える工夫が必要になります。JISテキストファイルなら改行コードまでの大きさくらいが良いと思います。文字列の中に改行コードが見つかるまで文字数を計算して、それでメモリ確保をし、JIS文字列を変換して、作業用の文字列配列に格納するといった、そういう仕組みにするだけのことです。このプログラムはテキストエディタやファイルローダとしての役割を担うものではないので、そこまでの具体的な拡張には挑戦しませんでした。実際の組み込みでは、プログラムが扱うデータの大きさにちょうどよい区切りを準備することになると思います。
 +
まぁこのままでもかなり大きさまで扱えるので、コンソールで遊ぶ程度ならこれでもいいんではないでしょうか?それよか、メモリ確保がうまくいかない場合の例外処理とか追加しますかね。そのあたりの説明はまた別の項目になるかと思います。
 +
 
 +
 
 +
ファイル読み込み時に文字コードセットが判明しているサンプルプログラムのようなケースはプログラムが簡単でしたが、もともとのファイル形式を自動判別して読み込むプログラムに対応しようとすると、またひとつ大変さが増します。自動判別ができないのはutf-8で書かれた英字だけのファイルを開いた場合で、ShiftJISとするのが最適なのか?UTF-8として開くのが最適なのかは、ユーザにあらかじめ決めてもらった方が良いかもしれません。一度でも日本語が使われていれば、おのずと判定ができるわけですが、すべての文字をチェックして英字以外の範囲の文字コードを見つけて、それが、どの文字コードなのかを判別する仕組みが必要です。
 +
 
 +
 
 +
おもしろそうですが、文字コードに詳しくないので、自分はまだその手法をしりません。また今度、考えてみようと思います。文字化けしてるコードをみて、あーこれはもともとはこのコードだったんだろうなという感覚はあるんですが、それと似たような法則があるんでしょうね。結局、この判定もICUでできちゃうんですけどね。これも時間があればやってみたいと思います。
 +
 
 +
 
 +
次はファイル出力にあたる書き込みですね。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
  //JISからUTF-16LEへの変換処理
 +
 
 +
  UConverter* ucnvTest;
 +
  UErrorCode uerrorNum;
 +
  int nStrSize;
 +
  int nStrResultSize;
 +
  char pcStrUTF16LEBOM[] = "\xFF\xFE";//\xエスケープシーケンスはx以降の16進数とした文字コードを示すもの。1バイトの文字コード指定で利用できます。
 +
  char pcStrUTF8BOM[] = "\xEF\xBB\xBF";
 +
  nStrSize = nSize;
 +
 
 +
  std::wstring stringCnvResult(nStrSize, L'\0');
 +
 
 +
  ucnvTest = ucnv_open("iso-2022-jp", &uerrorNum);
 +
  nStrResultSize = ucnv_toUChars(
 +
    ucnvTest,
 +
    &stringCnvResult[0], stringCnvResult.size(), // 変換先のポインタとサイズ
 +
    &pcStrFile[0], nStrSize,         // 変換元のポインタとサイズ
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  _tprintf(_T("%s\n"), stringCnvResult.c_str());
 +
  printf("\n");
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF16LEのTextモードでの書き込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  //\n 0x0Aが \r\nに変換されるため、Binaryモードで読み込んだ\r\nを保持した文字列から
 +
  //変換した文字列をテキストモードで書き込むと\r\r\nのように2重復帰が書き込まれる。
 +
  //テキストエディタでは\rひとつでも、改行されるため \r と \r\nで2つ改行になる。
 +
 
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathNewTexttoBinary, L"w,ccs=UTF-16LE");
 +
  fputws(stringCnvResult.c_str(), pfileText);
 +
  fclose(pfileText);
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF16LEのBinaryモードテキストの書き込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathNewUTF16LE, L"wb");
 +
  fputs(pcStrUTF16LEBOM,pfileText);
 +
  fputws(stringCnvResult.c_str(), pfileText);
 +
  fclose(pfileText);
 +
 
 +
  //UnicodeUTF-16LEのutf-8への変換処理
 +
  ucnvTest = ucnv_open("UTF-8", &uerrorNum);
 +
 
 +
  nStrSize = stringCnvResult.size();
 +
  std::string stringCnvResult3(ucnv_getMaxCharSize(ucnvTest) * nStrSize , L'\0');
 +
 
 +
 
 +
  nStrResultSize = ucnv_fromUChars(
 +
    ucnvTest,
 +
    &stringCnvResult3[0], stringCnvResult3.size(), // 変換先のポインタとサイズ
 +
    &stringCnvResult[0], nStrSize, // 変換元のポインタとサイズ
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult3.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  printf("%s\n", stringCnvResult3.c_str());
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF8のBOM無しテキストの書き込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathNewUTF8, L"wb");
 +
  //fputs(pcStrUTF8BOM,pfileText);
 +
  fputs(stringCnvResult3.c_str(), pfileText);
 +
  fclose(pfileText);
 +
 
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★UTF8のBOM有りテキストの書き込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePathNewUTF8BOM, L"wb");
 +
  fputs(pcStrUTF8BOM,pfileText);
 +
  fputs(stringCnvResult3.c_str(), pfileText);
 +
  fclose(pfileText);
 +
</syntaxhighlight2>
 +
先述の読み込み処理に続けてのプログラムになります。ファイルオープンモードでwを指定して、fputs関数でchar型の書き込み、fputwsでwchar_t型の書き込みをするような形式です。モードaで追記なのでファイル末尾から追記されます。ファイルの先頭に追加するときはBOMコードの後の所にファイルポジションをfsetpos関数で移動してからfputws/fputsで書き込むと良いでしょう。新規のファイル作成となるモードwのバイナリモードwbでは、BOMコードを付与しなければならないケースも出てきます。fputsでBOMコードを保持した文字列を引数にすると良いです。bを付けないテキストモードでの書き込みでは、ccs=UTF-8やccs=UTF-16LEを指定すると自動でBOMコードを追記してくれますので、そのままUTF-16ならwchar_t型の文字列を書き出せばよいです。但し、バイナリモードで読み込んだ文字列は\r\nがそのまま文字列になっているので、書き出し時に後ろの\nが\r\nに変換され、\r\r\nになってしまうので、バイナリモードで読み込んだ文字をテキストモードで書き出すのはやめた方がいいです。どうしても相互乗り換えするのであれば、改行コードの置換処理が必要です。UTF-8のテキストモード書き込みでもユニコードのUTF-16LE形式で書き込むことでUTF-8に変換されますので、プログラム内部ではUnicodeで文字列を扱った方が効率が良いと思います。テキストモードでサポートしない文字コードのような特殊な形式に変換する場合はバイナリモードで文字列を読み込んで、変換処理を実施し、char型に格納した文字コードをバイナリモードで書き出すと良いでしょう。サンプルプログラムではテキストモードで読み込んだJIS文字をUnicodeに変換しUTF-16テキストモードで書き込んだ失敗例をプログラムにしてあります。ファイルオープンモードをうまく使いこなすことと、Unicode以外の文字列はchar型でバイナリとして扱うところがポイントです。変換処理はICUに任せればかなり柔軟な入出力処理が作れると思います。
 +
 
 +
 
 +
ファイルオープンモードについてですが、r、w、a、rb、wb、ab の他にもr+ のように+記号を付けるパターンがあります。この場合、r+ 既存ファイルに読み込み上書き、w+ 新規ファイルで読み書き、a+ 既存ファイルに読み追記ができます。cをつけるとflush関数による反映ですべての操作が確定しファイルに反映するモードになります。通常はcではないモードのnが規定値になっています。bを指定しない場合も実際はtが規定値として扱われています。他にもディスクにファイルを残さずメモリ上だけでファイルの操作をするためにT(ファイル生成されない)やD(ファイルポインタを閉じると削除されるファイル)といった一時ファイル指定もありますし、シーケンシャルアクセス最適化のSにランダムアクセス最適化のR、子プロセスに継承しないNといった非常に難しいコアなオプションもあります。シーケンシャルやランダムアクセスについては記録するディスクの仕組みにもよりますが、通常はシーケンシャルの方が読み取り効率が良いはずですが、ランダムに配置された方が待ち時間が少なくなるというケースもあります。大容量・大量のファイルを扱う場合によく調べて選択するとよいかもしれません。Nは違うプログラム(子プロセス)からファイルポインタを2重に参照させないというようなオプションかと思います。やってみたことないので、具体的な例はここでは示せません。やはり経験が少ないと細かいところまでは説明できないですね。無念。
 +
 
 +
 
 +
ここの長ったらしい文字列処理の説明の総括的なプログラミングになっているかと思います。全部理解してこそ、やりきれる処理です。文字列処理のプログラムを普段作らない自分でもこの程度なら理解しておきたいものです。ここのサンプルは直線的なプログラムで無駄の多いサンプルです。みなさんはもっともっと効率のいい文字列処理をやって下さい。ここでは関数の引数や、クラスの考え方をあまり知らなくても、文字列処理ができるように、あまり多くの技術を使わないそういう無駄なサンプルになっていますが、上から順番に処理していくだけなので、処理の順番は理解しやすいようになっているのではないかと自負するところです。あとは文字コードの自動判定くらいを触れて、文字列処理に関するこの記事は終了にしたいなぁと思います。誰も読まないかもしれないのに、よくこんなにウダウダと長ったらしい文章を書いたなぁ。恐るべしだ。でも、こういううだうだした説明ともっと若いときに出会っていたら、もっと手早く理解できたのになぁと自分は思います。この長い文書が誰かの役に立っていたなら幸せなことです。
 +
 
 +
 
 +
ICUによる文字コード自動判定のプログラムは以下のとおりです。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string>      //std::string型定義
 +
#include <mbstring.h>  //mbs***関数
 +
#include <iostream>    //cpp cout etc 一般入出力関数
 +
#include <locale>      //Locale関数
 +
#include <tchar.h>    //TCHAR型+_tcs***関数
 +
#include "atlstr.h"    //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h"  //同上
 +
#include "cstringt.h"  //CStringTの定義プリプロセッサ
 +
#include <vector>      //Vector型テンプレートクラス
 +
 
 +
#include <sys/timeb.h> //Timeb型構造体
 +
 
 +
//_bstr_t型を利用するプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include "comutil.h"
 +
 
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t _End
 +
 
 +
//ICU ucnvプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include <unicode/ucnv.h>    //ucnv文字コード変換ライブラリヘッダ
 +
#include <unicode/translit.h> //文字変換ライブラリヘッダ
 +
#include <unicode/regex.h>    //正規表現
 +
#include <unicode/ucsdet.h>  //文字コード判定
 +
 
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")  //ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuuc.lib")  //ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuio.lib")
 +
#endif
 +
//ICU ucnv _End
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
using namespace std;
 +
 
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese")); //ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 
 +
_locale_t localeJpanease;
 +
localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 
 +
  FILE* pfileText;
 +
  fpos_t* fposPos = new fpos_t;
 +
  errno_t errNo;
 +
  size_t* psizeRuturnValue = new size_t;
 +
 
 +
  wchar_t pwcStrFilePath[]            = L"C:\\Users\\Administrator\\Documents\\マイ インフォメーション\\ファイル入出力\\test_utf16LE.txt";
 +
  char* pcStrStream;
 +
  pcStrStream = new char[1024];
 +
  int nCloseResult = 0;
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★テキストの読み込み
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★
 +
 
 +
  //int型でchar配列のサイズを動的に確保ができるので、int型の範囲のファイルなら
 +
  //一度に格納できるプログラムになっています。intの範囲を超えると動的メモリ確保で
 +
  //失敗します。その先の工夫はまた別途考える必要があります。少し筒変換したり…。
 +
 
 +
  int nSize = 0;
 +
  int nFeedCnt = 0;
 +
 
 +
  char* pcStrFile;
 +
  fpos_t* pfposStartPos = new fpos_t;
 +
  printf("★テキストの読み込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePath, L"rb");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\n", *fposPos); //ファイルを開いた時点でのポジションの確認。
 +
 
 +
  printf("test.txtテキストファイルの中身\n");
 +
  fgetpos(pfileText, pfposStartPos);
 +
  while(!feof(pfileText)){
 +
    nSize = nSize + nFeedCnt * 1024;
 +
    nFeedCnt++;
 +
    *psizeRuturnValue = fread(pcStrStream, sizeof(char), 1024, pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
      fgetpos(pfileText, fposPos);                 
 +
      for(int i = 0; i < *fposPos; i++){
 +
        printf("%02x:",0x000000FF & *(pcStrStream + i));
 +
      }
 +
  }
 +
  printf("[EOF]");
 +
  printf("\n");
 +
 
 +
  nSize = nSize + (int)*fposPos - ((nFeedCnt - 1) * 1024);
 +
  fsetpos(pfileText, pfposStartPos);
 +
  pcStrFile = new char[nSize + 1];
 +
  while(!feof(pfileText)){
 +
    *psizeRuturnValue = fread(pcStrFile, sizeof(char), nSize + 1, pfileText);//最終行がEOFのみの場合に失敗して1行前の値が残ることに注意。
 +
      for(int i = 0; i < nSize; i++){
 +
        printf("%02x:",0x000000FF & *(pcStrFile + i));
 +
      }
 +
  }
 +
 
 +
  printf("[EOF]");
 +
  printf("\n");
 +
  fgetpos(pfileText, fposPos);
 +
  printf("fpos-> %04d\npReturnValue-> %04d\n", *fposPos, *psizeRuturnValue); //ファイルを開いた時点でのポジションの確認。
 +
 
 +
 
 +
  nCloseResult = fclose(pfileText);
 +
  printf("nCloseErr->%d\n", nCloseResult);
 +
  printf("\n");
 +
 
 +
  UConverter* ucnvTest;
 +
  UErrorCode uerrorNum = U_ZERO_ERROR;
 +
  int nStrSize;
 +
  int nStrResultSize;
 +
  char pcStrUTF16LEBOM[] = "\xFF\xFE";
 +
  char pcStrUTF8BOM[] = "\xEF\xBB\xBF";
 +
  nStrSize = nSize;
 +
 
 +
  UCharsetDetector* pucsetdetecDetector = ucsdet_open(&uerrorNum);
 +
  ucsdet_setText(pucsetdetecDetector, pcStrFile, nSize, &uerrorNum);
 +
 
 +
  int32_t int32FindCharSetCnt = 0;
 +
  const UCharsetMatch* pucsetmatchStrCode = ucsdet_detect(pucsetdetecDetector, &uerrorNum);
 +
 
 +
  const char* cpcDetectStrCodeName;
 +
  const char* cpcDetectStrCodeLanguage;
 +
  cpcDetectStrCodeName = ucsdet_getName(pucsetmatchStrCode, &uerrorNum);//文字コード名 ICUの文字コードセット名に適した形式。
 +
  cpcDetectStrCodeLanguage = ucsdet_getLanguage(pucsetmatchStrCode, &uerrorNum);
 +
 
 +
  printf("★ICU Code Detectorによるテキストの文字コード自動判定\n");
 +
  printf("CodeName->%s\n",cpcDetectStrCodeName);
 +
  printf("CodeLang->%s\n",cpcDetectStrCodeLanguage);//RFC3066コードを取得できる。
 +
 
 +
  //Shift_JISからUTF-16LEへの変換処理
 +
 
 +
  //先頭がBOMコードなら変換する文字の先頭アドレスをBOMコードの長さを割り出し、nShiftByteに記録。
 +
  int nShiftByte = 0;
 +
  if(strlen(pcStrFile) >= 3){
 +
    if(strncmp(pcStrFile,pcStrUTF8BOM,3) == 0){
 +
      nShiftByte = 3;
 +
    }
 +
  }
 +
  if(strlen(pcStrFile) >= 2){
 +
    if(strncmp(pcStrFile,pcStrUTF16LEBOM,2) == 0){
 +
      nShiftByte = 2;
 +
    }
 +
  }
 +
 
 +
  std::wstring stringCnvResult(nStrSize, L'\0');
 +
 
 +
  ucnvTest = ucnv_open(cpcDetectStrCodeName, &uerrorNum);//変換する文字コードは自動判定で取得した文字コード。
 +
  nStrResultSize = ucnv_toUChars(
 +
    ucnvTest,
 +
    &stringCnvResult[0], stringCnvResult.size(),           // 変換先のポインタとサイズ
 +
    &pcStrFile[0 + nShiftByte], nStrSize - nShiftByte, // 変換元のポインタとサイズ BOMサイズがnShiftByteに格納されている。
 +
    &uerrorNum
 +
  );
 +
  stringCnvResult.resize(nStrResultSize);
 +
  ucnv_close(ucnvTest);
 +
  ucsdet_close(pucsetdetecDetector);
 +
  _tprintf(_T("%s[EOF]"), stringCnvResult.c_str());
 +
  printf("\n");
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
出力結果 utf16LEのテキストを指定した場合。
 +
<syntaxhighlight2 lang="text">
 +
★テキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
test.txtテキストファイルの中身
 +
ff:fe:54:30:6f:30:93:30:92:30:df:98:79:30:5f:30:88:30:02:30:0d:00:0a:00:0d:00:0a:00:0d:00:0a:00:5d:30:8c:30:60:30:51:30:60:30:88:30:02:30:0d:00:0a:00:[EOF]
 +
ff:fe:54:30:6f:30:93:30:92:30:df:98:79:30:5f:30:88:30:02:30:0d:00:0a:00:0d:00:0a:00:0d:00:0a:00:5d:30:8c:30:60:30:51:30:60:30:88:30:02:30:0d:00:0a:00:[EOF]
 +
fpos-> 0050
 +
pReturnValue-> 0000
 +
nCloseErr->0
 +
 
 +
★ICU Code Detectorによるテキストの文字コード自動判定
 +
CodeName->UTF-16LE
 +
CodeLang->
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
</syntaxhighlight2>
 +
出力結果 utf8のテキストを指定した場合。
 +
<syntaxhighlight2 lang="text">
 +
★テキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
test.txtテキストファイルの中身
 +
ef:bb:bf:e3:81:94:e3:81:af:e3:82:93:e3:82:92:e9:a3:9f:e3:81:b9:e3:81:9f:e3:82:88:e3:80:82:0d:0a:0d:0a:0d:0a:e3:81:9d:e3:82:8c:e3:81:a0:e3:81:91:e3:81:a0:e3:82:88:e3:80:82:0d:0a:[EOF]
 +
ef:bb:bf:e3:81:94:e3:81:af:e3:82:93:e3:82:92:e9:a3:9f:e3:81:b9:e3:81:9f:e3:82:88:e3:80:82:0d:0a:0d:0a:0d:0a:e3:81:9d:e3:82:8c:e3:81:a0:e3:81:91:e3:81:a0:e3:82:88:e3:80:82:0d:0a:[EOF]
 +
fpos-> 0059
 +
pReturnValue-> 0000
 +
nCloseErr->0
 +
 
 +
★ICU Code Detectorによるテキストの文字コード自動判定
 +
CodeName->UTF-8
 +
CodeLang->
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
</syntaxhighlight2>
 +
出力結果 JISのテキストを指定した場合。
 +
<syntaxhighlight2 lang="text">
 +
★テキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
test.txtテキストファイルの中身
 +
1b:24:42:24:34:24:4f:24:73:24:72:3f:29:24:59:24:3f:24:68:21:23:1b:28:4a:0d:0a:0d:0a:0d:0a:1b:24:42:24:3d:24:6c:24:40:24:31:24:40:24:68:21:23:1b:28:4a:0d:0a:[EOF]
 +
1b:24:42:24:34:24:4f:24:73:24:72:3f:29:24:59:24:3f:24:68:21:23:1b:28:4a:0d:0a:0d:0a:0d:0a:1b:24:42:24:3d:24:6c:24:40:24:31:24:40:24:68:21:23:1b:28:4a:0d:0a:[EOF]
 +
fpos-> 0052
 +
pReturnValue-> 0000
 +
nCloseErr->0
 +
 
 +
★ICU Code Detectorによるテキストの文字コード自動判定
 +
CodeName->ISO-2022-JP
 +
CodeLang->
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
</syntaxhighlight2>
 +
出力結果 ShiftJISのテキストを指定した場合。
 +
<syntaxhighlight2 lang="text">
 +
★テキストの読み込み
 +
Error?->0
 +
fpos-> 0000
 +
test.txtテキストファイルの中身
 +
82:b2:82:cd:82:f1:82:f0:90:48:82:d7:82:bd:82:e6:81:42:0d:0a:0d:0a:0d:0a:82:bb:82:ea:82:be:82:af:82:be:82:e6:81:42:0d:0a:[EOF]
 +
82:b2:82:cd:82:f1:82:f0:90:48:82:d7:82:bd:82:e6:81:42:0d:0a:0d:0a:0d:0a:82:bb:82:ea:82:be:82:af:82:be:82:e6:81:42:0d:0a:[EOF]
 +
fpos-> 0040
 +
pReturnValue-> 0000
 +
nCloseErr->0
 +
 
 +
★ICU Code Detectorによるテキストの文字コード自動判定
 +
CodeName->Shift_JIS
 +
CodeLang->ja
 +
ごはんを食べたよ。
 +
 
 +
 
 +
それだけだよ。
 +
[EOF]
 +
</syntaxhighlight2>
 +
とこのような感じになります。書き出すときには文字コード別にBOMを付与する処理が必要になりますが、自動判別によって、かなりたくさんの文字コードのテキストファイルを自動で読み込むことができるようになります。やや便利なコンソールアプリになったのかもしれません。そんな得体の知れないテキストファイルが転がっているかどうかは知りませんが…。BOMコードの種類にはUTF-16BEもあるので、このあたりにも対応したプログラムにするともっといいかもしれませんね。
 +
今回のサンプルでは完璧な変換をしてくれましたが、ややこしい文字構成ばかりのテキストファイルになってくると間違えることもあります。そのためICUでは文字コード一致率みたいなランキングを作ってくれる関数もありまして、ucsdet_detect関数の代わりにucsdet_detectAllという関数で UCharsetMatch**型を戻り値にするものがあります。ポインタのポインタってことは、配列ってことになります。ucsdete_getName関数で、引数のその配列の要素を渡せば、それぞれの文字コード名が一覧されます。具体的には以下のような要領になります。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
  int32_t int32FindCharSetCnt = 0;
 +
  int32_t int32Confidence = 0;
 +
  const UCharsetMatch* pucsetmatchStrCode = ucsdet_detect(pucsetdetecDetector, &uerrorNum);
 +
  const UCharsetMatch** ppucsetmatchStrCode = ucsdet_detectAll(pucsetdetecDetector, &int32FindCharSetCnt, &uerrorNum);
 +
 
 +
  const char* cpcDetectStrCodeName;
 +
  const char* cpcDetectStrCodeLanguage;
 +
 
 +
  for(int i = 0; i < int32FindCharSetCnt; i++){
 +
    int32Confidence = ucsdet_getConfidence(ppucsetmatchStrCode[i], &uerrorNum);0~100で表される信頼値
 +
    cpcDetectStrCodeName = ucsdet_getName(ppucsetmatchStrCode[i], &uerrorNum);//文字コード名 ICUの文字コードセット名に適した形式。
 +
    cpcDetectStrCodeLanguage = ucsdet_getLanguage(ppucsetmatchStrCode[i], &uerrorNum);   
 +
    printf("CodeConf->%d\n",int32Confidence);
 +
    printf("CodeName->%s\n",cpcDetectStrCodeName);
 +
    printf("CodeLang->%s\n",cpcDetectStrCodeLanguage);//RFC3066コードを取得できる。
 +
  }
 +
</syntaxhighlight2>
 +
のようにするとConfidenceの値が大きいほど一致率が高いものとして確認ができます。全部を一覧するにはfor文で0~int32FindCharSetCnt -1までの要素を確認するとよいです。
 +
出力結果 UTF-16LEのファイル。
 +
<syntaxhighlight2 lang="text">
 +
CodeConf->100
 +
CodeName->UTF-16LE
 +
CodeLang->
 +
CodeConf->23
 +
CodeName->windows-1252
 +
CodeLang->es
 +
CodeConf->23
 +
CodeName->windows-1250
 +
CodeLang->cs
 +
CodeConf->10
 +
CodeName->UTF-16BE
 +
CodeLang->
 +
</syntaxhighlight2>
 +
となります。
 +
 
 +
=='''文字列と数値の変換'''==
 +
実際のアプリケーションでは、数値の入力を行う部分でも、文字コードとして入力がなされ、各種のエディタや、エディットコントロール、入力画面からは文字としてテキストから渡されます。このように取り扱われる文字列としての数値を、プログラミング言語の数を扱う型に格納する技術が必要になります。
 +
 
 +
atoi、atol、atofのような標準関数で簡単に文字列を数値に変換することができます。逆に数値を文字列に変換する関数もitoaやltoa、ftoaのように準備されていますが非標準関数となっています。ほぼ標準で準備されています。同じことがprintf関数のような関数でva_listという可変長引数の型を引数とするvsprintf(vscprintf:文字数カウント用)関数あるい通常のsprintf(scprintf:文字数カウント)関数を使って実現できます。ここでは、使い方のややこしいvsprintfを使ってみました。数値の文字列化に関してはitoaなどの関数よりも書式設定ができる分、応用が利くので、自分ならこういうものを活用します。atoiのような関数はC++ではstd::atoiのような名前空間の中に定義されています。使い方は同じです。
 +
 
 +
では、以下がサンプルになります。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 
 +
 
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
 
 +
using namespace std;
 +
int getvscprintflen(char* format, ...){
 +
    va_list args;
 +
    int    len;
 +
 
 +
//可変長引数をargsに格納。引数formatの次から全てをva_list型のargsへ設定
 +
//引数文字列ポインタをformatの次に合わせる関数。
 +
    va_start( args, format );
 +
    len = _vscprintf( format, args );
 +
    return len;
 +
}
 +
 
 +
void getvsprintf(char* str, char* format, ...){
 +
    va_list args;
 +
    int    len;
 +
 
 +
    va_start( args, format );
 +
    len = _vscprintf( format, args );
 +
    vsprintf_s( str, len + 1, format, args );
 +
}
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
char pcStrInt[]="-8192";
 +
const char pcStrFloat[]="-3.14";
 +
int nInteger;
 +
long lLong;
 +
double dDouble;
 +
char* pcStrNumeric;
 +
 +
int nLen;
 +
nInteger = atoi(pcStrFloat);
 +
lLong    = atol(pcStrFloat);
 +
dDouble  = atof(pcStrInt);
 +
 
 +
printf("★文字列の数値化 型違いの場合\n");
 +
printf("nInteger->%d\n",nInteger);
 +
printf("lLong  ->%d\n",lLong);
 +
printf("dDouble ->%f\n",dDouble);
 +
printf("\n");
 +
 
 +
nInteger = atoi(pcStrInt);
 +
lLong    = atol(pcStrInt);
 +
dDouble  = atof(pcStrFloat);
 +
 
 +
printf("★文字列の数値化 型一致の場合\n");
 +
printf("nInteger->%d\n",nInteger);
 +
printf("lLong  ->%d\n",lLong);
 +
printf("dDouble ->%f\n",dDouble);
 +
printf("\n");
 +
 
 +
 
 +
//文字列長を取得する
 +
nLen = getvscprintflen("%3.2f", dDouble );
 +
 
 +
pcStrNumeric = new char[nLen + 1];
 +
 
 +
//文字列を出力※同じ引数を2回与えているのは冗長なので
 +
//pcStrNumericをメンバ関数にしたクラスを作ると一度にまとめれる。
 +
getvsprintf( pcStrNumeric, "%3.2f", dDouble );
 +
 
 +
printf("★数値を文字列 vsprintf関数を利用する場合\n");
 +
printf( "%s\n", pcStrNumeric);
 +
 +
delete[] pcStrNumeric;
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
出力結果
 +
<syntaxhighlight2 lang="text">
 +
★文字列の数値化 型違いの場合
 +
nInteger->-3
 +
lLong  ->-3
 +
dDouble ->-8192.000000
 +
 
 +
★文字列の数値化 型一致の場合
 +
nInteger->-8192
 +
lLong  ->-8192
 +
dDouble ->-3.140000
 +
 
 +
★数値を文字列 vsprintf関数を利用する場合
 +
-3.14
 +
</syntaxhighlight2>
 +
 
 +
=='''文字列と日付・日時・時間の変換'''==
 +
先述の数値の問題と同様、日付・日時・時間も文字列として与えられる場合があり、時制を扱う型との相互変換を行う技術も必要になります。
 +
 
 +
 
 +
時間処理については、また別の場所で考えたいと思いますが、自分が思うところによると、時間処理には、カレンダー日付を伴う日時の概念と、カレンダー日付を考慮しない、時間の概念の2つがあると思います。時間だけの概念ならば24時間を超えて、1週間=168時間、そして1年=8760時間(うるう年の1年は8784時間ですが…)という具合に表現できると思います。この時間の概念に24時間ごとに1日と数える方式として、1.5日(一日半)にあたる36時間だと「1日と12時間」という表現です。日にちを小数点で表すのは、あまり便利ではありませんが、概念としては存在していて、日付単位にすることもありますし、会話の中では具体的な時間を0.5日割り算として、余りを切り捨てる方式が使われると思います。さらには7日毎(168時間)に1週間として表し、「1週間と1日と12時間」の表現や時間を切り捨てる方式や、日付部分を1.5日と表現する方法。そして、ここから先はうるう年や月あたりに日数の関係であいまいな表現になりますが31日or30日で1カ月と表現する方式として「(およそ)1か月と23日」のような表現に365日毎に1年とした「(およそ)1年と(およそ)3カ月と1週間と2日と10時間」のような表現。大きな単位だけを採用して、小さいものを切り捨てるという概念。ここまでは時間についてでしたが更に細かいところでは時間と分と秒でも表現できて、1時間は60分ですが1時間以上の領域も分で表現し続ける方式として、2時間を120分、24時間を1440分と表すこともあります。1週間を超えるところまで分で表すと10080分でこの先も分で表すケースは人間の感覚による理解を超える表現になってくると思います。同じことを秒でも実施して、1分は60秒の領域を超えて1時間を3600秒そして1日は86400秒。秒の場合は1時間から2時間を超えたあたりで、秒での表現の感覚理解の限界を感じます。ここまでに述べた大きな単位と組み合わせて使う場合には分や秒は59分や59秒といった範囲以内で利用されます。長くなりましたが、こういったものがカレンダー日付を考慮しない時間という概念になると思います。1年や1カ月がどこの1か月か特定されないのが日常の1年や1カ月という表現になりますので、このあたりの表現は人間にわかりやすく説明するあいまいな表現としてだけ存在すると考えていいと思います。
 +
 
 +
 
 +
上記のカレンダー日付を考慮しない時間に加えて、カレンダー日付を考慮した時間の概念が存在し、これらを短い言葉で表現するなら非暦時間、暦時間と表したいと思います。暦時間の差分を考えることで非暦時間がうまれ、暦時間と非暦時間を結合させる場合には、かならず加減算して、暦時間に変化するということになります。計算機の暦時間の概念は、定義された基準時間を起点に秒単位で管理されていること、その起点が1970年1月1日00時00分00秒となっていて、世界協定時刻UTCとよばれる表現で表されていると理解しておくと良いです。そして、時刻をカウントする変数のbit数が32bitなら2038年までカウントできて、64bitなら3000億年までカウントできる仕組みです。これは個人的な希望になりますが、これからプログラムをする人は64bitの時間変数を扱って欲しいです。作成するプログラムが経済活動や、生活の基盤、生命活動を支えるものであれば尚更です。2038年は、執筆時点からあと24年でやってくるのです。経済的な損失、人的被害、労力を生まないために。各種コンパイラ提供元はそろそろ32bit時間変数のコンパイルをワーニングや使用宣言未定義エラーとかにする工夫を実施しても良いと思うのです。
 +
 
 +
 
 +
これが時間処理の全般になると思います。この暦時間と非暦時間の特殊ケースとして1秒よりも小さい時間であるミリ秒の存在があるといったところでしょうか?そして、文字列として時間を表現する場合には国際社会を含めたルールに基づいて出力します。まずは標準時間からの差が最も重要な概念になります。日本なら+9時間です。あまり日本では関係の無い概念ですがサマータイムという表現もあります。グローバルな展開をするプログラムなら重要な概念かもしれません。相手の時間を思いやる必要のある双方向通信アプリとかなら、なおさら重要です。そして、曜日、午前、午後、24時間表現、表現習慣も国、地域、組織、個人によって異なります。ここでは、日付処理は別の場で考えるとして、システム時間から得られた時刻を文字列にする方法、網羅はできないですが、時刻文字列をシステム時間変数に設定し、歴時間変数として扱う方法について確認したいと思います。この日付の表現に関しても、文字コード変換でお世話になったICUはかなり手広くサポートしています。国際的な文字の変換処理に関する部分の処理系を強くしていっている印象です。たしかに個人では抱えきれないほど国際的な表現は複雑ですので、特化した組織があるというのは、ありがたいことです。
 +
 
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 
 +
 
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
 
 +
using namespace std;
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
    //_tsetlocale(LC_ALL, _T("Japanese")); ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 
 +
_locale_t localeJpanease;
 +
localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 
 +
//日付や時刻を取り込む文字列の長さは大きくないため、一時的な文字列確保はこのような固定長の配列で問題はないと思います。
 +
//それでも動的に文字列長を決定してメモリを確保したいというプログラムの効率を無視する場合には、自作しなければいけない関数が増えるのかと思います。
 +
char tmpbuf[128], timebuf[26], ampm[] = "AM";
 +
    time_t ltime;
 +
    struct _timeb structtimebTime;
 +
    struct tm today, gmt, xmas = { 0, 0, 12, 25, 11, 93 };//秒, 分, 時間, 日, 月(0~11), 年(1900年基準)
 +
    errno_t err;
 +
 
 +
 +
//__timeb64型構造体変数のアドレスを引数とする_ftime64_s関数でtstructに現在時刻を設定。
 +
_ftime_s( &structtimebTime ); // _ftimeはC4996
 +
    //
 +
 
 +
//環境変数TZに設定されたタイムゾーンにしたがってグローバル変数_daylight(夏時間設定)、
 +
//_timezone(秒時差)、_tzname配列(要素1->タイムゾーン名 要素2->夏時間タイムゾーン名)を設定。
 +
    _tzset();
 +
 
 +
 
 +
    //strtimeは10文字で現在時刻を引数の文字列変数に格納する関数。
 +
    _strtime_s( tmpbuf, 128 );
 +
    printf( "OS 時間:\t\t\t\t%s\n", tmpbuf );
 +
    //strdateは9文字で現在日付を引数の文字列変数に格納する関数。
 +
    _strdate_s( tmpbuf, 128 );
 +
    printf( "OS 日付:\t\t\t\t%s\n", tmpbuf );
 +
 
 +
    // Get UNIX-style time and display as number and string.
 +
    //time_t型変数のアドレスを引数とするtime関数でltimeに現在日時秒数を協定世界時UTCで設定。
 +
time( &ltime );
 +
    printf( "秒数による日時情報 1970年1月1日基準:\t%ld\n", ltime );
 +
   
 +
//ctime_sは第三引数のtime_t型UTC秒数情報から第一引数の文字列ポインタへ現在のシステムのタイムゾーン時刻生成する関数。
 +
err = ctime_s(timebuf, 26, &ltime);
 +
    if (err)
 +
    {
 +
      printf("ctime_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
    printf( "現在日時情報 曜日月(英語):\t\t%s", timebuf );
 +
 
 +
 
 +
    //_gmtime64_s関数は第一引数のtm型構造体に第二引数で取得したUTC秒数情報からグリニッジ平均時Greenwich Mean Timeすなわち協定世界時を生成する関数。
 +
//※GMTが天体観測によって管理される時間で1秒の長さが微変動するもの、UTCは原子時計でGMTの情報をもとにうるう秒を入れたりして調整が入る。
 +
    err = _gmtime64_s( &gmt, &ltime );
 +
    if (err)
 +
    {
 +
      printf("_gmtime64_s failed due to an invalid argument.");
 +
    }
 +
//asctime_sは第三引数のtm型構造体に格納された情報から第一引数の文字列ポインタへ生成する関数。
 +
    err = asctime_s(timebuf, 26, &gmt);
 +
    if (err)
 +
    {
 +
      printf("asctime_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
    printf( "協定世界時 UTC:\t\t\t\t%s", timebuf );
 +
 
 +
    //_localtime64_sはtime_t型UTC秒数情報から第一引数のtm型構造体に現在のタイムゾーンの時刻を設定する関数。
 +
    err = _localtime64_s( &today, &ltime );
 +
    if (err)
 +
    {
 +
      printf("_localtime64_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
//tm構造体のtoday変数の24時間形式を格納するメンバ変数tm_hourの値が12以上なら午後なので、午前午後情報格納文字列の内容をPMに。
 +
    if( today.tm_hour >= 12 )
 +
    {
 +
        strcpy_s( ampm, sizeof(ampm), "PM" );
 +
        today.tm_hour -= 12;//午後で表現するので、12を引いた。但し、この後tm構造体変数として違う関数への引数とかにすると時間が12時間前になるので用途に注意。
 +
    }
 +
 
 +
    err = asctime_s(timebuf, 26, &today);
 +
    if (err)
 +
    {
 +
      printf("asctime_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
 
 +
//timebufの12文字目から8文字が時間なので、その部分だけを出力し、ampmの情報を付加する。
 +
    printf( "12時間表記 時間:\t\t\t%.8s %s\n", timebuf + 11, ampm);
 +
 
 +
 
 +
    //_timeb64構造体に取得したタイムゾーン現在時刻のメンバ変数出力
 +
    printf( "現在時刻のミリ秒:\t\t\t%03u[ミリ秒]\n", structtimebTime.millitm );
 +
    printf( "協定世界時とタイムゾーン時刻の差:\t%d\n", structtimebTime.timezone / 60 );
 +
 
 +
size_t* pReturnValue = new size_t;
 +
int index = structtimebTime.dstflag;
 +
 
 +
//タイムゾーン名の文字列長をpReturnValueに取得
 +
_get_tzname(pReturnValue, NULL, 0, index);
 +
 
 +
char* timeZoneName = new char[*pReturnValue + 1];
 +
size_t sizeInBytes = *pReturnValue + 1;
 +
 
 +
//タイムゾーン名の取得
 +
_get_tzname(pReturnValue, timeZoneName, sizeInBytes, index);
 +
 
 +
printf( "タイムゾーン名:\t\t\t\t%s\n", timeZoneName );
 +
    printf( "タイムゾーン名文字数:\t\t\t%d[byte]\n", *pReturnValue );
 +
    printf( "夏時間適用フラグ:\t\t\t%s\n", structtimebTime.dstflag ? "夏時間" : "夏時間非適用" );
 +
 
 +
    //mktime関数は初期値が与えられているtm型構造体の情報から日時情報を生成し、他のメンバ変数の設定を行う関数
 +
    if(mktime(&xmas) != (time_t)-1)
 +
    {
 +
      err = asctime_s(timebuf, 26, &xmas);
 +
      if (err)
 +
      {
 +
          printf("asctime_s failed due to an invalid argument.");
 +
          exit(1);
 +
      }
 +
      printf( "指定日付\t\t\t\t%s\n", timebuf );
 +
    }
 +
 
 +
    err = _localtime64_s( &today, &ltime );
 +
    if (err)
 +
    {
 +
        printf(" _localtime64_s failed due to invalid arguments.");
 +
        exit(1);
 +
    }
 +
 
 +
    //★時間変数を文字列に変換する関数 strftime 
 +
    *pReturnValue = strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", &today );
 +
printf("%d[byte]\n",* pReturnValue);
 +
//英語表記の曜日、月名が取得できる。
 +
strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", &today );
 +
    printf( tmpbuf );
 +
 
 +
*pReturnValue = _strftime_l(tmpbuf, 128, "今日は(%y年)%Y年%B(%b月)%d日(%A:%a;%w番目の曜日 %W回目の%A) %U週目 %j日目 現在時刻は(%p %I)%H:%M:%S\n", &today, localeJpanease );
 +
printf("%d[byte]\n",* pReturnValue);
 +
//ロケール設定により日本語表記の曜日、月名が取得できる。
 +
_strftime_l(tmpbuf, 128, "今日は(%y年)%Y年%B(%b月)%d日(%A:%a;%w番目の曜日 %W回目の%A) %U週目 %j日目 現在時刻は(%p %I)%H:%M:%S\n", &today, localeJpanease );
 +
    printf( tmpbuf );
 +
 
 +
*pReturnValue = _strftime_l(tmpbuf, 128, "%#c,%#x,%%,%#S,%#a,%#%,%z,%Z\n", &today, localeJpanease );
 +
printf("%d[byte]\n",* pReturnValue);
 +
//ロケール設定により日本語表記の曜日、月名が取得できる。
 +
_strftime_l(tmpbuf, 128, "%#c,%#x,%%,%#S,%#a,%#%,%z,%Z\n", &today, localeJpanease );
 +
    printf( tmpbuf );
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
 
 +
 
 +
出力結果
 +
OS 時間:                                20:18:03
 +
OS 日付:                                10/13/14
 +
秒数による日時情報 1970年1月1日基準:    1413199083
 +
現在日時情報 曜日月(英語):              Mon Oct 13 20:18:03 2014
 +
協定世界時 UTC:                        Mon Oct 13 11:18:03 2014
 +
12時間表記 時間:                        08:18:03 PM
 +
現在時刻のミリ秒:                      006[ミリ秒]
 +
協定世界時とタイムゾーン時刻の差:      -9
 +
タイムゾーン名:                        東京 (標準時)
 +
タイムゾーン名文字数:                  14[byte]
 +
夏時間適用フラグ:                      夏時間非適用
 +
指定日付                                Sat Dec 25 12:00:00 1993
 +
 +
53[byte]
 +
Today is Monday, day 13 of October in the year 2014.
 +
80[byte]
 +
今日は(14年)2014年10月(10月)13日(月曜日:月;1番目の曜日 41回目の月曜日) 41週目 286日目 現在時刻は(午後 08)20:18:03
 +
59[byte]
 +
2014年10月13日 20:18:03,2014年10月13日,,3,月,,東京 (標準時),東京 (標準時)
 +
 
 +
と上記のように時間の表記を文字列に変換できます。ICUによる変換は時間があれば、サンプルを作成したいと思います。
 +
 
 +
 
 +
それでICUによる時間の文字列化ですが、
 +
サンプルは以下にしめすような感じです。UCalendarというクラスとCalendar+SimpleFormatクラスの2通りがありまして、UCalendarの方はちょっと使いにくそうでした。あとは、タイムゾーンの対応がものすごくて、びっくりします。言語別にUnicodeで表記が出来ます。でも言語別を指定するためのキーワードを知るのが大変で、カレンダーのロケールについては、詳細な一覧方法は提供されていないようにも思います。オーソドックスなロケールは一覧できますが、これでは不十分でして、一番詳しいのは、英語のページになりますが、http://www.unicode.org/reports/tr35/ のサイトになります。長すぎる。日本語のロケールについては、"ja","ja-JP"の基本的な二つに加えてカレンダー用のロケールとして"ja_JP_TRADITIONAL","ja_JP@calendar=japanese"があり、こちらのロケールを使うと公年号(645年の大化から始まって明治 大正 昭和 平成)を使った表現に対応できます。他にも"ja"と同じですが、"japanese"や"jpn"でも良さそうでした。jpnはISO3表記ってことになるのでしょうか?難しいです。これが世界684の地域と620のタイムゾーンにわたって定義されているのでしょうから、なんつうか、やっぱ戦争でもして世界征服して一つの国になったほうがよかったんじゃないのかって思うくらい言語は分かれています。いや冗談冗談。戦争は駄目ですよ。不謹慎な冗談はやめた方がいいか…何の得にもならんしね。こうやって、全く面白くもないのに、おもしろいとおもって書いたことをつつかれて、社会的に抹殺されていくんだろうなぁ。有名人は大変だねぇ。あり得ない発言はだめなんですもんね。わけわからんことを言うと影響力ありますからね。そりゃ世間から指摘されますよね。全く思ってもないようなことを言うのだめだわな。
 +
 
 +
 
 +
まずは、UCalendarを使ったサンプル。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string>      //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream>    //cpp cout etc 一般入出力関数
 +
#include <locale>      //Locale関数
 +
#include <tchar.h>    //TCHAR型+_tcs***関数
 +
#include "atlstr.h"    //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h"  //同上
 +
#include "cstringt.h"  //CStringTの定義プリプロセッサ
 +
#include <vector>      //Vector型テンプレートクラス
 +
 
 +
#include <sys/timeb.h> //Timeb型構造体
 +
 
 +
//_bstr_t型を利用するプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include "comutil.h"
 +
 
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t _End
 +
 
 +
//ICU ucnvプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include <unicode/ucnv.h>    //ucnv文字コード変換ライブラリヘッダ
 +
#include <unicode/translit.h> //文字変換ライブラリヘッダ
 +
#include <unicode/regex.h>    //正規表現
 +
#include <unicode/ucsdet.h>  //文字コード判定
 +
#include <unicode/ucal.h>  //文字コード判定
 +
#include <unicode/uclean.h> //u_cleanup関数
 +
/* for uloc_getDefault() */
 +
#include <unicode/uloc.h>
 +
#include <unicode/calendar.h>
 +
#include <unicode/smpdtfmt.h>
 +
 
 +
//#include "unicode/utypes.h"
 +
//#include "unicode/locid.h"
 +
//#include "unicode/unistr.h"
 +
//#include "unicode/tzfmt.h"
 +
//#include "unicode/tznames.h"
 +
 
 +
 
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuucd.lib")  //ICU ucnvを使うために必要なライブラリ
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "iculed.lib")
 +
#pragma comment(lib, "iculxd.lib") 
 +
#pragma comment(lib, "icuiod.lib") 
 +
#pragma comment(lib, "icutud.lib") 
 +
 
 +
#else
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuuc.lib")  //ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuio.lib")
 +
#endif
 +
//Data  Library                    icudtXX(d).dll icudt(d).lib
 +
//Common Library                    icuucXX(d).dll icuuc(d).lib
 +
//Internationalization(i18n) Library icuinXX(d).dll icuin(d).lib
 +
//Layout Engine                      iculeXX(d).dll icule(d).lib
 +
//Layout Extention Engine            iculxXX(d).dll iculx(d).lib
 +
//ICU I/O(Unicode stdio) Library    icuioXX(d).dll icuio(d).lib
 +
//Tool Utility Library              icutuXX(d).dll icutu(d).lib
 +
 
 +
//ICU ucnv _End
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
using namespace std;
 +
 
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese")); //ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 
 +
  _locale_t localeJpanease;
 +
  localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 
 +
  int32_t int32TimeZoneID;
 +
  UChar* pucharResult = new UChar[1024];
 +
 
 +
  UErrorCode err = U_ZERO_ERROR;
 +
  printf("%s\n",uloc_getDefault());
 +
  UCalendar* cal = ucal_open(
 +
          L"Asia/Tokyo", 10, //TimezoneID と文字数
 +
          uloc_getDefault(), //Locale名 "ja_JP"
 +
          UCAL_TRADITIONAL,  //カレンダータイプ
 +
          &err);
 +
  printf("errorNum?->%d\n",err);
 +
  if (!cal)
 +
  {
 +
    err = U_ZERO_ERROR;
 +
    fprintf(stderr, "ICU error: %s\n", u_errorName(err));
 +
    u_cleanup();
 +
    return ;
 +
  }
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
  //★ここからしばらくは日付表示とは関係の無い、余計なプログラム
 +
 
 +
  //属性値取得関数 最初の曜日の番号は1
 +
  printf("★現在のオープンしているZoneIDの各種属性値を取得する関数。\n");
 +
  printf("Attrbute->%d\n", ucal_getAttribute(cal, UCAL_FIRST_DAY_OF_WEEK));
 +
  printf("\n");
 +
 
 +
 
 +
  //ゾーンIDを取得する関数。もちろんAsia/Tokyo。
 +
  printf("★現在のオープンしているZoneIDのTimeZoneIDをUchar型変数に取得し、その文字数を返す関数\n");
 +
  err = U_ZERO_ERROR;
 +
  int32TimeZoneID = ucal_getTimeZoneID(cal, pucharResult, 1024, &err);
 +
  wprintf(L"TimezoneID->%d[Byte]:%s\n",int32TimeZoneID,pucharResult);//10:Asia/Tokyo
 +
  printf("\n");
 +
 
 +
 
 +
  //タイプによるロケール名を取得。
 +
  //ULOC_ACTUAL_LOCALE->ja
 +
  //ULOC_VALID_LOCALE->ja_JP
 +
  //ULOC_REQUESTED_LOCALE->NULL
 +
  printf("★現在のオープンしているZoneIDのULocDataLocaleTypeによる名前を取得。\n");
 +
  err = U_ZERO_ERROR;
 +
  printf("TypeLocale->%s\n", ucal_getLocaleByType(cal, ULOC_VALID_LOCALE, &err));
 +
  printf("\n");
 +
 
 +
  //★ここまでが、かなり余計なプログラムでした。
 +
  //★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
 +
 +
  //日付をセットする。
 +
  err = U_ZERO_ERROR;
 +
  ucal_setDateTime(cal, 2014, UCAL_OCTOBER, 17, 22, 45, 00, &err);//直接指定。
 +
  ucal_setMillis(cal, ucal_getNow(), &err);//現在日時での指定で上書き。ミリ秒単位で表現されるダブル型の数値。
 +
  //関数名がミリ秒だけを扱うみたいに見えるけど、これで日付時刻ミリ秒まで全部セットされる。
 +
 
 +
 
 +
 
 +
  //特定のフィールドの制限値取得 月の最大。11でした。年の最大は144683です。14万年…
 +
  printf("★現在のオープンしているZoneIDの各種フィールド制限値の取得関数\n");
 +
  int32_t int32TempLimitValue;
 +
  err = U_ZERO_ERROR;
 +
  int32TempLimitValue = ucal_getLimit(cal,UCAL_MILLISECOND,UCAL_MINIMUM, &err);
 +
  printf("Limit->%d\n",int32TempLimitValue);
 +
  printf("\n");
 +
 
 +
  //特定のフィールドのロール 時間を追加したりできる。3週間追加する例。コメント化してますけど。
 +
  printf("★現在のオープンしているZoneIDの各種フィールドロール関数\n");
 +
  int32_t int32Amount = 3;
 +
  err = U_ZERO_ERROR;
 +
  //ucal_roll(cal, UCAL_WEEK_OF_YEAR, int32Amount,&err);
 +
  printf("Limit->%d\n",int32Amount);
 +
  printf("\n");
 +
 
 +
  err = U_ZERO_ERROR;
 +
  UDate udateGetMillis;
 +
  err = U_ZERO_ERROR;
 +
  udateGetMillis = ucal_getMillis(cal, &err);
 +
  printf("★現在のオープンしているZoneIDのミリ秒を取得。\n");
 +
  err = U_ZERO_ERROR;
 +
  printf("GetMilli->%f %f %f\n", udateGetMillis , ucal_getNow(), ucal_getGregorianChange(cal, &err));
 +
  printf("\n");
 +
 
 +
  //日時の出力
 +
  printf("Date->%d/%d/%d\n",
 +
          ucal_get(cal, UCAL_YEAR, &err),
 +
          ucal_get(cal, UCAL_MONTH, &err) + 1,
 +
          ucal_get(cal, UCAL_DATE, &err));
 +
 +
  printf("Time->%d:%d:%d:%d\n",
 +
          ucal_get(cal, UCAL_HOUR_OF_DAY, &err),
 +
          ucal_get(cal, UCAL_MINUTE, &err) + 1,
 +
          ucal_get(cal, UCAL_SECOND, &err),
 +
          ucal_get(cal, UCAL_MILLISECOND, &err));
 +
 +
  printf("Othr->%d:%d:%d:%d\n",
 +
          ucal_get(cal, UCAL_DAY_OF_WEEK, &err),
 +
          ucal_get(cal, UCAL_AM_PM, &err) ,
 +
          ucal_get(cal, UCAL_ZONE_OFFSET, &err),
 +
          ucal_get(cal, UCAL_DST_OFFSET, &err));
 +
 
 +
  ucal_close(cal);
 +
  u_cleanup();
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
出力 大体こんな感じ
 +
<syntaxhighlight2 lang="text">
 +
★現在のオープンしているZoneIDの各種属性値を取得する関数。
 +
Attrbute->1
 +
 
 +
★現在のオープンしているZoneIDのTimeZoneIDをUchar型変数に取得し、その文字数を返す関数
 +
TimezoneID->10[Byte]:Asia/Tokyo
 +
 
 +
★現在のオープンしているZoneIDのULocDataLocaleTypeによる名前を取得。
 +
TypeLocale->ja_JP
 +
 
 +
★現在のオープンしているZoneIDの各種フィールド制限値の取得関数
 +
Limit->0
 +
 
 +
★現在のオープンしているZoneIDの各種フィールドロール関数
 +
Limit->3
 +
 
 +
★現在のオープンしているZoneIDのミリ秒を取得。
 +
GetMilli->1413654266519.000000 1413654266529.000000 -12219292800000.000000
 +
 
 +
Date->2014/10/19
 +
Time->2:45:26:519
 +
Othr->1:0:32400000:0
 +
</syntaxhighlight2>
 +
そして、Calendar+SimpleFormatクラスを使うサンプルは以下のような感じ。上記のプログラムの続きなので、インクルードとか飛ばします。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
  UErrorCode status = U_ZERO_ERROR;
 +
  //Calendar *cals = Calendar::createInstance(status);//日本語カレンダーロケールは ja_JP@calendar=japanese ja_JP_TRADITIONAL ja_JP ja japaneseが指定可能
 +
  Calendar *cals = Calendar::createInstance("ja_JP@calendar=japanese", status);
 +
  SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("SSS S U Q q W w e F D zzzz zzz zz z EEE EE E YYYY YYY YY Y yyyy yyy yy v GG G y.M.d vv HH:mm:ss vvvv K:mm a vvv hh:mm h:m KK:mm  H:m aaa yyyyy.MM.dd GGG"), status);
 +
  //SimpleDateFormat ★ja_JP(引数無し) ☆ja_JP_TRADITIONAL 1988年基準 年引数が1なら1989年で公元号1年 公元号名は表示されない。
 +
  //z    タイムゾーン名(★GMT+09:18:59 ☆JST)
 +
  //zz  タイムゾーン  (★GMT+09:18:59 ☆JST)
 +
  //zzz  タイムゾーン  (★GMT+09:18:59 ☆JST)
 +
  //zzzz タイムゾーン年-タイムゾーン名(★2014-GMT+09:18:59 ☆2014-日本標準時)
 +
  //v   タイムゾーン年-タイムゾーン名(★2014-日本時間 ☆2014-JST)
 +
  //vv  タイムゾーン  (★表記無し)
 +
  //vvv タイムゾーン  (★表記無し)
 +
  //vvvv タイムゾーン名(★日本時間 ☆日本標準時)
 +
  //G    グレゴリオ暦年-歴名(★2014-西暦 ☆平成)
 +
  //GG  グレゴリオ暦名(年数値無し★西暦 ☆平成)
 +
  //GGG  グレゴリオ暦名(年数値無し★西暦 ☆平成)
 +
  //YYYY グレゴリオ暦年-公元号年(★2014-0026 ☆2014-2014)
 +
  //YYY  公元号年orグレゴリオ暦年(3桁表現最小表現 0埋め★026 ☆2014)
 +
  //YY  公元号年orグレゴリオ暦年(2桁表現固定0埋め★26 ☆14)
 +
  //Y    公元号年orグレゴリオ暦年(最小文字列★26 ☆2014)
 +
  //yyyyy公元号年5桁数値のみ(0埋め)
 +
  //yyyy 公元号年4桁数値のみ(0埋め)
 +
  //yyy  公元号年3桁数値のみ(0埋め)
 +
  //yy  公元号年2桁数値のみ(0埋め)
 +
  //y    公元号年数値のみ
 +
  //M    数値表現の月(最小文字列)※小文字だと時間の分
 +
  //MM  数値表現の月(2桁表現)※小文字だと時間の分
 +
  //MMMMM数値表現の月(最小文字列)※小文字だと時間の分
 +
  //d    数値表現の日(最小文字列)
 +
  //dd  数値表現の日(2桁表現)
 +
  //EEE  曜日(★土 1日前の曜日 ☆日)
 +
  //EE  曜日(★土 1日前の曜日 ☆日)
 +
  //E    曜日(★土 1日前の曜日 ☆日)
 +
  //a  午前・午後表記(漢字日本語★午前)
 +
  //K    数値表現の時間(0時は0のまま 最小文字列)
 +
  //KK  数値表現の時間(0時は0のまま 2桁表現0埋め)
 +
  //H    数値表現の時間(24時間制 0時は0のまま 最小文字列)
 +
  //HH  数値表現の時間(24時間制 0時は0のまま 2桁表現0埋め)
 +
  //h    数値表現の時間(0時は12時 最小文字列)
 +
  //hh  数値表現の時間(0時は12時 2桁表現0埋め)
 +
  //m    数値用言の分(最小文字列)※大文字だと日付の月
 +
  //mm  数値用言の分(2桁表現0埋め)※大文字だと日付の月
 +
  //s    数値表現の秒(最小文字列)
 +
  //ss  数値表現の秒(2桁表現0埋め)
 +
  //その他
 +
  //S    ミリ秒
 +
  //u    extended年
 +
  //Q    四半期 テキスト&番号
 +
  //q
 +
  //w    週目 通年
 +
  //W    週目 月
 +
  //D    日目 通年   
 +
  //e    曜日番号
 +
  //F    何回目の曜日 月 
 +
  //
 +
 
 +
  fmt->adoptCalendar(cals);//フォーマットにカレンダーを設定。
 +
  for(int k=2014;k<2015;k++){
 +
    cals->set(k - 1988 , 10 - 1, 17, 14, 0, 0);//カレンダーの日付を数値で設定する方法 ja_JP_TRADITIONAは1988年基準 昭和元年が1989年
 +
    UDate now = cals->getTime(status);//nowに現在時間を取得。UDateはDouble型と同じです。
 +
    UnicodeString buf;
 +
    fmt->format(now, buf);//UnicodeString型のbufの内容をnowに設定されている時間を文字列にしたものに変換。変換は指定されているフォーマットの形式。
 +
    char* dst = new char[256];
 +
    std::string conv(buf.extract(0, buf.length(), 0, "shift_jis"), '\0');//string型convをbufの文字列のShiftJIS形式長さ分確保 初期値は\0で埋める
 +
    //UnicodeStringのextractはbufの中身を(第一引数 =0)文字目から、(第二引数 =buf.length())文字目までを第四引数にしていされた文字コードの型に変換して第三引数の変数に格納する関数
 +
    //変換先が指定されていない場合でも変換後の文字サイズが返却されます。ここでは文字サイズを取得してconvを初期化しています。
 +
    buf.extract(0, buf.length(), &conv[0], "shift_jis");//ここでconvに実際に変換後の文字を格納。
 +
    memcpy(dst, conv.c_str(), conv.size());//convの内容をchar型dstにコピー
 +
    printf("%d-%s ", k, conv.c_str());//convの内容を出力。
 +
    delete dst;
 +
  }
 +
  delete fmt;
 +
</syntaxhighlight2>
 +
出力 いろんな種類の出力をがっつり記述したので、わけわからないことになってますが
 +
<syntaxhighlight2 lang="text">
 +
2014-274 2 26 4 4 3 42 6 3 290 日本標準時 JST JST JST 金 金 金 2014 2014 14 2014 0026 026 26 JST 平成 平成 26.10.17  14:00:00 日本標準時 2:00 午後  02:00 2:0 02:00  14:0 午後 00026.10.17 平成
 +
</syntaxhighlight2>
 +
あとのほうのプログラムの方がタイムゾーン名を各国語で表示できる分、国際化には向いているかもしれませんが、そんなプログラム組む人いるのかなぁ。
 +
ロケール名一覧は後で示す日本語タイムゾーンの各ロケールごとの表示一覧に、タイムゾーン名一覧は各タイムゾーンの日本語表記一覧に記載しました。
 +
 
 +
 
 +
 
 +
UCalendarクラスやCalendarクラスの使い方はICUのサイトを確認して下さい。なんやかんやで長い記事になっているせいで忘れられているかもしれませんが、ここでは文字列操作に関する情報を中心に扱っています。ちなみにICUのサイトを見てもクラス仕様書がきっちりのっているものの個別の関数の具体的な使い方についてはあまり触れられていません。関数名と機能から、あぁこういう風に使って欲しいんだなっていうのを感じ取るスキルが求められます。なので自分もカレンダーのロケール名指定方法の詳細な一覧は入手できませんでした。もしわかった人がいたら、各自のブログやWikiで情報を発信して下さい。よろしくお願いします。たぶんICUをここまで掘り下げて使っている人はいないはず。上記に記述した各タイムゾーンやロケールの一覧を取得するにはStringEnumerationやUEnumerationクラスの使い方を理解したり、Locale、Timezoneクラスの構造を理解することが求められると思います。頑張ってください。
 +
 
 +
 
 +
それから、年号なんですけどサンプルプログラムのFor文では2014年だけの一回のループになってますが、ちょこっと変えて645年からにすると、まぁ素敵なほどに年号を羅列してくれます。他にも、日本のタイムゾーンが各国でどのように表示されているのか、あるいは、タイムゾーンがどれほどあるのかを一覧した、日本目線の一覧を貼っておきます。ICUは文字列操作の処理範囲をここまで広くかんがえているんだなあと考えさせられます。一種のデータベースと言えるかもしれません。うすっぺらな自分では調べきることは困難な範囲です。日本のことですらあまりわかっていないし…
 +
 
 +
 
 +
プログラムでUNICODE文字を出力してますが、コンソール表示のときにはSJISに変換されるため、SJISで表現できない文字は文字化け?というか変換先がないため正しく表示されません。正しく表示させたい場合は先の項目で説明したとおり、ファイル入出力をつかってUNICODE形式でテキストファイルに出力するといいです。Unicode対応のメモ帳で閲覧できます。Terapadは無理。自分は今回の機会にサクラエディタを導入しました。Unicodeも対応している優秀なエディタであることに気付かされました。UNICODEフォントですが、Windows標準のフォントファイルは実はUnicodeフォントになっています。すごいです。
 +
 
 +
年号サンプル <syntaxhighlight2 lang="text">
 +
645-大化1:646-大化2:647-大化3:648-大化4:649-大化5:650-白雉1:651-白雉2:652-白雉3:653-白雉4:654-白雉5:655-白雉6:656-白雉7:657-白雉8:658-白雉9:659-白雉10:660-白雉11:661-白雉12:662-白雉13:663-白雉14:664-白雉15:665-白雉16:666-白雉17:667-白雉18:668-白雉19:669-白雉20:670-白雉21:671-白雉22:672-白鳳1:673-白鳳2:674-白鳳3:675-白鳳4:676-白鳳5:677-白鳳6:678-白鳳7:679-白鳳8:680-白鳳9:681-白鳳10:682-白鳳11:683-白鳳12:684-白鳳13:685-白鳳14:686-朱鳥1:687-朱鳥2:688-朱鳥3:689-朱鳥4:690-朱鳥5:691-朱鳥6:692-朱鳥7:693-朱鳥8:694-朱鳥9:695-朱鳥10:696-朱鳥11:697-朱鳥12:698-朱鳥13:699-朱鳥14:700-朱鳥15:701-大宝1:702-大宝2:703-大宝3:704-慶雲1:705-慶雲2:706-慶雲3:707-慶雲4:708-和銅1:709-和銅2:710-和銅3:711-和銅4:712-和銅5:713-和銅6:714-和銅7:715-霊亀1:716-霊亀2:717-霊亀3:718-養老2:719-養老3:720-養老4:721-養老5:722-養老6:723-養老7:724-神亀1:725-神亀2:726-神亀3:727-神亀4:728-神亀5:729-天平1:730-天平2:731-天平3:732-天平4:733-天平5:734-天平6:735-天平7:736-天平8:737-天平9:738-天平10:739-天平11:740-天平12:741-天平13:742-天平14:743-天平15:744-天平16:745-天平17:746-天平18:747-天平19:748-天平20:749-天平勝宝1:750-天平勝宝2:751-天平勝宝3:752-天平勝宝4:753-天平勝宝5:754-天平勝宝6:755-天平勝宝7:756-天平勝宝8:757-天平宝字1:758-天平宝字2:759-天平宝字3:760-天平宝字4:761-天平宝字5:762-天平宝字6:763-天平宝字7:764-天平宝字8:765-天平神護1:766-天平神護2:767-神護景雲1:768-神護景雲2:769-神護景雲3:770-宝亀1:771-宝亀2:772-宝亀3:773-宝亀4:774-宝亀5:775-宝亀6:776-宝亀7:777-宝亀8:778-宝亀9:779-宝亀10:780-宝亀11:781-天応1:782-延暦1:783-延暦2:784-延暦3:785-延暦4:786-延暦5:787-延暦6:788-延暦7:789-延暦8:790-延暦9:791-延暦10:792-延暦11:793-延暦12:794-延暦13:795-延暦14:796-延暦15:797-延暦16:798-延暦17:799-延暦18:800-延暦19:801-延暦20:802-延暦21:803-延暦22:804-延暦23:805-延暦24:806-大同1:807-大同2:808-大同3:809-大同4:810-弘仁1:811-弘仁2:812-弘仁3:813-弘仁4:814-弘仁5:815-弘仁6:816-弘仁7:817-弘仁8:818-弘仁9:819-弘仁10:820-弘仁11:821-弘仁12:822-弘仁13:823-弘仁14:824-天長1:825-天長2:826-天長3:827-天長4:828-天長5:829-天長6:830-天長7:831-天長8:832-天長9:833-天長10:834-承和1:835-承和2:836-承和3:837-承和4:838-承和5:839-承和6:840-承和7:841-承和8:842-承和9:843-承和10:844-承和11:845-承和12:846-承和13:847-承和14:848-嘉祥1:849-嘉祥2:850-嘉祥3:851-仁寿1:852-仁寿2:853-仁寿3:854-仁寿4:855-斉衡2:856-斉衡3:857-天安1:858-天安2:859-貞観1:860-貞観2:861-貞観3:862-貞観4:863-貞観5:864-貞観6:865-貞観7:866-貞観8:867-貞観9:868-貞観10:869-貞観11:870-貞観12:871-貞観13:872-貞観14:873-貞観15:874-貞観16:875-貞観17:876-貞観18:877-元慶1:878-元慶2:879-元慶3:880-元慶4:881-元慶5:882-元慶6:883-元慶7:884-元慶8:885-仁和1:886-仁和2:887-仁和3:888-仁和4:889-寛平1:890-寛平2:891-寛平3:892-寛平4:893-寛平5:894-寛平6:895-寛平7:896-寛平8:897-寛平9:898-昌泰1:899-昌泰2:900-昌泰3:901-延喜1:902-延喜2:903-延喜3:904-延喜4:905-延喜5:906-延喜6:907-延喜7:908-延喜8:909-延喜9:910-延喜10:911-延喜11:912-延喜12:913-延喜13:914-延喜14:915-延喜15:916-延喜16:917-延喜17:918-延喜18:919-延喜19:920-延喜20:921-延喜21:922-延喜22:923-延長1:924-延長2:925-延長3:926-延長4:927-延長5:928-延長6:929-延長7:930-延長8:931-承平1:932-承平2:933-承平3:934-承平4:935-承平5:936-承平6:937-承平7:938-天慶1:939-天慶2:940-天慶3:941-天慶4:942-天慶5:943-天慶6:944-天慶7:945-天慶8:946-天慶9:947-天暦1:948-天暦2:949-天暦3:950-天暦4:951-天暦5:952-天暦6:953-天暦7:954-天暦8:955-天暦9:956-天暦10:957-天暦11:958-天徳2:959-天徳3:960-天徳4:961-応和1:962-応和2:963-応和3:964-康保1:965-康保2:966-康保3:967-康保4:968-安和1:969-安和2:970-天禄1:971-天禄2:972-天禄3:973-天禄4:974-天延2:975-天延3:976-貞元1:977-貞元2:978-貞元3:979-天元2:980-天元3:981-天元4:982-天元5:983-永観1:984-永観2:985-寛和1:986-寛和2:987-永延1:988-永延2:989-永祚1:990-永祚2:991-正暦2:992-正暦3:993-正暦4:994-正暦5:995-長徳1:996-長徳2:997-長徳3:998-長徳4:999-長保1:1000-長保2:1001-長保3:1002-長保4:1003-長保5:1004-寛弘1:1005-寛弘2:1006-寛弘3:1007-寛弘4:1008-寛弘5:1009-寛弘6:1010-寛弘7:1011-寛弘8:1012-寛弘9:1013-長和2:1014-長和3:1015-長和4:1016-長和5:1017-寛仁1:1018-寛仁2:1019-寛仁3:1020-寛仁4:1021-治安1:1022-治安2:1023-治安3:1024-万寿1:1025-万寿2:1026-万寿3:1027-万寿4:1028-長元1:1029-長元2:1030-長元3:1031-長元4:1032-長元5:1033-長元6:1034-長元7:1035-長元8:1036-長元9:1037-長暦1:1038-長暦2:1039-長暦3:1040-長暦4:1041-長久2:1042-長久3:1043-長久4:1044-長久5:1045-寛徳2:1046-永承1:1047-永承2:1048-永承3:1049-永承4:1050-永承5:1051-永承6:1052-永承7:1053-天喜1:1054-天喜2:1055-天喜3:1056-天喜4:1057-天喜5:1058-康平1:1059-康平2:1060-康平3:1061-康平4:1062-康平5:1063-康平6:1064-康平7:1065-治暦1:1066-治暦2:1067-治暦3:1068-治暦4:1069-延久1:1070-延久2:1071-延久3:1072-延久4:1073-延久5:1074-承保1:1075-承保2:1076-承保3:1077-承保4:1078-承暦2:1079-承暦3:1080-承暦4:1081-永保1:1082-永保2:1083-永保3:1084-応徳1:1085-応徳2:1086-応徳3:1087-寛治1:1088-寛治2:1089-寛治3:1090-寛治4:1091-寛治5:1092-寛治6:1093-寛治7:1094-寛治8:1095-嘉保2:1096-嘉保3:1097-永長2:1098-承徳2:1099-康和1:1100-康和2:1101-康和3:1102-康和4:1103-康和5:1104-長治1:1105-長治2:1106-嘉承1:1107-嘉承2:1108-天仁1:1109-天仁2:1110-天永1:1111-天永2:1112-天永3:1113-永久1:1114-永久2:1115-永久3:1116-永久4:1117-永久5:1118-元永1:1119-元永2:1120-保安1:1121-保安2:1122-保安3:1123-保安4:1124-天治1:1125-天治2:1126-大治1:1127-大治2:1128-大治3:1129-大治4:1130-大治5:1131-天承1:1132-長承1:1133-長承2:1134-長承3:1135-保延1:1136-保延2:1137-保延3:1138-保延4:1139-保延5:1140-保延6:1141-永治1:1142-康治1:1143-康治2:1144-天養1:1145-久安1:1146-久安2:1147-久安3:1148-久安4:1149-久安5:1150-久安6:1151-仁平1:1152-仁平2:1153-仁平3:1154-仁平4:1155-久寿2:1156-保元1:1157-保元2:1158-保元3:1159-平治1:1160-永暦1:1161-応保1:1162-応保2:1163-長寛1:1164-長寛2:1165-永万1:1166-仁安1:1167-仁安2:1168-仁安3:1169-嘉応1:1170-嘉応2:1171-承安1:1172-承安2:1173-承安3:1174-承安4:1175-安元1:1176-安元2:1177-治承1:1178-治承2:1179-治承3:1180-治承4:1181-養和1:1182-寿永1:1183-寿永2:1184-元暦1:1185-文治1:1186-文治2:1187-文治3:1188-文治4:1189-文治5:1190-建久1:1191-建久2:1192-建久3:1193-建久4:1194-建久5:1195-建久6:1196-建久7:1197-建久8:1198-建久9:1199-正治1:1200-正治2:1201-建仁1:1202-建仁2:1203-建仁3:1204-元久1:1205-元久2:1206-建永1:1207-建永2:1208-承元2:1209-承元3:1210-承元4:1211-建暦1:1212-建暦2:1213-建暦3:1214-建保2:1215-建保3:1216-建保4:1217-建保5:1218-建保6:1219-承久1:1220-承久2:1221-承久3:1222-貞応1:1223-貞応2:1224-貞応3:1225-嘉禄1:1226-嘉禄2:1227-嘉禄3:1228-安貞2:1229-寛喜1:1230-寛喜2:1231-寛喜3:1232-貞永1:1233-天福1:1234-天福2:1235-嘉禎1:1236-嘉禎2:1237-嘉禎3:1238-嘉禎4:1239-延応1:1240-仁治1:1241-仁治2:1242-仁治3:1243-寛元1:1244-寛元2:1245-寛元3:1246-寛元4:1247-宝治1:1248-宝治2:1249-建長1:1250-建長2:1251-建長3:1252-建長4:1253-建長5:1254-建長6:1255-建長7:1256-康元1:1257-正嘉1:1258-正嘉2:1259-正元1:1260-文応1:1261-弘長1:1262-弘長2:1263-弘長3:1264-文永1:1265-文永2:1266-文永3:1267-文永4:1268-文永5:1269-文永6:1270-文永7:1271-文永8:1272-文永9:1273-文永10:1274-文永11:1275-建治1:1276-建治2:1277-建治3:1278-弘安1:1279-弘安2:1280-弘安3:1281-弘安4:1282-弘安5:1283-弘安6:1284-弘安7:1285-弘安8:1286-弘安9:1287-弘安10:1288-正応1:1289-正応2:1290-正応3:1291-正応4:1292-正応5:1293-永仁1:1294-永仁2:1295-永仁3:1296-永仁4:1297-永仁5:1298-永仁6:1299-正安1:1300-正安2:1301-正安3:1302-正安4:1303-嘉元1:1304-嘉元2:1305-嘉元3:1306-嘉元4:1307-徳治2:1308-延慶1:1309-延慶2:1310-延慶3:1311-応長1:1312-正和1:1313-正和2:1314-正和3:1315-正和4:1316-正和5:1317-文保1:1318-文保2:1319-元応1:1320-元応2:1321-元亨1:1322-元亨2:1323-元亨3:1324-元亨4:1325-正中2:1326-嘉暦1:1327-嘉暦2:1328-嘉暦3:1329-元徳1:1330-元徳2:1331-元弘1:1332-元弘2:1333-元弘3:1334-建武1:1335-建武2:1336-延元1:1337-延元2:1338-延元3:1339-延元4:1340-興国1:1341-興国2:1342-興国3:1343-興国4:1344-興国5:1345-興国6:1346-興国7:1347-正平2:1348-正平3:1349-正平4:1350-正平5:1351-正平6:1352-正平7:1353-正平8:1354-正平9:1355-正平10:1356-正平11:1357-正平12:1358-正平13:1359-正平14:1360-正平15:1361-正平16:1362-正平17:1363-正平18:1364-正平19:1365-正平20:1366-正平21:1367-正平22:1368-正平23:1369-正平24:1370-建徳1:1371-建徳2:1372-文中1:1373-文中2:1374-文中3:1375-天授1:1376-天授2:1377-天授3:1378-天授4:1379-康暦1:1380-康暦2:1381-弘和1:1382-弘和2:1383-弘和3:1384-至徳1:1385-至徳2:1386-至徳3:1387-嘉慶1:1388-嘉慶2:1389-康応1:1390-明徳1:1391-明徳2:1392-明徳3:1393-明徳4:1394-応永1:1395-応永2:1396-応永3:1397-応永4:1398-応永5:1399-応永6:1400-応永7:1401-応永8:1402-応永9:1403-応永10:1404-応永11:1405-応永12:1406-応永13:1407-応永14:1408-応永15:1409-応永16:1410-応永17:1411-応永18:1412-応永19:1413-応永20:1414-応永21:1415-応永22:1416-応永23:1417-応永24:1418-応永25:1419-応永26:1420-応永27:1421-応永28:1422-応永29:1423-応永30:1424-応永31:1425-応永32:1426-応永33:1427-応永34:1428-正長1:1429-永享1:1430-永享2:1431-永享3:1432-永享4:1433-永享5:1434-永享6:1435-永享7:1436-永享8:1437-永享9:1438-永享10:1439-永享11:1440-永享12:1441-嘉吉1:1442-嘉吉2:1443-嘉吉3:1444-文安1:1445-文安2:1446-文安3:1447-文安4:1448-文安5:1449-宝徳1:1450-宝徳2:1451-宝徳3:1452-享徳1:1453-享徳2:1454-享徳3:1455-康正1:1456-康正2:1457-長禄1:1458-長禄2:1459-長禄3:1460-長禄4:1461-寛正2:1462-寛正3:1463-寛正4:1464-寛正5:1465-寛正6:1466-文正1:1467-応仁1:1468-応仁2:1469-文明1:1470-文明2:1471-文明3:1472-文明4:1473-文明5:1474-文明6:1475-文明7:1476-文明8:1477-文明9:1478-文明10:1479-文明11:1480-文明12:1481-文明13:1482-文明14:1483-文明15:1484-文明16:1485-文明17:1486-文明18:1487-長享1:1488-長享2:1489-延徳1:1490-延徳2:1491-延徳3:1492-明応1:1493-明応2:1494-明応3:1495-明応4:1496-明応5:1497-明応6:1498-明応7:1499-明応8:1500-明応9:1501-文亀1:1502-文亀2:1503-文亀3:1504-永正1:1505-永正2:1506-永正3:1507-永正4:1508-永正5:1509-永正6:1510-永正7:1511-永正8:1512-永正9:1513-永正10:1514-永正11:1515-永正12:1516-永正13:1517-永正14:1518-永正15:1519-永正16:1520-永正17:1521-大永1:1522-大永2:1523-大永3:1524-大永4:1525-大永5:1526-大永6:1527-大永7:1528-享禄1:1529-享禄2:1530-享禄3:1531-享禄4:1532-天文1:1533-天文2:1534-天文3:1535-天文4:1536-天文5:1537-天文6:1538-天文7:1539-天文8:1540-天文9:1541-天文10:1542-天文11:1543-天文12:1544-天文13:1545-天文14:1546-天文15:1547-天文16:1548-天文17:1549-天文18:1550-天文19:1551-天文20:1552-天文21:1553-天文22:1554-天文23:1555-天文24:1556-弘治2:1557-弘治3:1558-永禄1:1559-永禄2:1560-永禄3:1561-永禄4:1562-永禄5:1563-永禄6:1564-永禄7:1565-永禄8:1566-永禄9:1567-永禄10:1568-永禄11:1569-永禄12:1570-元亀1:1571-元亀2:1572-元亀3:1573-天正1:1574-天正2:1575-天正3:1576-天正4:1577-天正5:1578-天正6:1579-天正7:1580-天正8:1581-天正9:1582-天正10:1583-天正11:1584-天正12:1585-天正13:1586-天正14:1587-天正15:1588-天正16:1589-天正17:1590-天正18:1591-天正19:1592-天正20:1593-文禄2:1594-文禄3:1595-文禄4:1596-文禄5:1597-慶長2:1598-慶長3:1599-慶長4:1600-慶長5:1601-慶長6:1602-慶長7:1603-慶長8:1604-慶長9:1605-慶長10:1606-慶長11:1607-慶長12:1608-慶長13:1609-慶長14:1610-慶長15:1611-慶長16:1612-慶長17:1613-慶長18:1614-慶長19:1615-元和1:1616-元和2:1617-元和3:1618-元和4:1619-元和5:1620-元和6:1621-元和7:1622-元和8:1623-元和9:1624-寛永1:1625-寛永2:1626-寛永3:1627-寛永4:1628-寛永5:1629-寛永6:1630-寛永7:1631-寛永8:1632-寛永9:1633-寛永10:1634-寛永11:1635-寛永12:1636-寛永13:1637-寛永14:1638-寛永15:1639-寛永16:1640-寛永17:1641-寛永18:1642-寛永19:1643-寛永20:1644-寛永21:1645-正保2:1646-正保3:1647-正保4:1648-慶安1:1649-慶安2:1650-慶安3:1651-慶安4:1652-承応1:1653-承応2:1654-承応3:1655-明暦1:1656-明暦2:1657-明暦3:1658-万治1:1659-万治2:1660-万治3:1661-寛文1:1662-寛文2:1663-寛文3:1664-寛文4:1665-寛文5:1666-寛文6:1667-寛文7:1668-寛文8:1669-寛文9:1670-寛文10:1671-寛文11:1672-寛文12:1673-延宝1:1674-延宝2:1675-延宝3:1676-延宝4:1677-延宝5:1678-延宝6:1679-延宝7:1680-延宝8:1681-天和1:1682-天和2:1683-天和3:1684-貞享1:1685-貞享2:1686-貞享3:1687-貞享4:1688-元禄1:1689-元禄2:1690-元禄3:1691-元禄4:1692-元禄5:1693-元禄6:1694-元禄7:1695-元禄8:1696-元禄9:1697-元禄10:1698-元禄11:1699-元禄12:1700-元禄13:1701-元禄14:1702-元禄15:1703-元禄16:1704-宝永1:1705-宝永2:1706-宝永3:1707-宝永4:1708-宝永5:1709-宝永6:1710-宝永7:1711-正徳1:1712-正徳2:1713-正徳3:1714-正徳4:1715-正徳5:1716-享保1:1717-享保2:1718-享保3:1719-享保4:1720-享保5:1721-享保6:1722-享保7:1723-享保8:1724-享保9:1725-享保10:1726-享保11:1727-享保12:1728-享保13:1729-享保14:1730-享保15:1731-享保16:1732-享保17:1733-享保18:1734-享保19:1735-享保20:1736-元文1:1737-元文2:1738-元文3:1739-元文4:1740-元文5:1741-寛保1:1742-寛保2:1743-寛保3:1744-延享1:1745-延享2:1746-延享3:1747-延享4:1748-寛延1:1749-寛延2:1750-寛延3:1751-寛延4:1752-宝暦2:1753-宝暦3:1754-宝暦4:1755-宝暦5:1756-宝暦6:1757-宝暦7:1758-宝暦8:1759-宝暦9:1760-宝暦10:1761-宝暦11:1762-宝暦12:1763-宝暦13:1764-明和1:1765-明和2:1766-明和3:1767-明和4:1768-明和5:1769-明和6:1770-明和7:1771-明和8:1772-明和9:1773-安永2:1774-安永3:1775-安永4:1776-安永5:1777-安永6:1778-安永7:1779-安永8:1780-安永9:1781-天明1:1782-天明2:1783-天明3:1784-天明4:1785-天明5:1786-天明6:1787-天明7:1788-天明8:1789-寛政1:1790-寛政2:1791-寛政3:1792-寛政4:1793-寛政5:1794-寛政6:1795-寛政7:1796-寛政8:1797-寛政9:1798-寛政10:1799-寛政11:1800-寛政12:1801-享和1:1802-享和2:1803-享和3:1804-文化1:1805-文化2:1806-文化3:1807-文化4:1808-文化5:1809-文化6:1810-文化7:1811-文化8:1812-文化9:1813-文化10:1814-文化11:1815-文化12:1816-文化13:1817-文化14:1818-文政1:1819-文政2:1820-文政3:1821-文政4:1822-文政5:1823-文政6:1824-文政7:1825-文政8:1826-文政9:1827-文政10:1828-文政11:1829-文政12:1830-文政13:1831-天保2:1832-天保3:1833-天保4:1834-天保5:1835-天保6:1836-天保7:1837-天保8:1838-天保9:1839-天保10:1840-天保11:1841-天保12:1842-天保13:1843-天保14:1844-天保15:1845-弘化2:1846-弘化3:1847-弘化4:1848-嘉永1:1849-嘉永2:1850-嘉永3:1851-嘉永4:1852-嘉永5:1853-嘉永6:1854-嘉永7:1855-安政2:1856-安政3:1857-安政4:1858-安政5:1859-安政6:1860-万延1:1861-文久1:1862-文久2:1863-文久3:1864-元治1:1865-慶応1:1866-慶応2:1867-慶応3:1868-明治1:1869-明治2:1870-明治3:1871-明治4:1872-明治5:1873-明治6:1874-明治7:1875-明治8:1876-明治9:1877-明治10:1878-明治11:1879-明治12:1880-明治13:1881-明治14:1882-明治15:1883-明治16:1884-明治17:1885-明治18:1886-明治19:1887-明治20:1888-明治21:1889-明治22:1890-明治23:1891-明治24:1892-明治25:1893-明治26:1894-明治27:1895-明治28:1896-明治29:1897-明治30:1898-明治31:1899-明治32:1900-明治33:1901-明治34:1902-明治35:1903-明治36:1904-明治37:1905-明治38:1906-明治39:1907-明治40:1908-明治41:1909-明治42:1910-明治43:1911-明治44:1912-大正1:1913-大正2:1914-大正3:1915-大正4:1916-大正5:1917-大正6:1918-大正7:1919-大正8:1920-大正9:1921-大正10:1922-大正11:1923-大正12:1924-大正13:1925-大正14:1926-大正15:1927-昭和2:1928-昭和3:1929-昭和4:1930-昭和5:1931-昭和6:1932-昭和7:1933-昭和8:1934-昭和9:1935-昭和10:1936-昭和11:1937-昭和12:1938-昭和13:1939-昭和14:1940-昭和15:1941-昭和16:1942-昭和17:1943-昭和18:1944-昭和19:1945-昭和20:1946-昭和21:1947-昭和22:1948-昭和23:1949-昭和24:1950-昭和25:1951-昭和26:1952-昭和27:1953-昭和28:1954-昭和29:1955-昭和30:1956-昭和31:1957-昭和32:1958-昭和33:1959-昭和34:1960-昭和35:1961-昭和36:1962-昭和37:1963-昭和38:1964-昭和39:1965-昭和40:1966-昭和41:1967-昭和42:1968-昭和43:1969-昭和44:1970-昭和45:1971-昭和46:1972-昭和47:1973-昭和48:1974-昭和49:1975-昭和50:1976-昭和51:1977-昭和52:1978-昭和53:1979-昭和54:1980-昭和55:1981-昭和56:1982-昭和57:1983-昭和58:1984-昭和59:1985-昭和60:1986-昭和61:1987-昭和62:1988-昭和63:1989-平成1:1990-平成2:1991-平成3:1992-平成4:1993-平成5:1994-平成6:1995-平成7:1996-平成8:1997-平成9:1998-平成10:1999-平成11:2000-平成12:2001-平成13:2002-平成14:2003-平成15:2004-平成16:2005-平成17:2006-平成18:2007-平成19:2008-平成20:2009-平成21:2010-平成22:2011-平成23:2012-平成24:2013-平成25:2014-平成26
 +
</syntaxhighlight2>
 +
 
 +
タイムゾーン名
 +
<syntaxhighlight2 lang="text">
 +
ACT                              オーストラリア中部標準時
 +
AET                              オーストラリア東部標準時
 +
AGT                              アルゼンチン標準時
 +
ART                              東ヨーロッパ標準時
 +
AST                              アラスカ標準時
 +
Africa/Abidjan                  グリニッジ標準時
 +
Africa/Accra                    グリニッジ標準時
 +
Africa/Addis_Ababa              東アフリカ時間
 +
Africa/Algiers                  中央ヨーロッパ標準時
 +
Africa/Asmara                    東アフリカ時間
 +
Africa/Asmera                    東アフリカ時間
 +
Africa/Bamako                    グリニッジ標準時
 +
Africa/Bangui                    西アフリカ標準時
 +
Africa/Banjul                    グリニッジ標準時
 +
Africa/Bissau                    グリニッジ標準時
 +
Africa/Blantyre                  中央アフリカ時間
 +
Africa/Brazzaville              西アフリカ標準時
 +
Africa/Bujumbura                中央アフリカ時間
 +
Africa/Cairo                    東ヨーロッパ標準時
 +
Africa/Casablanca                西ヨーロッパ標準時
 +
Africa/Ceuta                    中央ヨーロッパ標準時
 +
Africa/Conakry                  グリニッジ標準時
 +
Africa/Dakar                    グリニッジ標準時
 +
Africa/Dar_es_Salaam            東アフリカ時間
 +
Africa/Djibouti                  東アフリカ時間
 +
Africa/Douala                    西アフリカ標準時
 +
Africa/El_Aaiun                  西ヨーロッパ標準時
 +
Africa/Freetown                  グリニッジ標準時
 +
Africa/Gaborone                  中央アフリカ時間
 +
Africa/Harare                    中央アフリカ時間
 +
Africa/Johannesburg              南アフリカ標準時
 +
Africa/Juba                      東アフリカ時間
 +
Africa/Kampala                  東アフリカ時間
 +
Africa/Khartoum                  東アフリカ時間
 +
Africa/Kigali                    中央アフリカ時間
 +
Africa/Kinshasa                  西アフリカ標準時
 +
Africa/Lagos                    西アフリカ標準時
 +
Africa/Libreville                西アフリカ標準時
 +
Africa/Lome                      グリニッジ標準時
 +
Africa/Luanda                    西アフリカ標準時
 +
Africa/Lubumbashi                中央アフリカ時間
 +
Africa/Lusaka                    中央アフリカ時間
 +
Africa/Malabo                    西アフリカ標準時
 +
Africa/Maputo                    中央アフリカ時間
 +
Africa/Maseru                    南アフリカ標準時
 +
Africa/Mbabane                  南アフリカ標準時
 +
Africa/Mogadishu                東アフリカ時間
 +
Africa/Monrovia                  グリニッジ標準時
 +
Africa/Nairobi                  東アフリカ時間
 +
Africa/Ndjamena                  西アフリカ標準時
 +
Africa/Niamey                    西アフリカ標準時
 +
Africa/Nouakchott                グリニッジ標準時
 +
Africa/Ouagadougou              グリニッジ標準時
 +
Africa/Porto-Novo                西アフリカ標準時
 +
Africa/Sao_Tome                  グリニッジ標準時
 +
Africa/Timbuktu                  グリニッジ標準時
 +
Africa/Tripoli                  東ヨーロッパ標準時
 +
Africa/Tunis                    中央ヨーロッパ標準時
 +
Africa/Windhoek                  西アフリカ標準時
 +
America/Adak                    ハワイ・アリューシャン標準時
 +
America/Anchorage                アラスカ標準時
 +
America/Anguilla                大西洋標準時
 +
America/Antigua                  大西洋標準時
 +
America/Araguaina                ブラジリア標準時
 +
America/Argentina/Buenos_Aires  アルゼンチン標準時
 +
America/Argentina/Catamarca      アルゼンチン標準時
 +
America/Argentina/ComodRivadavia アルゼンチン標準時
 +
America/Argentina/Cordoba        アルゼンチン標準時
 +
America/Argentina/Jujuy          アルゼンチン標準時
 +
America/Argentina/La_Rioja      アルゼンチン標準時
 +
America/Argentina/Mendoza        アルゼンチン標準時
 +
America/Argentina/Rio_Gallegos  アルゼンチン標準時
 +
America/Argentina/Salta          アルゼンチン標準時
 +
America/Argentina/San_Juan      アルゼンチン標準時
 +
America/Argentina/San_Luis      西部アルゼンチン標準時
 +
America/Argentina/Tucuman        アルゼンチン標準時
 +
America/Argentina/Ushuaia        アルゼンチン標準時
 +
America/Aruba                    大西洋標準時
 +
America/Asuncion                パラグアイ標準時
 +
America/Atikokan                アメリカ東部標準時
 +
America/Atka                    ハワイ・アリューシャン標準時
 +
America/Bahia                    ブラジリア標準時
 +
America/Bahia_Banderas          アメリカ中部標準時
 +
America/Barbados                大西洋標準時
 +
America/Belem                    ブラジリア標準時
 +
America/Belize                  アメリカ中部標準時
 +
America/Blanc-Sablon            大西洋標準時
 +
America/Boa_Vista                アマゾン標準時
 +
America/Bogota                  コロンビア標準時
 +
America/Boise                    アメリカ山地標準時
 +
America/Buenos_Aires            アルゼンチン標準時
 +
America/Cambridge_Bay            アメリカ山地標準時
 +
America/Campo_Grande            アマゾン標準時
 +
America/Cancun                  アメリカ中部標準時
 +
America/Caracas                  ベネズエラ時間
 +
America/Catamarca                アルゼンチン標準時
 +
America/Cayenne                  仏領ギアナ時間
 +
America/Cayman                  アメリカ東部標準時
 +
America/Chicago                  アメリカ中部標準時
 +
America/Chihuahua                メキシコ太平洋標準時
 +
America/Coral_Harbour            アメリカ東部標準時
 +
America/Cordoba                  アルゼンチン標準時
 +
America/Costa_Rica              アメリカ中部標準時
 +
America/Creston                  アメリカ山地標準時
 +
America/Cuiaba                  アマゾン標準時
 +
America/Curacao                  大西洋標準時
 +
America/Danmarkshavn            グリニッジ標準時
 +
America/Dawson                  アメリカ太平洋標準時
 +
America/Dawson_Creek            アメリカ山地標準時
 +
America/Denver                  アメリカ山地標準時
 +
America/Detroit                  アメリカ東部標準時
 +
America/Dominica                大西洋標準時
 +
America/Edmonton                アメリカ山地標準時
 +
America/Eirunepe                アクレ標準時
 +
America/El_Salvador              アメリカ中部標準時
 +
America/Ensenada                アメリカ太平洋標準時
 +
America/Fort_Wayne              アメリカ東部標準時
 +
America/Fortaleza                ブラジリア標準時
 +
America/Glace_Bay                大西洋標準時
 +
America/Godthab                  グリーンランド西部標準時
 +
America/Goose_Bay                大西洋標準時
 +
America/Grand_Turk              アメリカ東部標準時
 +
America/Grenada                  大西洋標準時
 +
America/Guadeloupe              大西洋標準時
 +
America/Guatemala                アメリカ中部標準時
 +
America/Guayaquil                エクアドル時間
 +
America/Guyana                  ガイアナ時間
 +
America/Halifax                  大西洋標準時
 +
America/Havana                  キューバ標準時
 +
America/Hermosillo              メキシコ太平洋標準時
 +
America/Indiana/Indianapolis    アメリカ東部標準時
 +
America/Indiana/Knox            アメリカ中部標準時
 +
America/Indiana/Marengo          アメリカ東部標準時
 +
America/Indiana/Petersburg      アメリカ東部標準時
 +
America/Indiana/Tell_City        アメリカ中部標準時
 +
America/Indiana/Vevay            アメリカ東部標準時
 +
America/Indiana/Vincennes        アメリカ東部標準時
 +
America/Indiana/Winamac          アメリカ東部標準時
 +
America/Indianapolis            アメリカ東部標準時
 +
America/Inuvik                  アメリカ山地標準時
 +
America/Iqaluit                  アメリカ東部標準時
 +
America/Jamaica                  アメリカ東部標準時
 +
America/Jujuy                    アルゼンチン標準時
 +
America/Juneau                  アラスカ標準時
 +
America/Kentucky/Louisville      アメリカ東部標準時
 +
America/Kentucky/Monticello      アメリカ東部標準時
 +
America/Knox_IN                  アメリカ中部標準時
 +
America/Kralendijk              大西洋標準時
 +
America/La_Paz                  ボリビア時間
 +
America/Lima                    ペルー標準時
 +
America/Los_Angeles              アメリカ太平洋標準時
 +
America/Louisville              アメリカ東部標準時
 +
America/Lower_Princes            大西洋標準時
 +
America/Maceio                  ブラジリア標準時
 +
America/Managua                  アメリカ中部標準時
 +
America/Manaus                  アマゾン標準時
 +
America/Marigot                  大西洋標準時
 +
America/Martinique              大西洋標準時
 +
America/Matamoros                アメリカ中部標準時
 +
America/Mazatlan                メキシコ太平洋標準時
 +
America/Mendoza                  アルゼンチン標準時
 +
America/Menominee                アメリカ中部標準時
 +
America/Merida                  アメリカ中部標準時
 +
America/Metlakatla              アメリカ太平洋標準時
 +
America/Mexico_City              アメリカ中部標準時
 +
America/Miquelon                サンピエール・ミクロン標準時
 +
America/Moncton                  大西洋標準時
 +
America/Monterrey                アメリカ中部標準時
 +
America/Montevideo              ウルグアイ標準時
 +
America/Montreal                GMT-05:00
 +
America/Montserrat              大西洋標準時
 +
America/Nassau                  アメリカ東部標準時
 +
America/New_York                アメリカ東部標準時
 +
America/Nipigon                  アメリカ東部標準時
 +
America/Nome                    アラスカ標準時
 +
America/Noronha                  フェルナンド・デ・ノローニャ標準時
 +
America/North_Dakota/Beulah      アメリカ中部標準時
 +
America/North_Dakota/Center      アメリカ中部標準時
 +
America/North_Dakota/New_Salem  アメリカ中部標準時
 +
America/Ojinaga                  アメリカ山地標準時
 +
America/Panama                  アメリカ東部標準時
 +
America/Pangnirtung              アメリカ東部標準時
 +
America/Paramaribo              スリナム時間
 +
America/Phoenix                  アメリカ山地標準時
 +
America/Port-au-Prince          アメリカ東部標準時
 +
America/Port_of_Spain            大西洋標準時
 +
America/Porto_Acre              アクレ標準時
 +
America/Porto_Velho              アマゾン標準時
 +
America/Puerto_Rico              大西洋標準時
 +
America/Rainy_River              アメリカ中部標準時
 +
America/Rankin_Inlet            アメリカ中部標準時
 +
America/Recife                  ブラジリア標準時
 +
America/Regina                  アメリカ中部標準時
 +
America/Resolute                アメリカ中部標準時
 +
America/Rio_Branco              アクレ標準時
 +
America/Rosario                  アルゼンチン標準時
 +
America/Santa_Isabel            メキシコ北西部標準時
 +
America/Santarem                ブラジリア標準時
 +
America/Santiago                チリ標準時
 +
America/Santo_Domingo            大西洋標準時
 +
America/Sao_Paulo                ブラジリア標準時
 +
America/Scoresbysund            グリーンランド東部標準時
 +
America/Shiprock                アメリカ山地標準時
 +
America/Sitka                    アラスカ標準時
 +
America/St_Barthelemy            大西洋標準時
 +
America/St_Johns                ニューファンドランド標準時
 +
America/St_Kitts                大西洋標準時
 +
America/St_Lucia                大西洋標準時
 +
America/St_Thomas                大西洋標準時
 +
America/St_Vincent              大西洋標準時
 +
America/Swift_Current            アメリカ中部標準時
 +
America/Tegucigalpa              アメリカ中部標準時
 +
America/Thule                    大西洋標準時
 +
America/Thunder_Bay              アメリカ東部標準時
 +
America/Tijuana                  アメリカ太平洋標準時
 +
America/Toronto                  アメリカ東部標準時
 +
America/Tortola                  大西洋標準時
 +
America/Vancouver                アメリカ太平洋標準時
 +
America/Virgin                  大西洋標準時
 +
America/Whitehorse              アメリカ太平洋標準時
 +
America/Winnipeg                アメリカ中部標準時
 +
America/Yakutat                  アラスカ標準時
 +
America/Yellowknife              アメリカ山地標準時
 +
Antarctica/Casey                オーストラリア西部標準時
 +
Antarctica/Davis                デービス基地時間
 +
Antarctica/DumontDUrville        デュモン・デュルヴィル基地時間
 +
Antarctica/Macquarie            マッコーリー島時間
 +
Antarctica/Mawson                モーソン基地時間
 +
Antarctica/McMurdo              ニュージーランド標準時
 +
Antarctica/Palmer                チリ標準時
 +
Antarctica/Rothera              ロゼラ基地時間
 +
Antarctica/South_Pole            ニュージーランド標準時
 +
Antarctica/Syowa                昭和基地時間
 +
Antarctica/Troll                グリニッジ標準時
 +
Antarctica/Vostok                ボストーク基地時間
 +
Arctic/Longyearbyen              中央ヨーロッパ標準時
 +
Asia/Aden                        アラビア標準時
 +
Asia/Almaty                      東カザフスタン時間
 +
Asia/Amman                      東ヨーロッパ標準時
 +
Asia/Anadyr                      マガダン標準時
 +
Asia/Aqtau                      西カザフスタン時間
 +
Asia/Aqtobe                      西カザフスタン時間
 +
Asia/Ashgabat                    トルクメニスタン標準時
 +
Asia/Ashkhabad                  トルクメニスタン標準時
 +
Asia/Baghdad                    アラビア標準時
 +
Asia/Bahrain                    アラビア標準時
 +
Asia/Baku                        アゼルバイジャン標準時
 +
Asia/Bangkok                    インドシナ時間
 +
Asia/Beirut                      東ヨーロッパ標準時
 +
Asia/Bishkek                    キルギスタン時間
 +
Asia/Brunei                      ブルネイ・ダルサラーム時間
 +
Asia/Calcutta                    インド標準時
 +
Asia/Chita                      ヤクーツク標準時
 +
Asia/Choibalsan                  チョイバルサン標準時
 +
Asia/Chongqing                  中国標準時
 +
Asia/Chungking                  中国標準時
 +
Asia/Colombo                    インド標準時
 +
Asia/Dacca                      バングラデシュ標準時
 +
Asia/Damascus                    東ヨーロッパ標準時
 +
Asia/Dhaka                      バングラデシュ標準時
 +
Asia/Dili                        東ティモール時間
 +
Asia/Dubai                      湾岸標準時
 +
Asia/Dushanbe                    タジキスタン時間
 +
Asia/Gaza                        東ヨーロッパ標準時
 +
Asia/Harbin                      中国標準時
 +
Asia/Hebron                      東ヨーロッパ標準時
 +
Asia/Ho_Chi_Minh                インドシナ時間
 +
Asia/Hong_Kong                  香港標準時
 +
Asia/Hovd                        ホブド標準時
 +
Asia/Irkutsk                    イルクーツク標準時
 +
Asia/Istanbul                    東ヨーロッパ標準時
 +
Asia/Jakarta                    インドネシア西部時間
 +
Asia/Jayapura                    インドネシア東部時間
 +
Asia/Jerusalem                  イスラエル標準時
 +
Asia/Kabul                      アフガニスタン時間
 +
Asia/Kamchatka                  マガダン標準時
 +
Asia/Karachi                    パキスタン標準時
 +
Asia/Kashgar                    GMT+06:00
 +
Asia/Kathmandu                  ネパール時間
 +
Asia/Katmandu                    ネパール時間
 +
Asia/Khandyga                    ヤクーツク標準時
 +
Asia/Kolkata                    インド標準時
 +
Asia/Krasnoyarsk                クラスノヤルスク標準時
 +
Asia/Kuala_Lumpur                マレーシア時間
 +
Asia/Kuching                    マレーシア時間
 +
Asia/Kuwait                      アラビア標準時
 +
Asia/Macao                      中国標準時
 +
Asia/Macau                      中国標準時
 +
Asia/Magadan                    マガダン標準時
 +
Asia/Makassar                    インドネシア中部時間
 +
Asia/Manila                      フィリピン標準時
 +
Asia/Muscat                      湾岸標準時
 +
Asia/Nicosia                    東ヨーロッパ標準時
 +
Asia/Novokuznetsk                ノヴォシビルスク標準時
 +
Asia/Novosibirsk                ノヴォシビルスク標準時
 +
Asia/Omsk                        オムスク標準時
 +
Asia/Oral                        西カザフスタン時間
 +
Asia/Phnom_Penh                  インドシナ時間
 +
Asia/Pontianak                  インドネシア西部時間
 +
Asia/Pyongyang                  韓国標準時
 +
Asia/Qatar                      アラビア標準時
 +
Asia/Qyzylorda                  東カザフスタン時間
 +
Asia/Rangoon                    ミャンマー時間
 +
Asia/Riyadh                      アラビア標準時
 +
Asia/Saigon                      インドシナ時間
 +
Asia/Sakhalin                    サハリン標準時
 +
Asia/Samarkand                  ウズベキスタン標準時
 +
Asia/Seoul                      韓国標準時
 +
Asia/Shanghai                    中国標準時
 +
Asia/Singapore                  シンガポール標準時
 +
Asia/Srednekolymsk              マガダン標準時
 +
Asia/Taipei                      台北標準時
 +
Asia/Tashkent                    ウズベキスタン標準時
 +
Asia/Tbilisi                    グルジア標準時
 +
Asia/Tehran                      イラン標準時
 +
Asia/Tel_Aviv                    イスラエル標準時
 +
Asia/Thimbu                      ブータン時間
 +
Asia/Thimphu                    ブータン時間
 +
Asia/Tokyo                      日本標準時
 +
Asia/Ujung_Pandang              インドネシア中部時間
 +
Asia/Ulaanbaatar                ウランバートル標準時
 +
Asia/Ulan_Bator                  ウランバートル標準時
 +
Asia/Urumqi                      GMT+06:00
 +
Asia/Ust-Nera                    ウラジオストク標準時
 +
Asia/Vientiane                  インドシナ時間
 +
Asia/Vladivostok                ウラジオストク標準時
 +
Asia/Yakutsk                    ヤクーツク標準時
 +
Asia/Yekaterinburg              エカテリンブルグ標準時
 +
Asia/Yerevan                    アルメニア標準時
 +
Atlantic/Azores                  アゾレス標準時
 +
Atlantic/Bermuda                大西洋標準時
 +
Atlantic/Canary                  西ヨーロッパ標準時
 +
Atlantic/Cape_Verde              カーボベルデ標準時
 +
Atlantic/Faeroe                  西ヨーロッパ標準時
 +
Atlantic/Faroe                  西ヨーロッパ標準時
 +
Atlantic/Jan_Mayen              中央ヨーロッパ標準時
 +
Atlantic/Madeira                西ヨーロッパ標準時
 +
Atlantic/Reykjavik              グリニッジ標準時
 +
Atlantic/South_Georgia          サウスジョージア時間
 +
Atlantic/St_Helena              グリニッジ標準時
 +
Atlantic/Stanley                フォークランド諸島標準時
 +
Australia/ACT                    オーストラリア東部標準時
 +
Australia/Adelaide              オーストラリア中部標準時
 +
Australia/Brisbane              オーストラリア東部標準時
 +
Australia/Broken_Hill            オーストラリア中部標準時
 +
Australia/Canberra              オーストラリア東部標準時
 +
Australia/Currie                オーストラリア東部標準時
 +
Australia/Darwin                オーストラリア中部標準時
 +
Australia/Eucla                  オーストラリア中西部標準時
 +
Australia/Hobart                オーストラリア東部標準時
 +
Australia/LHI                    ロードハウ標準時
 +
Australia/Lindeman              オーストラリア東部標準時
 +
Australia/Lord_Howe              ロードハウ標準時
 +
Australia/Melbourne              オーストラリア東部標準時
 +
Australia/NSW                    オーストラリア東部標準時
 +
Australia/North                  オーストラリア中部標準時
 +
Australia/Perth                  オーストラリア西部標準時
 +
Australia/Queensland            オーストラリア東部標準時
 +
Australia/South                  オーストラリア中部標準時
 +
Australia/Sydney                オーストラリア東部標準時
 +
Australia/Tasmania              オーストラリア東部標準時
 +
Australia/Victoria              オーストラリア東部標準時
 +
Australia/West                  オーストラリア西部標準時
 +
Australia/Yancowinna            オーストラリア中部標準時
 +
BET                              ブラジリア標準時
 +
BST                              バングラデシュ標準時
 +
Brazil/Acre                      アクレ標準時
 +
Brazil/DeNoronha                フェルナンド・デ・ノローニャ標準時
 +
Brazil/East                      ブラジリア標準時
 +
Brazil/West                      アマゾン標準時
 +
CAT                              中央アフリカ時間
 +
CET                              GMT+01:00
 +
CNT                              ニューファンドランド標準時
 +
CST                              アメリカ中部標準時
 +
CST6CDT                          アメリカ中部標準時
 +
CTT                              中国標準時
 +
Canada/Atlantic                  大西洋標準時
 +
Canada/Central                  アメリカ中部標準時
 +
Canada/East-Saskatchewan        アメリカ中部標準時
 +
Canada/Eastern                  アメリカ東部標準時
 +
Canada/Mountain                  アメリカ山地標準時
 +
Canada/Newfoundland              ニューファンドランド標準時
 +
Canada/Pacific                  アメリカ太平洋標準時
 +
Canada/Saskatchewan              アメリカ中部標準時
 +
Canada/Yukon                    アメリカ太平洋標準時
 +
Chile/Continental                チリ標準時
 +
Chile/EasterIsland              イースター島標準時
 +
Cuba                            キューバ標準時
 +
EAT                              東アフリカ時間
 +
ECT                              中央ヨーロッパ標準時
 +
EET                              GMT+02:00
 +
EST                              GMT-05:00
 +
EST5EDT                          アメリカ東部標準時
 +
Egypt                            東ヨーロッパ標準時
 +
Eire                            グリニッジ標準時
 +
Etc/GMT                          GMT
 +
Etc/GMT+0                        GMT
 +
Etc/GMT+1                        GMT-01:00
 +
Etc/GMT+10                      GMT-10:00
 +
Etc/GMT+11                      GMT-11:00
 +
Etc/GMT+12                      GMT-12:00
 +
Etc/GMT+2                        GMT-02:00
 +
Etc/GMT+3                        GMT-03:00
 +
Etc/GMT+4                        GMT-04:00
 +
Etc/GMT+5                        GMT-05:00
 +
Etc/GMT+6                        GMT-06:00
 +
Etc/GMT+7                        GMT-07:00
 +
Etc/GMT+8                        GMT-08:00
 +
Etc/GMT+9                        GMT-09:00
 +
Etc/GMT-0                        GMT
 +
Etc/GMT-1                        GMT+01:00
 +
Etc/GMT-10                      GMT+10:00
 +
Etc/GMT-11                      GMT+11:00
 +
Etc/GMT-12                      GMT+12:00
 +
Etc/GMT-13                      GMT+13:00
 +
Etc/GMT-14                      GMT+14:00
 +
Etc/GMT-2                        GMT+02:00
 +
Etc/GMT-3                        GMT+03:00
 +
Etc/GMT-4                        GMT+04:00
 +
Etc/GMT-5                        GMT+05:00
 +
Etc/GMT-6                        GMT+06:00
 +
Etc/GMT-7                        GMT+07:00
 +
Etc/GMT-8                        GMT+08:00
 +
Etc/GMT-9                        GMT+09:00
 +
Etc/GMT0                        GMT
 +
Etc/Greenwich                    GMT
 +
Etc/UCT                          GMT
 +
Etc/UTC                          GMT
 +
Etc/Universal                    GMT
 +
Etc/Zulu                        GMT
 +
Europe/Amsterdam                中央ヨーロッパ標準時
 +
Europe/Andorra                  中央ヨーロッパ標準時
 +
Europe/Athens                    東ヨーロッパ標準時
 +
Europe/Belfast                  グリニッジ標準時
 +
Europe/Belgrade                  中央ヨーロッパ標準時
 +
Europe/Berlin                    中央ヨーロッパ標準時
 +
Europe/Bratislava                中央ヨーロッパ標準時
 +
Europe/Brussels                  中央ヨーロッパ標準時
 +
Europe/Bucharest                東ヨーロッパ標準時
 +
Europe/Budapest                  中央ヨーロッパ標準時
 +
Europe/Busingen                  中央ヨーロッパ標準時
 +
Europe/Chisinau                  東ヨーロッパ標準時
 +
Europe/Copenhagen                中央ヨーロッパ標準時
 +
Europe/Dublin                    グリニッジ標準時
 +
Europe/Gibraltar                中央ヨーロッパ標準時
 +
Europe/Guernsey                  グリニッジ標準時
 +
Europe/Helsinki                  東ヨーロッパ標準時
 +
Europe/Isle_of_Man              グリニッジ標準時
 +
Europe/Istanbul                  東ヨーロッパ標準時
 +
Europe/Jersey                    グリニッジ標準時
 +
Europe/Kaliningrad              極東ヨーロッパ時間
 +
Europe/Kiev                      東ヨーロッパ標準時
 +
Europe/Lisbon                    西ヨーロッパ標準時
 +
Europe/Ljubljana                中央ヨーロッパ標準時
 +
Europe/London                    グリニッジ標準時
 +
Europe/Luxembourg                中央ヨーロッパ標準時
 +
Europe/Madrid                    中央ヨーロッパ標準時
 +
Europe/Malta                    中央ヨーロッパ標準時
 +
Europe/Mariehamn                東ヨーロッパ標準時
 +
Europe/Minsk                    極東ヨーロッパ時間
 +
Europe/Monaco                    中央ヨーロッパ標準時
 +
Europe/Moscow                    モスクワ標準時
 +
Europe/Nicosia                  東ヨーロッパ標準時
 +
Europe/Oslo                      中央ヨーロッパ標準時
 +
Europe/Paris                    中央ヨーロッパ標準時
 +
Europe/Podgorica                中央ヨーロッパ標準時
 +
Europe/Prague                    中央ヨーロッパ標準時
 +
Europe/Riga                      東ヨーロッパ標準時
 +
Europe/Rome                      中央ヨーロッパ標準時
 +
Europe/Samara                    モスクワ標準時
 +
Europe/San_Marino                中央ヨーロッパ標準時
 +
Europe/Sarajevo                  中央ヨーロッパ標準時
 +
Europe/Simferopol                モスクワ標準時
 +
Europe/Skopje                    中央ヨーロッパ標準時
 +
Europe/Sofia                    東ヨーロッパ標準時
 +
Europe/Stockholm                中央ヨーロッパ標準時
 +
Europe/Tallinn                  東ヨーロッパ標準時
 +
Europe/Tirane                    中央ヨーロッパ標準時
 +
Europe/Tiraspol                  東ヨーロッパ標準時
 +
Europe/Uzhgorod                  東ヨーロッパ標準時
 +
Europe/Vaduz                    中央ヨーロッパ標準時
 +
Europe/Vatican                  中央ヨーロッパ標準時
 +
Europe/Vienna                    中央ヨーロッパ標準時
 +
Europe/Vilnius                  東ヨーロッパ標準時
 +
Europe/Volgograd                モスクワ標準時
 +
Europe/Warsaw                    中央ヨーロッパ標準時
 +
Europe/Zagreb                    中央ヨーロッパ標準時
 +
Europe/Zaporozhye                東ヨーロッパ標準時
 +
Europe/Zurich                    中央ヨーロッパ標準時
 +
Factory                          GMT
 +
GB                              グリニッジ標準時
 +
GB-Eire                          グリニッジ標準時
 +
GMT                              GMT
 +
GMT+0                            GMT
 +
GMT-0                            GMT
 +
GMT0                            GMT
 +
Greenwich                        GMT
 +
HST                              GMT-10:00
 +
Hongkong                        香港標準時
 +
IET                              アメリカ東部標準時
 +
IST                              インド標準時
 +
Iceland                          グリニッジ標準時
 +
Indian/Antananarivo              東アフリカ時間
 +
Indian/Chagos                    インド洋時間
 +
Indian/Christmas                クリスマス島時間
 +
Indian/Cocos                    ココス諸島時間
 +
Indian/Comoro                    東アフリカ時間
 +
Indian/Kerguelen                仏領南方南極時間
 +
Indian/Mahe                      セーシェル時間
 +
Indian/Maldives                  モルディブ時間
 +
Indian/Mauritius                モーリシャス標準時
 +
Indian/Mayotte                  東アフリカ時間
 +
Indian/Reunion                  レユニオン時間
 +
Iran                            イラン標準時
 +
Israel                          イスラエル標準時
 +
JST                              日本標準時
 +
Jamaica                          アメリカ東部標準時
 +
Japan                            日本標準時
 +
Kwajalein                        マーシャル諸島時間
 +
Libya                            東ヨーロッパ標準時
 +
MET                              GMT+01:00
 +
MIT                              アピーア標準時
 +
MST                              GMT-07:00
 +
MST7MDT                          アメリカ山地標準時
 +
Mexico/BajaNorte                アメリカ太平洋標準時
 +
Mexico/BajaSur                  メキシコ太平洋標準時
 +
Mexico/General                  アメリカ中部標準時
 +
NET                              アルメニア標準時
 +
NST                              ニュージーランド標準時
 +
NZ                              ニュージーランド標準時
 +
NZ-CHAT                          チャタム標準時
 +
Navajo                          アメリカ山地標準時
 +
PLT                              パキスタン標準時
 +
PNT                              アメリカ山地標準時
 +
PRC                              中国標準時
 +
PRT                              大西洋標準時
 +
PST                              アメリカ太平洋標準時
 +
PST8PDT                          アメリカ太平洋標準時
 +
Pacific/Apia                    アピーア標準時
 +
Pacific/Auckland                ニュージーランド標準時
 +
Pacific/Chatham                  チャタム標準時
 +
Pacific/Chuuk                    チューク時間
 +
Pacific/Easter                  イースター島標準時
 +
Pacific/Efate                    バヌアツ標準時
 +
Pacific/Enderbury                フェニックス諸島時間
 +
Pacific/Fakaofo                  トケラウ時間
 +
Pacific/Fiji                    フィジー標準時
 +
Pacific/Funafuti                ツバル時間
 +
Pacific/Galapagos                ガラパゴス時間
 +
Pacific/Gambier                  ガンビエ諸島時間
 +
Pacific/Guadalcanal              ソロモン諸島時間
 +
Pacific/Guam                    チャモロ時間
 +
Pacific/Honolulu                ハワイ・アリューシャン標準時
 +
Pacific/Johnston                ハワイ・アリューシャン標準時
 +
Pacific/Kiritimati              ライン諸島時間
 +
Pacific/Kosrae                  コスラエ時間
 +
Pacific/Kwajalein                マーシャル諸島時間
 +
Pacific/Majuro                  マーシャル諸島時間
 +
Pacific/Marquesas                マルキーズ時間
 +
Pacific/Midway                  サモア標準時
 +
Pacific/Nauru                    ナウル時間
 +
Pacific/Niue                    ニウエ時間
 +
Pacific/Norfolk                  ノーフォーク島時間
 +
Pacific/Noumea                  ニューカレドニア標準時
 +
Pacific/Pago_Pago                サモア標準時
 +
Pacific/Palau                    パラオ時間
 +
Pacific/Pitcairn                ピトケアン時間
 +
Pacific/Pohnpei                  ポナペ時間
 +
Pacific/Ponape                  ポナペ時間
 +
Pacific/Port_Moresby            パプアニューギニア時間
 +
Pacific/Rarotonga                クック諸島標準時
 +
Pacific/Saipan                  チャモロ時間
 +
Pacific/Samoa                    サモア標準時
 +
Pacific/Tahiti                  タヒチ時間
 +
Pacific/Tarawa                  ギルバート諸島時間
 +
Pacific/Tongatapu                トンガ標準時
 +
Pacific/Truk                    チューク時間
 +
Pacific/Wake                    ウェーク島時間
 +
Pacific/Wallis                  ウォリス・フツナ時間
 +
Pacific/Yap                      チューク時間
 +
Poland                          中央ヨーロッパ標準時
 +
Portugal                        西ヨーロッパ標準時
 +
ROC                              台北標準時
 +
ROK                              韓国標準時
 +
SST                              ソロモン諸島時間
 +
Singapore                        シンガポール標準時
 +
SystemV/AST4                    GMT-04:00
 +
SystemV/AST4ADT                  GMT-04:00
 +
SystemV/CST6                    GMT-06:00
 +
SystemV/CST6CDT                  GMT-06:00
 +
SystemV/EST5                    GMT-05:00
 +
SystemV/EST5EDT                  GMT-05:00
 +
SystemV/HST10                    GMT-10:00
 +
SystemV/MST7                    GMT-07:00
 +
SystemV/MST7MDT                  GMT-07:00
 +
SystemV/PST8                    GMT-08:00
 +
SystemV/PST8PDT                  GMT-08:00
 +
SystemV/YST9                    GMT-09:00
 +
SystemV/YST9YDT                  GMT-09:00
 +
Turkey                          東ヨーロッパ標準時
 +
UCT                              GMT
 +
US/Alaska                        アラスカ標準時
 +
US/Aleutian                      ハワイ・アリューシャン標準時
 +
US/Arizona                      アメリカ山地標準時
 +
US/Central                      アメリカ中部標準時
 +
US/East-Indiana                  アメリカ東部標準時
 +
US/Eastern                      アメリカ東部標準時
 +
US/Hawaii                        ハワイ・アリューシャン標準時
 +
US/Indiana-Starke                アメリカ中部標準時
 +
US/Michigan                      アメリカ東部標準時
 +
US/Mountain                      アメリカ山地標準時
 +
US/Pacific                      アメリカ太平洋標準時
 +
US/Pacific-New                  アメリカ太平洋標準時
 +
US/Samoa                        サモア標準時
 +
UTC                              GMT
 +
Universal                        GMT
 +
VST                              インドシナ時間
 +
W-SU                            モスクワ標準時
 +
WET                              GMT
 +
Zulu                            GMT
 +
 
 +
</syntaxhighlight2>
 +
 
 +
各言語での日本時間の表記
 +
<syntaxhighlight2 lang="text">
 +
Asia/Tokyo af          Japan-standaardtyd
 +
Asia/Tokyo af_NA      Japan-standaardtyd
 +
Asia/Tokyo af_ZA      Japan-standaardtyd
 +
Asia/Tokyo agq        GMT+09:00
 +
Asia/Tokyo agq_CM      GMT+09:00
 +
Asia/Tokyo ak          GMT+09:00
 +
Asia/Tokyo ak_GH      GMT+09:00
 +
Asia/Tokyo am          የጃፓን መደበኛ ሰዓት
 +
Asia/Tokyo am_ET      የጃፓን መደበኛ ሰዓት
 +
Asia/Tokyo ar          توقيت اليابان الرسمي
 +
Asia/Tokyo ar_001      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_AE      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_BH      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_DJ      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_DZ      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_EG      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_EH      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_ER      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_IL      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_IQ      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_JO      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_KM      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_KW      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_LB      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_LY      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_MA      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_MR      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_OM      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_PS      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_QA      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_SA      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_SD      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_SO      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_SS      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_SY      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_TD      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_TN      توقيت اليابان الرسمي
 +
Asia/Tokyo ar_YE      توقيت اليابان الرسمي
 +
Asia/Tokyo as          GMT+০৯:০০
 +
Asia/Tokyo as_IN      GMT+০৯:০০
 +
Asia/Tokyo asa        GMT+09:00
 +
Asia/Tokyo asa_TZ      GMT+09:00
 +
Asia/Tokyo az          Yaponiya Standart Vaxtı
 +
Asia/Tokyo az_Cyrl    GMT+09:00
 +
Asia/Tokyo az_Cyrl_AZ  GMT+09:00
 +
Asia/Tokyo az_Latn    Yaponiya Standart Vaxtı
 +
Asia/Tokyo az_Latn_AZ  Yaponiya Standart Vaxtı
 +
Asia/Tokyo bas        GMT+09:00
 +
Asia/Tokyo bas_CM      GMT+09:00
 +
Asia/Tokyo be          GMT+09:00
 +
Asia/Tokyo be_BY      GMT+09:00
 +
Asia/Tokyo bem        GMT+09:00
 +
Asia/Tokyo bem_ZM      GMT+09:00
 +
Asia/Tokyo bez        GMT+09:00
 +
Asia/Tokyo bez_TZ      GMT+09:00
 +
Asia/Tokyo bg          Японско стандартно време
 +
Asia/Tokyo bg_BG      Японско стандартно време
 +
Asia/Tokyo bm          GMT+09:00
 +
Asia/Tokyo bm_Latn    GMT+09:00
 +
Asia/Tokyo bm_Latn_ML  GMT+09:00
 +
Asia/Tokyo bn          জাপান মানক সময়
 +
Asia/Tokyo bn_BD      জাপান মানক সময়
 +
Asia/Tokyo bn_IN      জাপান মানক সময়
 +
Asia/Tokyo bo          GMT+09:00
 +
Asia/Tokyo bo_CN      GMT+09:00
 +
Asia/Tokyo bo_IN      GMT+09:00
 +
Asia/Tokyo br          GMT+09:00
 +
Asia/Tokyo br_FR      GMT+09:00
 +
Asia/Tokyo brx        जपान स्टैंडर्ड टाईम
 +
Asia/Tokyo brx_IN      जपान स्टैंडर्ड टाईम
 +
Asia/Tokyo bs          Standardno japansko vrijeme
 +
Asia/Tokyo bs_Cyrl    Јапанско стандардно време
 +
Asia/Tokyo bs_Cyrl_BA  Јапанско стандардно време
 +
Asia/Tokyo bs_Latn    Standardno japansko vrijeme
 +
Asia/Tokyo bs_Latn_BA  Standardno japansko vrijeme
 +
Asia/Tokyo ca          Hora estàndard del Japó
 +
Asia/Tokyo ca_AD      Hora estàndard del Japó
 +
Asia/Tokyo ca_ES      Hora estàndard del Japó
 +
Asia/Tokyo ca_FR      Hora estàndard del Japó
 +
Asia/Tokyo ca_IT      Hora estàndard del Japó
 +
Asia/Tokyo cgg        GMT+09:00
 +
Asia/Tokyo cgg_UG      GMT+09:00
 +
Asia/Tokyo chr        GMT+09:00
 +
Asia/Tokyo chr_US      GMT+09:00
 +
Asia/Tokyo cs          Japonský standardní čas
 +
Asia/Tokyo cs_CZ      Japonský standardní čas
 +
Asia/Tokyo cy          Amser Safonol Japan
 +
Asia/Tokyo cy_GB      Amser Safonol Japan
 +
Asia/Tokyo da          Japansk normaltid
 +
Asia/Tokyo da_DK      Japansk normaltid
 +
Asia/Tokyo da_GL      Japansk normaltid
 +
Asia/Tokyo dav        GMT+09:00
 +
Asia/Tokyo dav_KE      GMT+09:00
 +
Asia/Tokyo de          Japanische Normalzeit
 +
Asia/Tokyo de_AT      Japanische Normalzeit
 +
Asia/Tokyo de_BE      Japanische Normalzeit
 +
Asia/Tokyo de_CH      Japanische Normalzeit
 +
Asia/Tokyo de_DE      Japanische Normalzeit
 +
Asia/Tokyo de_LI      Japanische Normalzeit
 +
Asia/Tokyo de_LU      Japanische Normalzeit
 +
Asia/Tokyo dje        GMT+09:00
 +
Asia/Tokyo dje_NE      GMT+09:00
 +
Asia/Tokyo dsb        Japański standardny cas
 +
Asia/Tokyo dsb_DE      Japański standardny cas
 +
Asia/Tokyo dua        GMT+09:00
 +
Asia/Tokyo dua_CM      GMT+09:00
 +
Asia/Tokyo dyo        GMT+09:00
 +
Asia/Tokyo dyo_SN      GMT+09:00
 +
Asia/Tokyo dz          ཇ་པཱན་ཚད་ལྡན་ཆུ་ཚོད
 +
Asia/Tokyo dz_BT      ཇ་པཱན་ཚད་ལྡན་ཆུ་ཚོད
 +
Asia/Tokyo ebu        GMT+09:00
 +
Asia/Tokyo ebu_KE      GMT+09:00
 +
Asia/Tokyo ee          GMT+09:00
 +
Asia/Tokyo ee_GH      GMT+09:00
 +
Asia/Tokyo ee_TG      GMT+09:00
 +
Asia/Tokyo el          Χειμερινή ώρα Ιαπωνίας
 +
Asia/Tokyo el_CY      Χειμερινή ώρα Ιαπωνίας
 +
Asia/Tokyo el_GR      Χειμερινή ώρα Ιαπωνίας
 +
Asia/Tokyo en          Japan Standard Time
 +
Asia/Tokyo en_001      Japan Standard Time
 +
Asia/Tokyo en_150      Japan Standard Time
 +
Asia/Tokyo en_AG      Japan Standard Time
 +
Asia/Tokyo en_AI      Japan Standard Time
 +
Asia/Tokyo en_AS      Japan Standard Time
 +
Asia/Tokyo en_AU      Japan Standard Time
 +
Asia/Tokyo en_BB      Japan Standard Time
 +
Asia/Tokyo en_BE      Japan Standard Time
 +
Asia/Tokyo en_BM      Japan Standard Time
 +
Asia/Tokyo en_BS      Japan Standard Time
 +
Asia/Tokyo en_BW      Japan Standard Time
 +
Asia/Tokyo en_BZ      Japan Standard Time
 +
Asia/Tokyo en_CA      Japan Standard Time
 +
Asia/Tokyo en_CC      Japan Standard Time
 +
Asia/Tokyo en_CK      Japan Standard Time
 +
Asia/Tokyo en_CM      Japan Standard Time
 +
Asia/Tokyo en_CX      Japan Standard Time
 +
Asia/Tokyo en_DG      Japan Standard Time
 +
Asia/Tokyo en_DM      Japan Standard Time
 +
Asia/Tokyo en_ER      Japan Standard Time
 +
Asia/Tokyo en_FJ      Japan Standard Time
 +
Asia/Tokyo en_FK      Japan Standard Time
 +
Asia/Tokyo en_FM      Japan Standard Time
 +
Asia/Tokyo en_GB      Japan Standard Time
 +
Asia/Tokyo en_GD      Japan Standard Time
 +
Asia/Tokyo en_GG      Japan Standard Time
 +
Asia/Tokyo en_GH      Japan Standard Time
 +
Asia/Tokyo en_GI      Japan Standard Time
 +
Asia/Tokyo en_GM      Japan Standard Time
 +
Asia/Tokyo en_GU      Japan Standard Time
 +
Asia/Tokyo en_GY      Japan Standard Time
 +
Asia/Tokyo en_HK      Japan Standard Time
 +
Asia/Tokyo en_IE      Japan Standard Time
 +
Asia/Tokyo en_IM      Japan Standard Time
 +
Asia/Tokyo en_IN      Japan Standard Time
 +
Asia/Tokyo en_IO      Japan Standard Time
 +
Asia/Tokyo en_JE      Japan Standard Time
 +
Asia/Tokyo en_JM      Japan Standard Time
 +
Asia/Tokyo en_KE      Japan Standard Time
 +
Asia/Tokyo en_KI      Japan Standard Time
 +
Asia/Tokyo en_KN      Japan Standard Time
 +
Asia/Tokyo en_KY      Japan Standard Time
 +
Asia/Tokyo en_LC      Japan Standard Time
 +
Asia/Tokyo en_LR      Japan Standard Time
 +
Asia/Tokyo en_LS      Japan Standard Time
 +
Asia/Tokyo en_MG      Japan Standard Time
 +
Asia/Tokyo en_MH      Japan Standard Time
 +
Asia/Tokyo en_MO      Japan Standard Time
 +
Asia/Tokyo en_MP      Japan Standard Time
 +
Asia/Tokyo en_MS      Japan Standard Time
 +
Asia/Tokyo en_MT      Japan Standard Time
 +
Asia/Tokyo en_MU      Japan Standard Time
 +
Asia/Tokyo en_MW      Japan Standard Time
 +
Asia/Tokyo en_MY      Japan Standard Time
 +
Asia/Tokyo en_NA      Japan Standard Time
 +
Asia/Tokyo en_NF      Japan Standard Time
 +
Asia/Tokyo en_NG      Japan Standard Time
 +
Asia/Tokyo en_NR      Japan Standard Time
 +
Asia/Tokyo en_NU      Japan Standard Time
 +
Asia/Tokyo en_NZ      Japan Standard Time
 +
Asia/Tokyo en_PG      Japan Standard Time
 +
Asia/Tokyo en_PH      Japan Standard Time
 +
Asia/Tokyo en_PK      Japan Standard Time
 +
Asia/Tokyo en_PN      Japan Standard Time
 +
Asia/Tokyo en_PR      Japan Standard Time
 +
Asia/Tokyo en_PW      Japan Standard Time
 +
Asia/Tokyo en_RW      Japan Standard Time
 +
Asia/Tokyo en_SB      Japan Standard Time
 +
Asia/Tokyo en_SC      Japan Standard Time
 +
Asia/Tokyo en_SD      Japan Standard Time
 +
Asia/Tokyo en_SG      Japan Standard Time
 +
Asia/Tokyo en_SH      Japan Standard Time
 +
Asia/Tokyo en_SL      Japan Standard Time
 +
Asia/Tokyo en_SS      Japan Standard Time
 +
Asia/Tokyo en_SX      Japan Standard Time
 +
Asia/Tokyo en_SZ      Japan Standard Time
 +
Asia/Tokyo en_TC      Japan Standard Time
 +
Asia/Tokyo en_TK      Japan Standard Time
 +
Asia/Tokyo en_TO      Japan Standard Time
 +
Asia/Tokyo en_TT      Japan Standard Time
 +
Asia/Tokyo en_TV      Japan Standard Time
 +
Asia/Tokyo en_TZ      Japan Standard Time
 +
Asia/Tokyo en_UG      Japan Standard Time
 +
Asia/Tokyo en_UM      Japan Standard Time
 +
Asia/Tokyo en_US      Japan Standard Time
 +
Asia/Tokyo en_US_POSIX Japan Standard Time
 +
Asia/Tokyo en_VC      Japan Standard Time
 +
Asia/Tokyo en_VG      Japan Standard Time
 +
Asia/Tokyo en_VI      Japan Standard Time
 +
Asia/Tokyo en_VU      Japan Standard Time
 +
Asia/Tokyo en_WS      Japan Standard Time
 +
Asia/Tokyo en_ZA      Japan Standard Time
 +
Asia/Tokyo en_ZM      Japan Standard Time
 +
Asia/Tokyo en_ZW      Japan Standard Time
 +
Asia/Tokyo eo          GMT+09:00
 +
Asia/Tokyo es          hora estándar de Japón
 +
Asia/Tokyo es_419      hora estándar de Japón
 +
Asia/Tokyo es_AR      hora estándar de Japón
 +
Asia/Tokyo es_BO      hora estándar de Japón
 +
Asia/Tokyo es_CL      hora estándar de Japón
 +
Asia/Tokyo es_CO      hora estándar de Japón
 +
Asia/Tokyo es_CR      hora estándar de Japón
 +
Asia/Tokyo es_CU      hora estándar de Japón
 +
Asia/Tokyo es_DO      hora estándar de Japón
 +
Asia/Tokyo es_EA      hora estándar de Japón
 +
Asia/Tokyo es_EC      hora estándar de Japón
 +
Asia/Tokyo es_ES      hora estándar de Japón
 +
Asia/Tokyo es_GQ      hora estándar de Japón
 +
Asia/Tokyo es_GT      hora estándar de Japón
 +
Asia/Tokyo es_HN      hora estándar de Japón
 +
Asia/Tokyo es_IC      hora estándar de Japón
 +
Asia/Tokyo es_MX      Hora estándar de Japón
 +
Asia/Tokyo es_NI      hora estándar de Japón
 +
Asia/Tokyo es_PA      hora estándar de Japón
 +
Asia/Tokyo es_PE      hora estándar de Japón
 +
Asia/Tokyo es_PH      hora estándar de Japón
 +
Asia/Tokyo es_PR      hora estándar de Japón
 +
Asia/Tokyo es_PY      hora estándar de Japón
 +
Asia/Tokyo es_SV      hora estándar de Japón
 +
Asia/Tokyo es_US      hora estándar de Japón
 +
Asia/Tokyo es_UY      hora estándar de Japón
 +
Asia/Tokyo es_VE      hora estándar de Japón
 +
Asia/Tokyo et          Jaapani standardaeg
 +
Asia/Tokyo et_EE      Jaapani standardaeg
 +
Asia/Tokyo eu          Japoniako ordu estandarra
 +
Asia/Tokyo eu_ES      Japoniako ordu estandarra
 +
Asia/Tokyo ewo        GMT+09:00
 +
Asia/Tokyo ewo_CM      GMT+09:00
 +
Asia/Tokyo fa          وقت عادی ژاپن
 +
Asia/Tokyo fa_AF      وقت عادی ژاپن
 +
Asia/Tokyo fa_IR      وقت عادی ژاپن
 +
Asia/Tokyo ff          GMT+09:00
 +
Asia/Tokyo ff_CM      GMT+09:00
 +
Asia/Tokyo ff_GN      GMT+09:00
 +
Asia/Tokyo ff_MR      GMT+09:00
 +
Asia/Tokyo ff_SN      GMT+09:00
 +
Asia/Tokyo fi          Japanin normaaliaika
 +
Asia/Tokyo fi_FI      Japanin normaaliaika
 +
Asia/Tokyo fil        Standard Time ng Japan
 +
Asia/Tokyo fil_PH      Standard Time ng Japan
 +
Asia/Tokyo fo          GMT+09:00
 +
Asia/Tokyo fo_FO      GMT+09:00
 +
Asia/Tokyo fr          heure normale du Japon
 +
Asia/Tokyo fr_BE      heure normale du Japon
 +
Asia/Tokyo fr_BF      heure normale du Japon
 +
Asia/Tokyo fr_BI      heure normale du Japon
 +
Asia/Tokyo fr_BJ      heure normale du Japon
 +
Asia/Tokyo fr_BL      heure normale du Japon
 +
Asia/Tokyo fr_CA      heure normale du Japon
 +
Asia/Tokyo fr_CD      heure normale du Japon
 +
Asia/Tokyo fr_CF      heure normale du Japon
 +
Asia/Tokyo fr_CG      heure normale du Japon
 +
Asia/Tokyo fr_CH      heure normale du Japon
 +
Asia/Tokyo fr_CI      heure normale du Japon
 +
Asia/Tokyo fr_CM      heure normale du Japon
 +
Asia/Tokyo fr_DJ      heure normale du Japon
 +
Asia/Tokyo fr_DZ      heure normale du Japon
 +
Asia/Tokyo fr_FR      heure normale du Japon
 +
Asia/Tokyo fr_GA      heure normale du Japon
 +
Asia/Tokyo fr_GF      heure normale du Japon
 +
Asia/Tokyo fr_GN      heure normale du Japon
 +
Asia/Tokyo fr_GP      heure normale du Japon
 +
Asia/Tokyo fr_GQ      heure normale du Japon
 +
Asia/Tokyo fr_HT      heure normale du Japon
 +
Asia/Tokyo fr_KM      heure normale du Japon
 +
Asia/Tokyo fr_LU      heure normale du Japon
 +
Asia/Tokyo fr_MA      heure normale du Japon
 +
Asia/Tokyo fr_MC      heure normale du Japon
 +
Asia/Tokyo fr_MF      heure normale du Japon
 +
Asia/Tokyo fr_MG      heure normale du Japon
 +
Asia/Tokyo fr_ML      heure normale du Japon
 +
Asia/Tokyo fr_MQ      heure normale du Japon
 +
Asia/Tokyo fr_MR      heure normale du Japon
 +
Asia/Tokyo fr_MU      heure normale du Japon
 +
Asia/Tokyo fr_NC      heure normale du Japon
 +
Asia/Tokyo fr_NE      heure normale du Japon
 +
Asia/Tokyo fr_PF      heure normale du Japon
 +
Asia/Tokyo fr_PM      heure normale du Japon
 +
Asia/Tokyo fr_RE      heure normale du Japon
 +
Asia/Tokyo fr_RW      heure normale du Japon
 +
Asia/Tokyo fr_SC      heure normale du Japon
 +
Asia/Tokyo fr_SN      heure normale du Japon
 +
Asia/Tokyo fr_SY      heure normale du Japon
 +
Asia/Tokyo fr_TD      heure normale du Japon
 +
Asia/Tokyo fr_TG      heure normale du Japon
 +
Asia/Tokyo fr_TN      heure normale du Japon
 +
Asia/Tokyo fr_VU      heure normale du Japon
 +
Asia/Tokyo fr_WF      heure normale du Japon
 +
Asia/Tokyo fr_YT      heure normale du Japon
 +
Asia/Tokyo fur        GMT+09:00
 +
Asia/Tokyo fur_IT      GMT+09:00
 +
Asia/Tokyo fy          Japanske standerttiid
 +
Asia/Tokyo fy_NL      Japanske standerttiid
 +
Asia/Tokyo ga          Am Caighdeánach na Seapáine
 +
Asia/Tokyo ga_IE      Am Caighdeánach na Seapáine
 +
Asia/Tokyo gd          Bun-àm na Seapaine
 +
Asia/Tokyo gd_GB      Bun-àm na Seapaine
 +
Asia/Tokyo gl          Horario estándar de Xapón
 +
Asia/Tokyo gl_ES      Horario estándar de Xapón
 +
Asia/Tokyo gsw        GMT+09:00
 +
Asia/Tokyo gsw_CH      GMT+09:00
 +
Asia/Tokyo gsw_FR      GMT+09:00
 +
Asia/Tokyo gsw_LI      GMT+09:00
 +
Asia/Tokyo gu          જાપાન માનક સમય
 +
Asia/Tokyo gu_IN      જાપાન માનક સમય
 +
Asia/Tokyo guz        GMT+09:00
 +
Asia/Tokyo guz_KE      GMT+09:00
 +
Asia/Tokyo gv          GMT+09:00
 +
Asia/Tokyo gv_IM      GMT+09:00
 +
Asia/Tokyo ha          GMT+09:00
 +
Asia/Tokyo ha_Latn    GMT+09:00
 +
Asia/Tokyo ha_Latn_GH  GMT+09:00
 +
Asia/Tokyo ha_Latn_NE  GMT+09:00
 +
Asia/Tokyo ha_Latn_NG  GMT+09:00
 +
Asia/Tokyo haw        GMT+09:00
 +
Asia/Tokyo haw_US      GMT+09:00
 +
Asia/Tokyo he          שעון יפן (חורף)
 +
Asia/Tokyo he_IL      שעון יפן (חורף)
 +
Asia/Tokyo hi          जापान मानक समय
 +
Asia/Tokyo hi_IN      जापान मानक समय
 +
Asia/Tokyo hr          japansko standardno vrijeme
 +
Asia/Tokyo hr_BA      japansko standardno vrijeme
 +
Asia/Tokyo hr_HR      japansko standardno vrijeme
 +
Asia/Tokyo hsb        japanski standardny čas
 +
Asia/Tokyo hsb_DE      japanski standardny čas
 +
Asia/Tokyo hu          japán téli idő
 +
Asia/Tokyo hu_HU      japán téli idő
 +
Asia/Tokyo hy          Ճապոնիայի ստանդարտ ժամանակ
 +
Asia/Tokyo hy_AM      Ճապոնիայի ստանդարտ ժամանակ
 +
Asia/Tokyo id          Waktu Standar Jepang
 +
Asia/Tokyo id_ID      Waktu Standar Jepang
 +
Asia/Tokyo ig          GMT+09:00
 +
Asia/Tokyo ig_NG      GMT+09:00
 +
Asia/Tokyo ii          GMT+09:00
 +
Asia/Tokyo ii_CN      GMT+09:00
 +
Asia/Tokyo is          Staðaltími í Japan
 +
Asia/Tokyo is_IS      Staðaltími í Japan
 +
Asia/Tokyo it          Ora standard del Giappone
 +
Asia/Tokyo it_CH      Ora standard del Giappone
 +
Asia/Tokyo it_IT      Ora standard del Giappone
 +
Asia/Tokyo it_SM      Ora standard del Giappone
 +
Asia/Tokyo ja          日本標準時
 +
Asia/Tokyo ja_JP      日本標準時
 +
Asia/Tokyo jgo        GMT+09:00
 +
Asia/Tokyo jgo_CM      GMT+09:00
 +
Asia/Tokyo jmc        GMT+09:00
 +
Asia/Tokyo jmc_TZ      GMT+09:00
 +
Asia/Tokyo ka          იაპონიის სტანდარტული დრო
 +
Asia/Tokyo ka_GE      იაპონიის სტანდარტული დრო
 +
Asia/Tokyo kab        GMT+09:00
 +
Asia/Tokyo kab_DZ      GMT+09:00
 +
Asia/Tokyo kam        GMT+09:00
 +
Asia/Tokyo kam_KE      GMT+09:00
 +
Asia/Tokyo kde        GMT+09:00
 +
Asia/Tokyo kde_TZ      GMT+09:00
 +
Asia/Tokyo kea        GMT+09:00
 +
Asia/Tokyo kea_CV      GMT+09:00
 +
Asia/Tokyo khq        GMT+09:00
 +
Asia/Tokyo khq_ML      GMT+09:00
 +
Asia/Tokyo ki          GMT+09:00
 +
Asia/Tokyo ki_KE      GMT+09:00
 +
Asia/Tokyo kk          Жапония стандартты уақыты
 +
Asia/Tokyo kk_Cyrl    Жапония стандартты уақыты
 +
Asia/Tokyo kk_Cyrl_KZ  Жапония стандартты уақыты
 +
Asia/Tokyo kkj        GMT+09:00
 +
Asia/Tokyo kkj_CM      GMT+09:00
 +
Asia/Tokyo kl          GMT+09:00
 +
Asia/Tokyo kl_GL      GMT+09:00
 +
Asia/Tokyo kln        GMT+09:00
 +
Asia/Tokyo kln_KE      GMT+09:00
 +
Asia/Tokyo km          ម៉ោង​ស្តង់ដារ​នៅ​ជប៉ុន
 +
Asia/Tokyo km_KH      ម៉ោង​ស្តង់ដារ​នៅ​ជប៉ុន
 +
Asia/Tokyo kn          ಜಪಾನ್ ಪ್ರಮಾಣಿತ ಸಮಯ
 +
Asia/Tokyo kn_IN      ಜಪಾನ್ ಪ್ರಮಾಣಿತ ಸಮಯ
 +
Asia/Tokyo ko          일본 표준시
 +
Asia/Tokyo ko_KP      일본 표준시
 +
Asia/Tokyo ko_KR      일본 표준시
 +
Asia/Tokyo kok        GMT+09:00
 +
Asia/Tokyo kok_IN      GMT+09:00
 +
Asia/Tokyo ks          جاپٲنۍ سٹینڑاڑ ٹایِم
 +
Asia/Tokyo ks_Arab    جاپٲنۍ سٹینڑاڑ ٹایِم
 +
Asia/Tokyo ks_Arab_IN  جاپٲنۍ سٹینڑاڑ ٹایِم
 +
Asia/Tokyo ksb        GMT+09:00
 +
Asia/Tokyo ksb_TZ      GMT+09:00
 +
Asia/Tokyo ksf        GMT+09:00
 +
Asia/Tokyo ksf_CM      GMT+09:00
 +
Asia/Tokyo ksh        GMT+09:00
 +
Asia/Tokyo ksh_DE      GMT+09:00
 +
Asia/Tokyo kw          GMT+09:00
 +
Asia/Tokyo kw_GB      GMT+09:00
 +
Asia/Tokyo ky          Жапан стандарт убактысы
 +
Asia/Tokyo ky_Cyrl    Жапан стандарт убактысы
 +
Asia/Tokyo ky_Cyrl_KG  Жапан стандарт убактысы
 +
Asia/Tokyo lag        GMT+09:00
 +
Asia/Tokyo lag_TZ      GMT+09:00
 +
Asia/Tokyo lb          Japanesch Normalzäit
 +
Asia/Tokyo lb_LU      Japanesch Normalzäit
 +
Asia/Tokyo lg          GMT+09:00
 +
Asia/Tokyo lg_UG      GMT+09:00
 +
Asia/Tokyo lkt        GMT+09:00
 +
Asia/Tokyo lkt_US      GMT+09:00
 +
Asia/Tokyo ln          GMT+09:00
 +
Asia/Tokyo ln_AO      GMT+09:00
 +
Asia/Tokyo ln_CD      GMT+09:00
 +
Asia/Tokyo ln_CF      GMT+09:00
 +
Asia/Tokyo ln_CG      GMT+09:00
 +
Asia/Tokyo lo          ເວ​ລາ​ມາດ​ຕະ​ຖານ​ຍີ່​ປຸ່ນ
 +
Asia/Tokyo lo_LA      ເວ​ລາ​ມາດ​ຕະ​ຖານ​ຍີ່​ປຸ່ນ
 +
Asia/Tokyo lt          Japonijos žiemos laikas
 +
Asia/Tokyo lt_LT      Japonijos žiemos laikas
 +
Asia/Tokyo lu          GMT+09:00
 +
Asia/Tokyo lu_CD      GMT+09:00
 +
Asia/Tokyo luo        GMT+09:00
 +
Asia/Tokyo luo_KE      GMT+09:00
 +
Asia/Tokyo luy        GMT+09:00
 +
Asia/Tokyo luy_KE      GMT+09:00
 +
Asia/Tokyo lv          Japānas ziemas laiks
 +
Asia/Tokyo lv_LV      Japānas ziemas laiks
 +
Asia/Tokyo mas        GMT+09:00
 +
Asia/Tokyo mas_KE      GMT+09:00
 +
Asia/Tokyo mas_TZ      GMT+09:00
 +
Asia/Tokyo mer        GMT+09:00
 +
Asia/Tokyo mer_KE      GMT+09:00
 +
Asia/Tokyo mfe        GMT+09:00
 +
Asia/Tokyo mfe_MU      GMT+09:00
 +
Asia/Tokyo mg          GMT+09:00
 +
Asia/Tokyo mg_MG      GMT+09:00
 +
Asia/Tokyo mgh        GMT+09:00
 +
Asia/Tokyo mgh_MZ      GMT+09:00
 +
Asia/Tokyo mgo        GMT+09:00
 +
Asia/Tokyo mgo_CM      GMT+09:00
 +
Asia/Tokyo mk          Стандардно време во Јапонија
 +
Asia/Tokyo mk_MK      Стандардно време во Јапонија
 +
Asia/Tokyo ml          ജപ്പാൻ സ്റ്റാൻഡേർഡ് സമയം
 +
Asia/Tokyo ml_IN      ജപ്പാൻ സ്റ്റാൻഡേർഡ് സമയം
 +
Asia/Tokyo mn          Японы стандарт цаг
 +
Asia/Tokyo mn_Cyrl    Японы стандарт цаг
 +
Asia/Tokyo mn_Cyrl_MN  Японы стандарт цаг
 +
Asia/Tokyo mr          जपान प्रमाण वेळ
 +
Asia/Tokyo mr_IN      जपान प्रमाण वेळ
 +
Asia/Tokyo ms          Waktu Piawai Jepun
 +
Asia/Tokyo ms_Latn    Waktu Piawai Jepun
 +
Asia/Tokyo ms_Latn_BN  Waktu Piawai Jepun
 +
Asia/Tokyo ms_Latn_MY  Waktu Piawai Jepun
 +
Asia/Tokyo ms_Latn_SG  Waktu Piawai Jepun
 +
Asia/Tokyo mt          GMT+09:00
 +
Asia/Tokyo mt_MT      GMT+09:00
 +
Asia/Tokyo mua        GMT+09:00
 +
Asia/Tokyo mua_CM      GMT+09:00
 +
Asia/Tokyo my          ဂျပန် စံတော်ချိန်
 +
Asia/Tokyo my_MM      ဂျပန် စံတော်ချိန်
 +
Asia/Tokyo naq        GMT+09:00
 +
Asia/Tokyo naq_NA      GMT+09:00
 +
Asia/Tokyo nb          japansk normaltid
 +
Asia/Tokyo nb_NO      japansk normaltid
 +
Asia/Tokyo nb_SJ      japansk normaltid
 +
Asia/Tokyo nd          GMT+09:00
 +
Asia/Tokyo nd_ZW      GMT+09:00
 +
Asia/Tokyo ne          जापान मानक समय
 +
Asia/Tokyo ne_IN      जापान मानक समय
 +
Asia/Tokyo ne_NP      जापान मानक समय
 +
Asia/Tokyo nl          Japanse standaardtijd
 +
Asia/Tokyo nl_AW      Japanse standaardtijd
 +
Asia/Tokyo nl_BE      Japanse standaardtijd
 +
Asia/Tokyo nl_BQ      Japanse standaardtijd
 +
Asia/Tokyo nl_CW      Japanse standaardtijd
 +
Asia/Tokyo nl_NL      Japanse standaardtijd
 +
Asia/Tokyo nl_SR      Japanse standaardtijd
 +
Asia/Tokyo nl_SX      Japanse standaardtijd
 +
Asia/Tokyo nmg        GMT+09:00
 +
Asia/Tokyo nmg_CM      GMT+09:00
 +
Asia/Tokyo nn          GMT+09:00
 +
Asia/Tokyo nn_NO      GMT+09:00
 +
Asia/Tokyo nnh        GMT+09:00
 +
Asia/Tokyo nnh_CM      GMT+09:00
 +
Asia/Tokyo nus        GMT+09:00
 +
Asia/Tokyo nus_SD      GMT+09:00
 +
Asia/Tokyo nyn        GMT+09:00
 +
Asia/Tokyo nyn_UG      GMT+09:00
 +
Asia/Tokyo om          GMT+09:00
 +
Asia/Tokyo om_ET      GMT+09:00
 +
Asia/Tokyo om_KE      GMT+09:00
 +
Asia/Tokyo or          GMT+09:00
 +
Asia/Tokyo or_IN      GMT+09:00
 +
Asia/Tokyo os          GMT+09:00
 +
Asia/Tokyo os_GE      GMT+09:00
 +
Asia/Tokyo os_RU      GMT+09:00
 +
Asia/Tokyo pa          ਜਪਾਨ ਮਿਆਰੀ ਸਮਾਂ
 +
Asia/Tokyo pa_Arab    GMT+۰۹:۰۰
 +
Asia/Tokyo pa_Arab_PK  GMT+۰۹:۰۰
 +
Asia/Tokyo pa_Guru    ਜਪਾਨ ਮਿਆਰੀ ਸਮਾਂ
 +
Asia/Tokyo pa_Guru_IN  ਜਪਾਨ ਮਿਆਰੀ ਸਮਾਂ
 +
Asia/Tokyo pl          Japonia (czas standardowy)
 +
Asia/Tokyo pl_PL      Japonia (czas standardowy)
 +
Asia/Tokyo ps          GMT+۰۹:۰۰
 +
Asia/Tokyo ps_AF      GMT+۰۹:۰۰
 +
Asia/Tokyo pt          Horário Padrão do Japão
 +
Asia/Tokyo pt_AO      Hora Padrão do Japão
 +
Asia/Tokyo pt_BR      Horário Padrão do Japão
 +
Asia/Tokyo pt_CV      Hora Padrão do Japão
 +
Asia/Tokyo pt_GW      Hora Padrão do Japão
 +
Asia/Tokyo pt_MO      Hora Padrão do Japão
 +
Asia/Tokyo pt_MZ      Hora Padrão do Japão
 +
Asia/Tokyo pt_PT      Hora Padrão do Japão
 +
Asia/Tokyo pt_ST      Hora Padrão do Japão
 +
Asia/Tokyo pt_TL      Hora Padrão do Japão
 +
Asia/Tokyo qu          GMT+09:00
 +
Asia/Tokyo qu_BO      GMT+09:00
 +
Asia/Tokyo qu_EC      GMT+09:00
 +
Asia/Tokyo qu_PE      GMT+09:00
 +
Asia/Tokyo rm          GMT+09:00
 +
Asia/Tokyo rm_CH      GMT+09:00
 +
Asia/Tokyo rn          GMT+09:00
 +
Asia/Tokyo rn_BI      GMT+09:00
 +
Asia/Tokyo ro          Ora standard a Japoniei
 +
Asia/Tokyo ro_MD      Ora standard a Japoniei
 +
Asia/Tokyo ro_RO      Ora standard a Japoniei
 +
Asia/Tokyo rof        GMT+09:00
 +
Asia/Tokyo rof_TZ      GMT+09:00
 +
Asia/Tokyo ru          Япония, стандартное время
 +
Asia/Tokyo ru_BY      Япония, стандартное время
 +
Asia/Tokyo ru_KG      Япония, стандартное время
 +
Asia/Tokyo ru_KZ      Япония, стандартное время
 +
Asia/Tokyo ru_MD      Япония, стандартное время
 +
Asia/Tokyo ru_RU      Япония, стандартное время
 +
Asia/Tokyo ru_UA      Япония, стандартное время
 +
Asia/Tokyo rw          GMT+09:00
 +
Asia/Tokyo rw_RW      GMT+09:00
 +
Asia/Tokyo rwk        GMT+09:00
 +
Asia/Tokyo rwk_TZ      GMT+09:00
 +
Asia/Tokyo sah        GMT+09:00
 +
Asia/Tokyo sah_RU      GMT+09:00
 +
Asia/Tokyo saq        GMT+09:00
 +
Asia/Tokyo saq_KE      GMT+09:00
 +
Asia/Tokyo sbp        GMT+09:00
 +
Asia/Tokyo sbp_TZ      GMT+09:00
 +
Asia/Tokyo se          UTC+09:00
 +
Asia/Tokyo se_FI      UTC+09:00
 +
Asia/Tokyo se_NO      UTC+09:00
 +
Asia/Tokyo se_SE      UTC+09:00
 +
Asia/Tokyo seh        GMT+09:00
 +
Asia/Tokyo seh_MZ      GMT+09:00
 +
Asia/Tokyo ses        GMT+09:00
 +
Asia/Tokyo ses_ML      GMT+09:00
 +
Asia/Tokyo sg          GMT+09:00
 +
Asia/Tokyo sg_CF      GMT+09:00
 +
Asia/Tokyo shi        GMT+09:00
 +
Asia/Tokyo shi_Latn    GMT+09:00
 +
Asia/Tokyo shi_Latn_MA GMT+09:00
 +
Asia/Tokyo shi_Tfng    GMT+09:00
 +
Asia/Tokyo shi_Tfng_MA GMT+09:00
 +
Asia/Tokyo si          ජපාන සම්මත වේලාව
 +
Asia/Tokyo si_LK      ජපාන සම්මත වේලාව
 +
Asia/Tokyo sk          Japonský štandardný čas
 +
Asia/Tokyo sk_SK      Japonský štandardný čas
 +
Asia/Tokyo sl          Japonski standardni čas
 +
Asia/Tokyo sl_SI      Japonski standardni čas
 +
Asia/Tokyo smn        GMT+09:00
 +
Asia/Tokyo smn_FI      GMT+09:00
 +
Asia/Tokyo sn          GMT+09:00
 +
Asia/Tokyo sn_ZW      GMT+09:00
 +
Asia/Tokyo so          GMT+09:00
 +
Asia/Tokyo so_DJ      GMT+09:00
 +
Asia/Tokyo so_ET      GMT+09:00
 +
Asia/Tokyo so_KE      GMT+09:00
 +
Asia/Tokyo so_SO      GMT+09:00
 +
Asia/Tokyo sq          Ora standarde e Japonisë
 +
Asia/Tokyo sq_AL      Ora standarde e Japonisë
 +
Asia/Tokyo sq_MK      Ora standarde e Japonisë
 +
Asia/Tokyo sq_XK      Ora standarde e Japonisë
 +
Asia/Tokyo sr          Јапанско стандардно време
 +
Asia/Tokyo sr_Cyrl    Јапанско стандардно време
 +
Asia/Tokyo sr_Cyrl_BA  Јапанско стандардно време
 +
Asia/Tokyo sr_Cyrl_ME  Јапанско стандардно време
 +
Asia/Tokyo sr_Cyrl_RS  Јапанско стандардно време
 +
Asia/Tokyo sr_Cyrl_XK  Јапанско стандардно време
 +
Asia/Tokyo sr_Latn    Japansko standardno vreme
 +
Asia/Tokyo sr_Latn_BA  Japansko standardno vreme
 +
Asia/Tokyo sr_Latn_ME  Japansko standardno vreme
 +
Asia/Tokyo sr_Latn_RS  Japansko standardno vreme
 +
Asia/Tokyo sr_Latn_XK  Japansko standardno vreme
 +
Asia/Tokyo sv          japansk normaltid
 +
Asia/Tokyo sv_AX      japansk normaltid
 +
Asia/Tokyo sv_FI      japansk normaltid
 +
Asia/Tokyo sv_SE      japansk normaltid
 +
Asia/Tokyo sw          Saa Wastani za Japani
 +
Asia/Tokyo sw_KE      Saa Wastani za Japani
 +
Asia/Tokyo sw_TZ      Saa Wastani za Japani
 +
Asia/Tokyo sw_UG      Saa Wastani za Japani
 +
Asia/Tokyo swc        GMT+09:00
 +
Asia/Tokyo swc_CD      GMT+09:00
 +
Asia/Tokyo ta          ஜப்பான் நிலையான நேரம்
 +
Asia/Tokyo ta_IN      ஜப்பான் நிலையான நேரம்
 +
Asia/Tokyo ta_LK      ஜப்பான் நிலையான நேரம்
 +
Asia/Tokyo ta_MY      ஜப்பான் நிலையான நேரம்
 +
Asia/Tokyo ta_SG      ஜப்பான் நிலையான நேரம்
 +
Asia/Tokyo te          జపాన్ ప్రామాణిక సమయం
 +
Asia/Tokyo te_IN      జపాన్ ప్రామాణిక సమయం
 +
Asia/Tokyo teo        GMT+09:00
 +
Asia/Tokyo teo_KE      GMT+09:00
 +
Asia/Tokyo teo_UG      GMT+09:00
 +
Asia/Tokyo th          เวลามาตรฐานญี่ปุ่น
 +
Asia/Tokyo th_TH      เวลามาตรฐานญี่ปุ่น
 +
Asia/Tokyo ti          GMT+09:00
 +
Asia/Tokyo ti_ER      GMT+09:00
 +
Asia/Tokyo ti_ET      GMT+09:00
 +
Asia/Tokyo to          houa fakasiapani taimi totonu
 +
Asia/Tokyo to_TO      houa fakasiapani taimi totonu
 +
Asia/Tokyo tr          Japonya Standart Saati
 +
Asia/Tokyo tr_CY      Japonya Standart Saati
 +
Asia/Tokyo tr_TR      Japonya Standart Saati
 +
Asia/Tokyo twq        GMT+09:00
 +
Asia/Tokyo twq_NE      GMT+09:00
 +
Asia/Tokyo tzm        GMT+09:00
 +
Asia/Tokyo tzm_Latn    GMT+09:00
 +
Asia/Tokyo tzm_Latn_MA GMT+09:00
 +
Asia/Tokyo ug          ياپونىيە ئۆلچەملىك ۋاقتى
 +
Asia/Tokyo ug_Arab    ياپونىيە ئۆلچەملىك ۋاقتى
 +
Asia/Tokyo ug_Arab_CN  ياپونىيە ئۆلچەملىك ۋاقتى
 +
Asia/Tokyo uk          за японським стандартним часом
 +
Asia/Tokyo uk_UA      за японським стандартним часом
 +
Asia/Tokyo ur          جاپان سٹینڈرڈ ٹائم
 +
Asia/Tokyo ur_IN      جاپان سٹینڈرڈ ٹائم
 +
Asia/Tokyo ur_PK      جاپان سٹینڈرڈ ٹائم
 +
Asia/Tokyo uz          Yaponiya standart vaqti
 +
Asia/Tokyo uz_Arab    GMT+۰۹:۰۰
 +
Asia/Tokyo uz_Arab_AF  GMT+۰۹:۰۰
 +
Asia/Tokyo uz_Cyrl    Япония стандарт вақти
 +
Asia/Tokyo uz_Cyrl_UZ  Япония стандарт вақти
 +
Asia/Tokyo uz_Latn    Yaponiya standart vaqti
 +
Asia/Tokyo uz_Latn_UZ  Yaponiya standart vaqti
 +
Asia/Tokyo vai        GMT+09:00
 +
Asia/Tokyo vai_Latn    GMT+09:00
 +
Asia/Tokyo vai_Latn_LR GMT+09:00
 +
Asia/Tokyo vai_Vaii    GMT+09:00
 +
Asia/Tokyo vai_Vaii_LR GMT+09:00
 +
Asia/Tokyo vi          Giờ Chuẩn Nhật Bản
 +
Asia/Tokyo vi_VN      Giờ Chuẩn Nhật Bản
 +
Asia/Tokyo vun        GMT+09:00
 +
Asia/Tokyo vun_TZ      GMT+09:00
 +
Asia/Tokyo wae        GMT+09:00
 +
Asia/Tokyo wae_CH      GMT+09:00
 +
Asia/Tokyo xog        GMT+09:00
 +
Asia/Tokyo xog_UG      GMT+09:00
 +
Asia/Tokyo yav        GMT+09:00
 +
Asia/Tokyo yav_CM      GMT+09:00
 +
Asia/Tokyo yi          GMT+09:00
 +
Asia/Tokyo yi_001      GMT+09:00
 +
Asia/Tokyo yo          GMT+09:00
 +
Asia/Tokyo yo_BJ      GMT+09:00
 +
Asia/Tokyo yo_NG      GMT+09:00
 +
Asia/Tokyo zgh        GMT+09:00
 +
Asia/Tokyo zgh_MA      GMT+09:00
 +
Asia/Tokyo zh          日本标准时间
 +
Asia/Tokyo zh_Hans    日本标准时间
 +
Asia/Tokyo zh_Hans_CN  日本标准时间
 +
Asia/Tokyo zh_Hans_HK  日本标准时间
 +
Asia/Tokyo zh_Hans_MO  日本标准时间
 +
Asia/Tokyo zh_Hans_SG  日本标准时间
 +
Asia/Tokyo zh_Hant    日本標準時間
 +
Asia/Tokyo zh_Hant_HK  日本標準時間
 +
Asia/Tokyo zh_Hant_MO  日本標準時間
 +
Asia/Tokyo zh_Hant_TW  日本標準時間
 +
Asia/Tokyo zu          Isikhathi esivamile sase-Japan
 +
Asia/Tokyo zu_ZA      Isikhathi esivamile sase-Japan
 +
</syntaxhighlight2>
 +
 
 +
=='''文字列の抽出'''==
 +
文字列のコピーでコピーする文字数を限定する関数***ncpy系の関数がありましたので、前方抽出はできまるようになったと思います。他にもtokenを使ったり、正規表現を使う事でも抽出ができました。これらの文字の位置を示す関数と、この他にも存在する文字の位置に関する関数を活用することで、もっと他の抽出方法を考えることもできます。前方から何文字目~n文字。前方のnバイト目に目的の文字開始位置があれば、そこからn文字、前方のnバイト目に目的の文字開始位置があって、次のmバイト目に終端位置があって、その間にあるn文字を抽出といった具合です。これらはマルチバイト文字がおさめられた文字列変数ではバイト数と文字数が一致しないことから慎重に処理する必要があります。またワイド文字も2バイト固定のように感じてしまいますが、実際は4バイトの文字である可能性も0ではないので、きちんと文字数とバイト数を計算して、開始位置に文字型ポインターを格納したりする必要があります。配列によって決まった長さの実体のある文字列で終端に\0が入っているような構造の先頭を指し示すポインタと、そのポインタの型と同じだけど実体は持たないポインタの変数を利用して、実体を持たないポインタ変数が、文字の抽出開始位置を指し示すようにすること、そこらからコピーする文字数を正確に数えることがポイントになります。ポイントというとポインタと紛らわしいので、ミソになりますとでも言った方がいいのかもしれません。ここで紹介する抽出と、これまでに紹介した正規表現やtokenを活用すると更に操作の幅が広がります。
 +
 
 +
 
 +
とにかく文字を数えて、文字列ポインタを移動させ、サロゲートペアなら4バイト、通常のワイド文字範囲なら2byteってなかんじで数えます。面倒ですが、サロゲートペアのことを考えると文字数での抽出はこのような気遣いが必要です。マルチバイト文字でやるときは、また違った対応が必要になります。仕組みとしては文字数とバイト数をきちんと数えて、先頭文字にポインタを合わせる。***ncpy系の関数でそこから必要なバイト数をコピーするという感じになります。コンソール画面ではShiftJISなので文字化けしますから、Unicode文字としてテキストに出力するプログラムになっています。今回のプログラムでは対応しませんでしたが、異体字セレクタに対応すると、2バイト文字にはさらに DB40 DD00 の4バイトが付与されていますので、次の4バイトの値がDB40 DD**になっていないか確認をする必要があり、そのようになっている場合は+4バイトするような計算も必要です。テキストエディタを作成する場合にはフォントを異体字セレクタにしたがって切り替える試みが必要になります。フォントが対応していなければ切り替えることはできないので、処理としては元の文字を表示するだけになります。DB40 DD** のような異体字補助番号は文字コードとして使われないことになっています。
 +
<syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string>      //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream>    //cpp cout etc 一般入出力関数
 +
#include <locale>      //Locale関数
 +
#include <tchar.h>    //TCHAR型+_tcs***関数
 +
#include "atlstr.h"    //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h"  //同上
 +
#include "cstringt.h"  //CStringTの定義プリプロセッサ
 +
#include <vector>      //Vector型テンプレートクラス
 +
 
 +
#include <sys/timeb.h> //Timeb型構造体
 +
 
 +
//_bstr_t型を利用するプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include "comutil.h"
 +
 
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t _End
 +
 
 +
//ICU ucnvプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include <unicode/ucnv.h>    //ucnv文字コード変換ライブラリヘッダ
 +
#include <unicode/translit.h> //文字変換ライブラリヘッダ
 +
#include <unicode/regex.h>    //正規表現
 +
#include <unicode/ucsdet.h>  //文字コード判定
 +
#include <unicode/ucal.h>  //文字コード判定
 +
#include <unicode/uclean.h> //u_cleanup関数
 +
/* for uloc_getDefault() */
 +
#include <unicode/uloc.h>
 +
#include <unicode/calendar.h>
 +
#include <unicode/smpdtfmt.h>
 +
 
 +
//#include "unicode/utypes.h"
 +
//#include "unicode/locid.h"
 +
//#include "unicode/unistr.h"
 +
//#include "unicode/tzfmt.h"
 +
//#include "unicode/tznames.h"
 +
 
 +
 
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuucd.lib")  //ICU ucnvを使うために必要なライブラリ
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "iculed.lib")
 +
#pragma comment(lib, "iculxd.lib") 
 +
#pragma comment(lib, "icuiod.lib") 
 +
#pragma comment(lib, "icutud.lib") 
 +
 
 +
#else
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuuc.lib")  //ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuio.lib")
 +
#endif
 +
//Data  Library                    icudtXX(d).dll icudt(d).lib
 +
//Common Library                    icuucXX(d).dll icuuc(d).lib
 +
//Internationalization(i18n) Library icuinXX(d).dll icuin(d).lib
 +
//Layout Engine                      iculeXX(d).dll icule(d).lib
 +
//Layout Extention Engine            iculxXX(d).dll iculx(d).lib
 +
//ICU I/O(Unicode stdio) Library    icuioXX(d).dll icuio(d).lib
 +
//Tool Utility Library              icutuXX(d).dll icutu(d).lib
 +
 
 +
//ICU ucnv _End
 +
 
 +
#include "UnicodeConverter.h"
 +
 
 +
using namespace std;
 +
 
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese")); //ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 
 +
_locale_t localeJpanease;
 +
localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 
 +
  FILE* pfileText;
 +
  fpos_t* fposPos = new fpos_t;
 +
  errno_t errNo;
 +
  size_t* psizeRuturnValue = new size_t;
 +
 
 +
  wchar_t pwcStrFilePath[]            = L"C:\\...\\...\\...\\test_new_Extract.txt";
 +
  char* pcStrStream;
 +
  pcStrStream = new char[1024];
 +
  int nCloseResult = 0;
 +
 
 +
  wchar_t pwcStrSurrogate[] = L"\xD840\xDC0B\xD867\xDE3Dごはん\xD840\xDC0B\xD842\xDFB7を食べたYo。";//L"𠀋𩸽ごはん𠀋𠮷を食べたYo。"と同じ。
 +
  const wchar_t* pwcStrPos;//実体は持たない文字位置格納変数
 +
  const wchar_t* pwcStrStPos;//実体は持たない文字位置格納変数
 +
  wchar_t* pwcStrSurrogateExtract;
 +
 
 +
  pwcStrPos = pwcStrSurrogate;
 +
  int nSize =  wcslen(pwcStrSurrogate);
 +
  int nByteCnt = 0;
 +
  int nCharCnt = 0;
 +
  int nStPos = 2;//文字位置では0文字目からカウントする仕組みなので、3文字目にポインタが合います。
 +
  printf("%d\n",nSize);
 +
  while (nByteCnt < nSize && nCharCnt < nStPos){
 +
    unsigned int unValue = _wcsnextc(pwcStrPos);
 +
    pwcStrPos++;
 +
    printf("%0x:",unValue);
 +
    if(unValue >= 0xD800 && unValue <= 0xDFFF){ 
 +
      pwcStrPos++;
 +
      nByteCnt++;
 +
    }
 +
    nCharCnt++;
 +
    nByteCnt++;
 +
  }
 +
  pwcStrStPos = pwcStrPos;//先頭の文字列にポインタを合わせる。
 +
  printf("\n");
 +
  printf("%d[Byte],%d[文字]\n",nByteCnt,nCharCnt);
 +
  int nEnPos = 5;//先頭文字から5文字目までのバイト数を数えます。そういう意味では最初の先頭文字の指定と合わせた方が良かったかも。
 +
  nByteCnt = 0;
 +
  nCharCnt = 0;
 +
  nSize =  wcslen(pwcStrPos);
 +
 
 +
  printf("%d\n",nSize);
 +
  while (nByteCnt < nSize && nCharCnt < nEnPos){
 +
    unsigned int unValue = _wcsnextc(pwcStrPos);
 +
    pwcStrPos++;
 +
    printf("%0x:",unValue);
 +
    if(unValue >= 0xD800 && unValue <= 0xDFFF){ 
 +
      pwcStrPos++;
 +
      nByteCnt++;
 +
    }
 +
    nCharCnt++;
 +
    nByteCnt++;
 +
  }
 +
  printf("\n");
 +
 
 +
  pwcStrSurrogateExtract = new wchar_t[nByteCnt + 1];
 +
  wcsncpy_s(pwcStrSurrogateExtract, nByteCnt + 1, pwcStrStPos, nByteCnt);//5文字分のバイト数をコピーする。7バイトだね。
 +
 
 +
  printf("%d[Byte],%d[文字]\n",nByteCnt,nCharCnt);
 +
  wprintf(L"%s",pwcStrPos);
 +
  printf("\n");
 +
 
 +
  fpos_t* pfposStartPos = new fpos_t;
 +
  printf("★テキストの新規書き込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePath, L"w,ccs=UTF-16LE");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fputws(pwcStrSurrogate,pfileText);
 +
  fputws(L"\n",pfileText);
 +
 
 +
  fputws(pwcStrStPos,pfileText);
 +
  fputws(L"\n",pfileText);
 +
 
 +
  fputws(pwcStrPos,pfileText);
 +
  fputws(L"\n",pfileText);
 +
 
 +
  fputws(pwcStrSurrogateExtract,pfileText);
 +
 
 +
  fclose(pfileText);
 +
  return 0;
 +
}
 +
</syntaxhighlight2>
 +
コンソール側出力
 +
<syntaxhighlight2 lang="text">
 +
18
 +
d840:d842:
 +
4[Byte],2[文字]
 +
14
 +
3054:306f:3093:d840:d842:
 +
7[Byte],5[文字]
 +
を食べたYo。
 +
★テキストの新規書き込み
 +
Error?->0
 +
</syntaxhighlight2>
 +
テキスト出力
 +
<syntaxhighlight2 lang="text">
 +
𠀋𩸽ごはん𠀋𠮷を食べたYo。
 +
ごはん𠀋𠮷を食べたYo。
 +
を食べたYo。
 +
ごはん𠀋𠮷
 +
</syntaxhighlight2>
 +
 
 +
 
 +
という感じで、以上ですかね。
 +
 
 +
 
 +
基本機能を用いて、文字列操作のすべてを掌握できるような、異常なまでに長い記事を書いたつもりです。それくらい文字列操作はコンピュータを使う人から喜ばれるプログラミングだと思います。文字を扱うプログラムは意思を疎通したり記録したり、人間文化の中枢にある処理です。プログラムによって文字情報をうまく表示してくれたり、編集してくれたり、閲覧できるようになることは、ありがたいこと、この上ない機能でしょう。ここで紹介したものだけでは文字処理の効率はイマイチかもしれません。便利な文字列クラスはこのWebの世界をたぐり探せば存在するかもしれません。ですが、C++範疇の文字列操作のエッセンスとしては、ここで紹介したものがほとんど全てとなります。この長い記事を参考に理解する努力をしてみたのなら、やりたい文字列操作をどういう具合にやっていけばいいのかという基本というかコツみたいなものはつかめたと思います。つかめなかった人もヒントくらいにはなったのではないでしょうか?ここから先はプログラムされる人のそれぞれの文字列操作感覚に従って、プログラムを作りこんでいっていただければと思います。基本がわかっていれば、Webで検索してでてくるようなややこしい説明も理解していけるでしょう。やりたいことを実現するのは面倒で手数も多いと実感したと思います。効率よくやりたいことができるようになるまで、知恵を振り絞って、頑張ってみてください。ここまで理解しようとしたならきっとできるはずです。
 +
 
 +
 
 +
ここを参照してくれたみなさんが作れってくれたアプリが使いやすいものになって、いろんな人の人生を充実させるものになることを願います。
 +
 
 +
 
 +
[[C PlusPlus#Cにもあった技術|C++]]へ戻る
 +
 
 +
 
 
<!--
 
<!--
 
{|class="wikitable"
 
{|class="wikitable"

2022年9月5日 (月) 00:00時点における最新版



個人用ツール
名前空間

変種
操作
案内
ツールボックス