鏑矢の憂鬱2000年11月前半
透明1ドットイメージ
 
2000/11/01 (Wed)
・今日は STL & iostream 入門の中から STL の #06 - #09 を Codian に移して、イラストを追加しました。いつも思うんだけど、書いてるときには文章量気になんないのに、読み返すときにはなんかいつのまにかすごい量になってる(爆)。しかも推敲ってむっちゃ精神力使うんでややへとへと気味。
 
・あと、就職前研修で情報処理2種レベルの勉強をしてるんだけど、これって結構ためになります(爆)。これはやっとくべきかもしんない。でも、プログラミングやるぞーってときにこれから始めたら絶対イヤになる(爆)。全然楽しくないもん。知識偏りながらでもいいから、ゲーム作りながらとかの方がずっと憶えるの早いだろうなーと思うです。仕事でこれ勉強しなきゃってことだったら、ホント辛いだろうなぁ……。
 
・それでも、プログラミングってのは他のものよりもずっと身に着けるの簡単だと思うんです。まず、勉強したことがすぐ実践できる。プログラム組んでコンパイルして実行すればいいわけだから。膨大な知識量が必要だけど、それはネットにアウトソーシング(爆)。必要なときに拾ってくれば十分でしょう。そして、コピーがいくらでもできるってのが大きいかな。たとえば「ピアノの演奏」なんてスキルはコピーが効かないから一回一回弾き直さなきゃなんないけど、ソースコードなら他の人が書いたのでもいいし、自分のも少しずつ直せるからね。
 
・あとは「1から書き起こせる技術」かなぁ。わては元々小説書いてた関係でそーゆーのは苦になんないんだよね。理系の人にとってはそーゆーの大変なのかなとか思う。でもま、これも最終的には貼り付けていけばいいんだから大丈夫か。時間掛かるだろうけど。とゆーわけで、プログラマーになるのは簡単です。勉強してくうえで「うげーわかんねー!」ってゆーつまずきがあったら、うちに訊きに来ましょう(爆)。就職前研修中の方大歓迎〜!
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/02 (Thu)
・うにゃ。では今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 リストビューのデータをソートしたいんですが、やり方が分かりません。教えてください。
透明1ドットイメージ
透明1ドットイメージ
 
・リストコントロールに付いてるソート機能、使いづらいんだよねー。一応、リストコントロールのスタイルに「昇順でソートする」「降順でソートする」っていうのがあるから、プロパティの設定や LVS_SORTASCENDING や LVS_SORTDESCENDING をウィンドウスタイルに設定してこの機能使っても医院だけど、でもこれは「ラベルの文字列」でしかソートできないから使えないかな。任意の基準でソートするときには、 LVM_SORTITEMS メッセージを使います。 MFC なら CListCtrl::SortItems() 。これ使ってみましょう。
 
// グローバル変数(汗)。
CListCtrl *gp_cListCtrl;

// ソート用コールバック関数。
int CALLBACK CompareFunc
	( LPARAM lParam1, LPARAM lParam2
	, LPARAM lParamSort)
{
	int iRes
		= gp_cListCtrl->GetItemText( lParam1, 0 ).Compare
			( gp_cListCtrl->GetItemText( lParam2, 0 ) );
	return iRes;
}

// この関数を最初に呼びだしてください。
void SortListCtrl( CListCtrl &pr_cListCtrl )
{
	gp_cListCtrl = &pr_cListCtrl;
	BOOL bRes;
	for( int iF1 = 0; iF1 < 100; iF1++ )
	{
		bRes = pr_cListCtrl.SetItemData( iF1, iF1 );
		if( !bRes )
			break;
	}
	pr_cListCtrl.SortItems( CompareFunc, 0 );
}
	
 
・まず、ソートにはコールバック関数が必要。上の例だと CompareFunc() がこれにあたります。このコールバック関数が「値の比較」の役割を持つように実装します。ところが! この関数に渡されるのは「各アイテムが持つオマケな値」なんで、そのままではソートできません。そこで、ソート直前にこの「各アイテムのオマケな値」を「インデックスナンバー」に書き直します。それが上の for ループね。
 
