Version 5.08
LPCTSTR
「というわけで、数字を文字列に変えるには?」
『 sprintf() ! だよね』
「そういうこと。それじゃ、久々に FileTest プロジェクトに戻って」
void CFileTestDlg::OnBtnShow()
{
m_cDataLstBox.AddString( "あたし" );
m_cDataLstBox.AddString( "水希ちゃん" );
m_cDataLstBox.AddString( "そんな感じ" );
}
『あ、ボタン押したらリストボックスに追加するっていうのだよね』
「 Ver 5.02 ( No.067 ) の続きってことで。今回の計画では、ファイルに
いっぱい入ってる整数値をリストボックスに追加する、っていうことにしま
す」
『そー決められました』
「そのためのテストってことで、3つの整数値をリストボックスに追加する
ように、このメンバ関数を書き換えてみて」
『おお、ちゃんとしたプログラムっぽい! えっと……』
「こういうときは、まずひとつだけ追加、って形にして」
『あとで増やすんだね。プログラムは少しずつの積み重ね』
「そゆこと」
『じゃ、まず int 変数用意。あ、読み取り専用だから const にしとこ』
const int iSource = 100;
『これを文字列に変換すれば、 AddString() に渡せるんだよね。……とり
あえず渡すところだけ書いてみようかな。 char 配列用意してっと』
char chDist[256];
『そいや、この前とかも chDist だったけど、 Dist ってどーゆー意味?』
「……あ!」
『な、なに?』
「ごめん、間違った」
『ええ〜!!』
「 chDest だ。 Dest は destination の略で〈目的地〉とかって意味」
『う〜、しっかりしてよ〜』
「まーこういうこともあるよ」
『……で、 chDest にして、これを AddString() に渡すんだから』
m_cDataLstBox.AddString( chDest );
『あとは iSource から chDest に変換すればいいんだから、 sprintf()
使って……』
sprintf(
『っと、使い方分かんないや』
「そういうときは MSDN 」
『だね。って、 sprintf() のページ見ても分かんないんだけど……』
「〈引数〉のところ見れば」
『あ、第1引数の char ポインタに書き込まれるんだね』
「分かってると思うけど、ポインタは」
『配列に [] 付けないの渡せばいいんだよね。ところでこの sprintf() の
ページに書いてある buffer ってなに?』
「バッファっていうのは〈緩衝材〉って意味で、とりあえずデータを置く場
所。でもここじゃ〈文字列を置く場所〉って意味で使われてるかな」
『とりあえずの置き場か。じゃ、さっきの chDest も chBuffer の方が良か
ったかな』
「その辺は場合場合だね。実際、 AddString() が最終的な出力先だから、
chBuffer の方がいいかもね。あとは chTemp とか」
『 Temp って人材派遣会社の』
「あ、それ当たり」
『ええ〜なんでツッコミ入れてくんないの?』
「だから当たりだって。 Temp は temporary の略で〈臨時の〉って意味」
『あ、だから人材派遣なわけね』
「変数としては、一時的なデータの置き場、って感じかな。でもこういうの
使い始めると大変だからほどほどにね」
『だよね、何度もデータ変換したりしなきゃいけなかったら Temp だらけに
なりそうだもんね。でっと、 sprintf() の最初の引数が出力先だから』
sprintf( chDest,
『あとは TRACE() と同じっと。全部まとめると』
void CFileTestDlg::OnBtnShow()
{
const int i = 100;
char chDest[256];
sprintf( chDest, "%d", i );
m_cDataLstBox.AddString( chDest );
}
『ビルドして実行、【表示】ボタンを押すと……やたっ、 100 って出た!』
「そんな感じだね。さて、ちょっと脇道にそれて、 AddString() って何だ
っけ」
『メンバ関数だよね。えっと m_cDataLstBox は…… CListBox の変数なん
だよね』
「これも Ver 5.02 ( No.067 ) を参照にしてねってことで」
『だから CListBox の AddString() なんだよね。 MSDN 見てもそう書いて
あるよ』
「その MSDN のページ、 AddString() の引数は?」
int AddString( LPCTSTR lpszItem );
『…… LPCTSTR ?? "" で囲んだの……文字列リテラルだっけ、それ渡せ
てたからてっきり char * だと思ってたのに……』
「前は〈 LPCTSTR って書いてあったら文字列を渡せる〉ってことにしてた
けど、ここでひとつ、しっかり見ておきましょう」
『うお”、なんか大変そうな予感!』
「さてまず、〈組込型〉っていうものから」
『くみこみがた?』
「基本型とかプリミティブ型とかとも言うんだけど、 C++ 言語に初めっか
ら入ってる型のこと」
『ってことは、 char とか int とかってこと?』
「そういうこと。 MSDN で〈基本型〉のページ見てみて」
『あ、これって前に見たことあるような気が』
「 Ver 4.08 ( No.058 ) で見たね。ここに載っているのが組込型」
『 LPCTSTR 載ってないね』
「で、ここに載っていない型は、どっかで必ず定義されてます」
『どゆこと?』
「たとえば CListBox はクラスだから、どっかで定義されてるはずってこと」
『クラスなんかがそうなるんだね。ってことは、 LPCTSTR もどっかで定義
されてるの?』
「そういうこと。 MFC の入ってるフォルダの Afxwin.h の中で」
class CListBox : public CWnd
{ // 以下略
「って感じに作られてるわけ」
『 MFC のフォルダ?』
「 MFC そのもののプログラムが入ってるフォルダね。詳しくは Ver 3.8
( No.033 ) を読み返して思い出してみて」
『そうそう、 CWnd とか全部そうやって入ってるんだった。もう1年も前だ
から忘れてたけど』
「同じように、 LPCTSTR も作られてるわけ」
『ってことはクラス?』
「あ、そういうわけじゃないんだけどね。それに、 MFC のものでもないし」
『じゃーなんなの? ランタイム? あ、でも sprintf() は char * だっ
たもんね』
「あともうひとつあったでしょ、 API っていうのが」
『なんだっけそれ』
「……」
『あー、 API っていうのがウィンドウズの操作をするためので、 MFC はそ
れを呼んでるだけなんだよね、って Ver 3.9 ( No.034 ) とかに書いてある』
「 LPCTSTR は API で定義されているもの。この定義されてる部分も、プロ
グラムとしてちゃんと書かれてるから」
『それを探すんだよね』
「そう、実際には全文検索で探すんだけど、これはかなり大変だから、今回
は直接見てみることにするね」
『難しいの?』
「そう、探し方にコツがいるし、どれが求めてる情報なのか見極めるための
知識も必要」
『そーゆーもんなんだ』
「というわけで、 LPCTSTR は Wtypes.h で次のように定義されてます」
typedef /* [string] */ const TCHAR __RPC_FAR *LPCTSTR;
『あ、 typedef って初見』
「 typedef は sizeof と同じ C++ の機能のひとつで、型の〈別名〉を付け
るためのもの」
『別名?』
「たとえば」
typedef int Int;
「ってなってたら、 Int を int と同じように使えるってこと」
『あ、そういう別名なんだ』
「あと」
typedef int *PInt;
「なら、 PInt は int * 型として使えるようになるから」
『よーするに、一番最後の単語が〈新しい型〉なんだよね』
「そうそう。ってことは?」
『ってことは、 LPCTSTR 型は、 const TCHAR __RPC_FAR * 型ってことにな
るけど……なんかチンプンカンプン』
「でも分かんないのふたつだけでしょ」
『うん、 TCHAR と __RPC_FAR ってゆーの』
「 TCHAR も __RPC_FAR も、同じように〈他のの別名〉。全部大文字の単語
はたいがいそうだね」
『ってことは、 TRACE() も?』
「あ、そういえばそうだね。で、 TCHAR は char の別名。 __RPC_FAR は空
白」
『空白?』
「そ。えっと、 Rpc.h っていうファイルに次のような行があるでしょ」
# define __RPC_FAR
『あ、 define って前に見たね』
「 #define は〈単語の置き換え〉をするためのもの。 Ver 4.09 ( No.059 )
でやったよね」
『そうそう、定数値作るときに使った。でもこれって、何に置き換えてる
の?』
「これは空白に置き換えてるもの」
『あ、右側の単語が左側のに置き換わるんだもんね、だから空白になるんだ。
……? 置き換わるって、なんか typedef みたいだね』
「そう、昔は typedef の代わりによく使われてたかな。ま、その辺は置い
といて、結局 LPCTSTR は?」
『 TCHAR を char にして、 __RPC_FAR を空白にすると』
typedef const char *LPCTSTR;
『あ、なんだ、ただの const char ポインタじゃない! だから文字列リテ
ラルとか渡せたんだ』
「同じく、 LPTSTR っていうのは」
typedef /* [string] */ TCHAR __RPC_FAR *LPTSTR;
『これはただの char ポインタだね』
「つまり LPCTSTR も LPTSTR も」
『ただの char ポインタ、文字列用に使うってことなんだね。あと const
のあるなしで、 LPCTSTR が渡す専用、 LPTSTR が受け取りようなんだ』
「 API とか MFC でこのふたつはよく出てくるから。重要なのは、こうやっ
て調べればちゃんと分かるってこと」
『私はわかんないけど……』
「もちろん今はね。でも勉強すればちゃんと分かる!」
『ようするに、 LPCTSTR みたいな謎なのも、なんとかできればちゃんと分
かるってことね』
「そういうこと」
/*
Preview Next Story!
*/
『でも難しい〜』
「ま、細かいことよりも〈調べれば分かる!〉ってことが大事」
『それはそうよね、〈何も分かんない〉じゃ政治は変わらないよね』
「うお、なんかすごいこと言ってる……」
『というわけで次回』
< Version 5.09 ファイルから読み取る! >
「につづく!」
『あ、もしかしたら iostream とか使う?』
「使います」
『おお!!』