C 日本語文字列 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(マルチバイト文字列、ワイド文字列)
(マルチバイト文字列、ワイド文字列の相互変換)
207行: 207行:
  
 
== '''マルチバイト文字列、ワイド文字列の相互変換''' ==
 
== '''マルチバイト文字列、ワイド文字列の相互変換''' ==
 +
まずは、文字列の配列で以下のように格納されているものがあって、<br />
 +
TCHAR *cStr0[]={_T("表示:よねウィキの機能<yonewiki>"),_T("表示:よねウィキの機能1<yonewiki>"),_T("表示:よねウィキの機能2<yonewiki>")};<br />
 +
を単純にpcStr0というポインタ変数を使って、まるまるコピーする場合はこんな風に自分ならやります。<br />
 +
動的メモリを確保してもらいますが、それで効率が本当にいいのか悪いのかは知りません。なんとなくやりきった感じだけはします。<br />
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#include <iostream>
 +
//#include<locale.h> tchar.hがインクルードされていれば、いらない。
 +
#include<tchar.h>
 +
int main() {
 +
_tsetlocale( LC_ALL, _T("Japanese"));
 +
TCHAR *cStr0[]={_T("表示:よねウィキの機能<yonewiki>"),_T("表示:よねウィキの機能1<yonewiki>"),_T("表示:よねウィキの機能2<yonewiki>")};
 +
TCHAR **pcStr0 = new TCHAR*[sizeof(cStr0)/sizeof(*cStr0)];
 +
for(int i = 0; i < (sizeof(cStr0)/sizeof(*cStr0)); i++){
 +
                _tprintf(_T("cStr0=%s sizeof=%d StrCount=%d\n"), cStr0[i], sizeof(cStr0)/sizeof(*cStr0),_tcslen(cStr0[i]));
 +
pcStr0[i] = new TCHAR[_tcslen(cStr0[i]) + 1];
 +
_tprintf(_T("cStr0=%s\n\n"),*(cStr0 + i));
 +
_tcscpy_s(pcStr0[i], _tcslen(cStr0[i]) + 1,cStr0[i]);
 +
}
 +
for(int i = 0; i < 3; i++){
 +
_tprintf(_T("_tcslen(cStr0[i])=%d\npcStr0=%s\n cStr0=%s\n\n"),_tcslen(cStr0[i]),*(pcStr0 + i),*(cStr0 + i));
 +
}
 +
for(int i = 0; i < 3; i++){
 +
delete[] *(pcStr0 + i);
 +
}
 +
delete[] pcStr0;
 +
printf("\n");
 +
return 0;
 +
}
 +
</syntaxhighlight>
 +
本当は12行目のコピーをする関数である_tcscpy_s関数は語尾の_sの無い関数を使いたいところですが、warningが表示されるので、あえて使いこなします。<br />
 +
_tcscpy_sの第一引数はコピー先のTCHAR型先頭アドレスでコピーするのに必要な配列の大きさを持っていれば良いです。第二引数では、コピー先の配列の大きさを指定しています。<br />
 +
第三引数はコピー元のTCHAR型の先頭アドレスです。<br />
 +
<br />
 +
7行目のNew演算子では、TCHAR型のポインタのポインタ型の配列大きさを3を確保して、実体化しています。<br />
 +
アドレスを保持できる4Byteの大きさの領域が配列番号0~3まで作られたことになります。<br />
 +
10行目のNew演算子では、cStr[0]~[2]の文字列の文字数+1の大きさの配列をTCHAR型で確保します。<br />
 +
ワイド文字列のwchar_t型でも21文字+1、22文字+1、22文字+1と順番に確保しますし、<br />
 +
マルチバイト文字ならchar型ですので、すべて全角文字に対しては2byte、2文字分の領域が必要だと計算し、<br />
 +
32文字+1、33文字+1、33文字+1を確保します。何故+1文字分を確保するかと言えば、文字列の最後には\0を格納してくれるので、<br />
 +
その分をあけておかなければなりません。<br />
 +