・これが終わったら CListCtrl::SortItems() を呼んでソート開始。第1引数にコールバック関数へのポインタを渡します。すると、リストコントロールからコールバック関数が呼ばれます。 lParam1 と lParam2 は「各アイテムが持つオマケな値」なんだけど、さっきインデックスナンバーに書き換えてあるから、これで直接アイテムの文字列を取得して、それを CString::Compare() で比較して返します。これでソート完了。
 
・なんかまー、グローバル変数とか普通の関数とか使わなきゃいけないのがイヤーンだけど(汗)、まーこの辺はなんとかなるでしょ。コールバック関数は static メンバ関数に置き換えても大丈夫だし。あと、今回は「ソートごとに SetItemData() を呼ぶ」ってしてるんだけど、そうじゃなく、データ丸ごと配列や CArray や std::vector に入れて、各要素へのポインタを SetItemData() しとくっていう方法もあるかな。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/03 (Fri)
・今日もお便り紹介!
 
透明1ドットイメージ
透明1ドットイメージ
 いつも楽しく読ませて頂いています。今日は質問です。
 Windows98はTrackMouseEvent APIを使えばマウスがウィンドウから出ていったことを調べられるんだぞー、っていうのを聞いて
 
http://www.nekomimi.ne.jp/~sysneitf/mfc/mouse_track.html
 
 この辺のを参考に試してみたのですが、どうしてもコンパイル時に
 
Myapp.obj : error LNK2001: 外部シンボル "_TrackMouseEvent" は未解決です
Debug/Myapp.exe : fatal error LNK1120: 外部参照 1 が未解決です。
link.exe の実行エラー
	
 
 とか言われてしまいます(T_T)
 このエラーの意味するところはなんなのでしょうか?
 MFCは使わずにSDKでやってるのが原因でしょうか(T_T)
透明1ドットイメージ
透明1ドットイメージ
 
・んーと、このエラーは「あるヘッダーファイルで宣言されている関数を使ったんだけど、リンクする段階で関数の本体が見つからない」って場合に発生するエラーです。たとえば「関数の宣言だけして定義部書いてない」とかって時に発生します。今回の場合 DLL の中の関数なんでちょっと違って、「 TrackMouseEvent がライブラリファイルの中にない」っていうことなんだと思います。
 
・リファレンスを見ると TrackMouseEvent() は user32.lib ってライブラリファイルの中に入ってるんで、まずこれが【プロジェクトの設定】ダイアログの【リンク】−【一般】ページの【オブジェクト/ライブラリモジュール】に書き込まれてるかチェック。って言っても、普通に SDK で GUI アプリ作るときにはまず書いてあると思うんでこれは大丈夫でしょう。
 
・そうなると、 VC のバージョンとかかな。 TrackMouseEvent() は最近装備された関数だから、 VC5 以前に付いてる user32.lib には TrackMouseEvent() が入ってないっていう可能性もあるかも。とりあえずこちらでは VC6 & Win98 、 Console プロジェクトでリンクが成功するのを確認してるんで、一度この環境で最初から組み直してテストしてみた方が早いかもしんない。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/04 (Sat)
・今日はお休みしまーす。
透明1ドットイメージ
 
2000/11/05 (Sun)
・お知らせ! 今日の更新で Codian に STL の関数オブジェクト(前編)を追加しました。クラスをどんどん作っていかないといけない関数オブジェクトについての解説です。まーメルマガのと同じなんだけど良かったらこっちも見てねん。来週は iostream の「文字列からの読み取り」を追加する予定。
 
・あと今日は就職前研修・情報処理2種レベルのをしてました。マルチタスク OS の仕組みとか書かれてて、フツーの人はこーゆーのから勉強するのかーとか(爆)。わては仕組みの前にまず API とかで使うっていう方が先だったからなー。実際、 API で触れると OS の概観とかは結構わかったりするもんです。ちょっと危険だけど(爆)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/06 (Mon)
・ういー、やっぱ辞書いっぱい来てる(汗)。でも、前みたく「検索しちゃったー」的な単語が少ないのがちょっと嬉しいかもしんない。とりあえず気ままに送ってねー。今日はこれだけ(爆)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/07 (Tue)
・今日は就職前研修をしに会社へ行ってきました。どんな感じだったかは日記の方で<なぜこっちで書かん!
透明1ドットイメージ
 
2000/11/08 (Wed)
・あなたは「ガベージコレクション」派? それとも「ガーベジコレクション」派? どーでもいーけど「ガベージ」は東京風、「ガーベジ」は大阪風な気がする(爆)。では今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 アイコンはDrawIconでウィンドウに表示できますが、 Explorerとかでは選択された場合にアイコンが青っぽくなりますよね? あの選択されたアイコンはどうやって表示したら良いのでしょうか?
透明1ドットイメージ
透明1ドットイメージ
 
・これは結構面倒そう。普通に HICON としてそういうアイコンを取得する方法は見つからなかったです。描画方法としては、 CImageList::Draw() ( API なら ImageList_Draw() )に ILD_SELECTED を渡すことで「選択状態(ハイライト状態)」を描けるみたいです。ただイメージリスト使うの面倒そう……。
 
・あと、 SHGetFileInfo() に SHGFI_SELECTED を渡しても得られるそうだけど、これって「ファイルのアイコン」だからちょっと限定されちゃいますね。あと Knowledge Base の Q128786 に書いてあるのが「自前で描画する方法」っぽいんで、最終的にはこんな感じにする必要があるかもしんない……。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/09 (Thu)
・今日はぷらとわを書いてました。今日1日で2話半書けました。気合いがあればこれだけできる(爆)。今日書いたのは、ランタイムも MFC も結局 API を使ってるんですよーって部分と、文字列リソースの読み込み、エラーの表示方法とか結構色々。
 
・ぷらとわでは、こまごまとしたことをしっかり書いていきたいなと思ってます。だって、そういう事こそ重要なのに、どこにも書いてないんだもの(爆)。プログラムに必要なことを「なぜ」を含めてしっかり書いていきたいです。たとえば「リテラル文字列はないほうがいい」とか。
 
・だからまー、なんか全然終わる気配見せないんですけど(汗)。今の「ファイル読み込んで表示」ってのも、あと10回は続くだろうし。このネタで半年も掛かるとはなー。最終回までにあと何年かかるんだか……。っつーか自分でも「どこが最終回か」ってのは全然イメージできてないんだけどね。でもとりあえず、今の段階がほど遠いことははっきり判ってるんで(汗)。来年中に終わらないのは確実だな……。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/10 (Fri)
・今日は就職前研修(提出物)をしてました。 OS の仕組みとかアルゴリズムとか、なんか結構難しい(汗)。わてはウィンドウズで身に着けて MSDN で用語憶えてって感じだから、こういう汎用的な用語や用法は苦手だなー。まー実際に仕事で使うことはあんまないとは思うんだけど(汗)。あ、今日はこれだけだわ(爆)。
 
・あ、そうそう! やっぱスケジュール的に大変なんで、来週と再来週、つまり13日から26日までの間は辞書の単語受付をお休みします。ま、たった2週間なんで心配しないよーに。これまでにも何度となく短期休業してるし。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/11 (Sat)
・今日はポッキーの日……でわなく(そうだけど)、お休みです。うにゃ。
透明1ドットイメージ
 