18行目、20行目では、delete演算子で動的生成した領域の放棄を宣言して、リソースを返却します。<br />
 +
使い終わったら速やかに、返す。<br />
 +
出力結果はマルチバイト文字設定だと<br />
 +
<syntaxhighlight lang="cpp">
 +
cStr0=表示:よねウィキの機能<yonewiki> sizeof=3 StrCount=32
 +
cStr0=表示:よねウィキの機能<yonewiki>
 +
 +
cStr0=表示:よねウィキの機能1<yonewiki> sizeof=3 StrCount=33
 +
cStr0=表示:よねウィキの機能1<yonewiki>
 +
 +
cStr0=表示:よねウィキの機能2<yonewiki> sizeof=3 StrCount=33
 +
cStr0=表示:よねウィキの機能2<yonewiki>
 +
 +
_tcslen(cStr0[i])=32
 +
pcStr0=表示:よねウィキの機能<yonewiki>
 +
cStr0=表示:よねウィキの機能<yonewiki>
 +
 +
_tcslen(cStr0[i])=33
 +
pcStr0=表示:よねウィキの機能1<yonewiki>
 +
cStr0=表示:よねウィキの機能1<yonewiki>
 +
 +
_tcslen(cStr0[i])=33
 +
pcStr0=表示:よねウィキの機能2<yonewiki>
 +
cStr0=表示:よねウィキの機能2<yonewiki>
 +
</syntaxhighlight>
 +
となります。<br />
 +
ワイド文字列設定なら<br />
 +
<syntaxhighlight lang="cpp">
 +
cStr0=表示:よねウィキの機能<yonewiki> sizeof=3 StrCount=21
 +
sizecStr0=0,cStr0=表示:よねウィキの機能<yonewiki>
 +
 +
cStr0=表示:よねウィキの機能1<yonewiki> sizeof=3 StrCount=22
 +
sizecStr0=0,cStr0=表示:よねウィキの機能1<yonewiki>
 +
 +
cStr0=表示:よねウィキの機能2<yonewiki> sizeof=3 StrCount=22
 +
sizecStr0=0,cStr0=表示:よねウィキの機能2<yonewiki>
 +
 +
_tcslen(cStr0[i])=21
 +
pcStr0=表示:よねウィキの機能<yonewiki>
 +
cStr0=表示:よねウィキの機能<yonewiki>
 +
 +
_tcslen(cStr0[i])=22
 +
pcStr0=表示:よねウィキの機能1<yonewiki>
 +
cStr0=表示:よねウィキの機能1<yonewiki>
 +
 +
_tcslen(cStr0[i])=22
 +
pcStr0=表示:よねウィキの機能2<yonewiki>
 +
cStr0=表示:よねウィキの機能2<yonewiki>
 +
</syntaxhighlight>
 +
となります。Visual C++をつかわれているのであれば、プロジェクトの設定をマルチバイトにしたり、Unicodeにしてみたりして下さい。<br />
 +
TCHAR型で記述しているので、どちらでも動作すると思います。<br />
 +
<br />
 +
それで、なんでしたっけ、ワイド文字列とマルチバイト文字列の相互互換なんですけど、<br />
 +
ようするにこのコピーをするときにワイド文字列とマルチバイトが混じっているケースで考えて、どのように対処すればいいのかで、<br />
 +
説明ができると思ったのでした。<br />
 +
mbstowcs関数とwcstombs関数でやりとりが出来るようになっています。<br />
 +
実際、こんなケースがあるのかは知りませんが、こんな関数があるってことは、テキストをどこからか読み込んだ場合とか、<br />
 +
そういったプログラムから引数として受け取るとか、そういったケースもあるのでしょう。<br />
 +
関数の引数はそれぞれ異なるので、気を付けなければなりません。
 +
 +
で、無理矢理にそういったサンプルのプログラムを作るのは意外と面倒でして、サンプルは鋭意執筆中ということにしておきたいと思います。ぉぃ。<br />

2013年11月23日 (土) 00:00時点における版



個人用ツール
名前空間

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