2000/11/12 (Sun)
・まずはお知らせ。 Codian に iostream の #07 から #10 を追加しました。つっても、 STL に比べると人気ないんだけどね(泣)。 sprintf() や sscanf() の代わりになるのになぁ。あと辞書も今日から2週間お休みします。ま、たった2週間ですな。
 
・その辞書の話。なーんか、さすがに単語数が640もあると、昔書いたのはちょっとヤバイです(汗)。継承の項目がスゲーバカなこと書いてたんでちょっと手直ししたり。 is-a とかちゃんと書いてるのに、継承が「コードの減少に役立つ」とかゆーことを言ってたら全然信憑性ないですな。会社入ったらさすがに単語の受付はできないけど、メンテは少しずつしてった方がいいかもなー。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/13 (Mon)
・今日はお休みしまーす。
透明1ドットイメージ
 
2000/11/14 (Tue)
・今日はお便り紹介。質問が多かったんでふたつに分けますねー。では前半!
 
透明1ドットイメージ
透明1ドットイメージ
 VisualC++6 pro. で、プロファイラを使いたいのですが、使いかたを教えてもらえませんか?
 
 STL のvector とかで、T0,T1 とかありますが、あれは何?
 
 string -> char* の変換って、char を新たに確保して、コピーしなおさないとできないのですか? string::data() だとできないことがあります。( linux gcc )
 
 読みやすいコードを書くようにしたいと思っています。で、金菜さん、じゃなかった鏑矢さんの、なんか規約みたいなもん教えてください。
透明1ドットイメージ
透明1ドットイメージ
 
・プロファイラって使ったことなかった(爆)。あんま必要なかったからなー。「プロジェクトの設定」ダイアログの「リンク」ページの一番下の欄に /profile を追加してリビルドしてから、「ビルド」−「プロファイル」で色々設定するみたいです。使ったことないからよく分からん(汗)。設定も、こうしないとできなかったし。 std::vector の T0 と T1 って MSDN に書いてあるのかな。これは誤植というか、省略してる部分があるみたいです。それよりソースコードを読んだ方が分かりやすいと思うです。 MSDN の STL リファレンスは全体的に分かりにくい……。
 
・ std::string 内の配列を char * 型として取り出すには std::string::begin() を呼び出します。 std::string::data() は const char * を返すから、書き込みしたいときには std::string::begin() の方ですね。命名規則は KTL のポリシーを見るのが手っ取り早いかも。あとは「縦に長く、横に短く」が基本(爆)。 if や for のあとは必ずネストするし、引数の数が多いときは必ず複数行に分けるし。就職前研修で「 while ((input_char = getchar()) != '\n') 」ってコードが出てきたんだけど個人的にはこゆのも嫌い。わざわざ1行に詰め込まなくてもとか思うんだけど。
 
・んじゃ後半!
 
透明1ドットイメージ
透明1ドットイメージ
template< class _Tvalue >
class Ta
{
public:
    template< class __Tvalue >
    void func( const __Tvalue& _Value );
};

template< class _Tvalue >
template< class __Tvalue >
void Ta< _Tvalue >::func( const __Tvalue& _Value )
{
}
	
 
 ができないんで、(bcc はできた) 宣言部に直接実装してますが、醜くくて困ってます。
 それで、下請けの関数を呼び出すように(短くするため)しているんですが、直接書くのはやっぱりみにくいのかなぁ?一般的にはどうなんだろうかと思って質問しました。
 
 ほとんどROMばっかりですが、これからもよろしくお願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・それ前にも訊いてるっす(爆)。わての場合、クラステンプレートのメンバ関数は全部クラスの中で実装しちゃってます(爆)。その方がテンプレートらしいかなと思って。 KTL とかそうですな。まーこれは特別として、 VC6 のコンパイラを考えると、結局はメンバテンプレート自体使わない方向になっちゃうかなー。たとえばこれも VC6 じゃ使えないし。 VC6 は使わないことにするか、 VC6 に合わせるか……。
 
・でわまたっ!
透明1ドットイメージ
 
2000/11/15 (Wed)
・今日は会社の方に行って就職前研修を受けてきました。その模様は日記の方で<だからなぜこっちでせん(爆)。では今日はお便り紹介〜。
 
透明1ドットイメージ
透明1ドットイメージ
 うっす 尺八郎です
 
const char *str = std::string("oopps").c_str();
	
 
 ま、そう言うことで
透明1ドットイメージ
透明1ドットイメージ
 
・あー、こういうふうにしちゃうと領域がなくなっちゃってるから str に入ってるのが無効なポインタになっちゃってますね。これが昨日のの原因かもしんないってことですね。実際、動的確保するクラスってこういう使い方して問題になること多いかもしんない……。余談だけど、なんでどのライブラリの std::string::c_str() も「 '\0' を追加」の実装してないんだろう。まんま std::string::data() を呼んでるのもあるし……。
 
・ふたつめのお便り〜。
 
透明1ドットイメージ
透明1ドットイメージ
> std::string 内の配列を char * 型として取り出すには
> std::string::begin() を呼び出します。
 
 これはまずいと思います。
 実体がどうであれ、std::string::begin()が返すのはあくまでstd::string::iteratorであって、char*ではありません。char*として扱えるのは、operator*()を使用したときだけです。
#だから、std::string::begin()の戻り値をstd::copy()に渡すのはありだけど、
#std::strcpy()やstd::memcpyに使うのは駄目。
 
> 就職前研修で「 while ((input_char = getchar()) != '\n') 」って
> コードが出てきたんだけど個人的にはこゆのも嫌い。
> わざわざ1行に詰め込まなくてもとか思うんだけど。
 
 これは1行に書くべき代表的な例です。
 
while(1)
{
	char ch = getchar();
	if(ch == '\n')
		break;
	/* ... */
}
	
 

 
char ch;
while((ch = getchar()) != '\n')
{
	/* ... */
}
	
 
 では、どちらがループの終了条件を的確に表現しているか、という事です。
透明1ドットイメージ
透明1ドットイメージ
 
・う”、わて的には if で抜ける方が分かりやすい(爆)。確かにループとしては while の中に入れた方が分かりやすいんだけど、1行にいろんなもの詰め込むってのはやっぱどうもね。 関数呼んで戻り値格納して、比較して while に掛ける、とか考えると頭がこんがらがってしまう(汗)。って、よー考えたらアルゴリズム呼び出すときとかって1行に詰め込むこと多いな(爆)。やっぱ慣れなんかなー。
 
・「 operator*() 」で取得って std::string::iterator から * 1文字取得して & でアドレス取得ってことなんかな。これはこれで変な気が(汗)。これって std::string::iterator::operator*() が「値で返す実装」だったら動かないわけで、結局 std::string::iterator が char * ってことに依存してるよーな気が。で、 std::string で char * を取得したいときには結局どうしたらいいんでしょうねぇ(汗)。 API とかに渡したいし。それともそれはしちゃダメっていう設計思想なのかなぁ……。というわけでこんな物を作ってみたり。
 
class string_converter
{
	std::string &m_rcStr;
	char *m_pch;
public:
    string_converter( std::string &p_rcStr )
        : m_rcStr( p_rcStr )
    {
        m_pch = new char[ m_rcStr.size() ];
    }

    ~string_converter()
    {
        m_rcStr = m_pch;
        delete[] m_pch;
    }

    operator char *()
    {
        return m_pch;
    }
};

// 使用例
void use_string_converter()
{
    std::string str( 256, '\0' );
    strcpy( string_converter( str ), "AAAAA" );
    printf( "%s\n", str.data() );
}
	
 
・……単なるお遊びなんで使用しないように(爆)。
 
・でわまたっ!
 
 
(C)KAB-studio 2000 ALL RIGHTS RESERVED.