#pragma twice

KAB-studio > プログラミング > #pragma twice > 085 Version 5.20 ファイル読み込みをさらにブラッシュアップ!

#pragma twice 085 Version 5.20 ファイル読み込みをさらにブラッシュアップ!

前のページへ 表紙・目次へ 次のページへ

 Version 5.20
ファイル読み込みをさらにブラッシュアップ!

前回までで、 CFileTestDlg::OnBtnShow() はこんな感じになってます

void CFileTestDlg::OnBtnShow() 
{
    m_cDataLstBox.ResetContent();

    int i;
    std::ifstream cIFStrm;
    cIFStrm.open( "_Data.txt" );
    if( cIFStrm.fail() )
    {
        CString cStr;
        cStr.LoadString( IDS_E_NOFILE );
        const int iIDOffset = 1000;
        CString cStrCap;
        cStrCap.LoadString( IDS_E_NOFILE + iIDOffset );
        MessageBox
            ( cStr, cStrCap
            , MB_OK | MB_ICONEXCLAMATION );
        return;
    }

    while( !cIFStrm.eof() )
    {
        cIFStrm
            >> i;
        if( cIFStrm.fail() )
        {
            TRACE( "整数値じゃないです\n" );
            return;
        }
        char chDest[256];
        sprintf( chDest, "%d", i );
        m_cDataLstBox.AddString( chDest );
    }
}

今はファイル読み込みの所のエラー処理をしてるんだよね
そうです。でもちょっと下の方見てみて。こっちでもエラー処理してるで
しょ
あ、ホントだ、 TRACE() でエラー出してるね
ここにも同じコードを書くのは無駄だから、エラー処理を外のメンバ関数
として作ることにします。他の部分でもエラー処理が必要になるかもしれな
いしね
へー、そういうことできるんだ
同じ部分は関数にまとめる、それが基本。プログラムがすっきりして見や
すくなるし、間違いを直すのも1ヶ所だけで済むからね
そりゃそうよねー、同じとこいっぱいあったら全部直さなきゃ行けないも
んね
ではまず、メンバ関数を作ってみましょう。今までは〈あるイベントに対
応するメンバ関数〉しか作ってこなかったけど
 CFileTestDlg::OnBtnShow() がそうだね
もちろん普通のメンバ関数も作れます。ワークスペースの【Class View】
を見て
ワークスペースってリソースとかソースファイルとか色々載ってるのだよ
ね。そのクラスのっと
 CAboutDlg とか CFileTestApp とかあるでしょ
 CFileTestDlg もね。このクラスにメンバ関数付けるんだよね
そう、 CFileTestDlg::OnBtnShow() から呼び出すから同じクラスにしま
す。この【Class View】で CFileTestDlg を右クリックして、メニューか
ら【メンバ関数の追加】を選んで
ダイアログ出たよ
【関数の型】はメンバ関数の戻り値のこと
 void でいい?
ホントはこういうのはちゃんと考えなきゃいけないんだけど、考えたくな
い時は bool で
なんで?
ちょっとエラーを返したい時とかに便利だから
あー
【関数の宣言】はメンバ関数の名前と引数。こんな感じにして

    MessageError( unsigned int p_puiID )

 unsigned int の引数?
 IDS_E_NOFILE とかの ID を引数に渡すから
あー
 unsigned なのは ID だから。 ID は符号なしだからね
他は?
【アクセス制御】は Private にしといて。これはちょっと難しいから説
明は結構あとで。これで完了
んじゃ OK っと
こんなのが CFileTestDlg::OnBtnShow() の下にできたと思うよ

bool CFileTestDlg::MessageError(unsigned int p_puiID)
{

}

おおっ、メンバ関数!
ではさっきのエラー処理の部分を書き込んで、ちょっと手直ししてこんな
感じに

bool CFileTestDlg::MessageError(unsigned int p_puiID)
{
    const unsigned int iIDOffset = 1000;
    CString cStr;
    cStr.LoadString( p_puiID );
    CString cStrCap;
    cStrCap.LoadString( p_puiID + iIDOffset );
    MessageBox
        ( cStr, cStrCap
        , MB_OK | MB_ICONEXCLAMATION );
    return true;
}

えーっと、違うところは…… iIDOffset 作ってるとこが最初に来てるね
別に最初じゃなくてもいいんだけど、これは気分で
その方が見やすいもんね。あと CString::LoadString() に渡してるのが
IDS_E_NOFILE から p_puiID になってるね
つまり引数として渡された値を ID としてエラーメッセージを取り出すっ
てこと。そして、呼び出す側はこうなります

    if( cIFStrm.fail() )
    {
        MessageError( IDS_E_NOFILE );
        return;
    }

うおすっきり!
とりあえず試してみて
ビルドして実行して【表示】ボタン! うんちゃんとさっきと同じダイア
ログが出た
こういうふうに関数にまとめるの、めんどくさがっちゃダメだからね
分かってるよー、後から直すときとか大変なんだもんね。次は?
じゃ、後半の while に移ろうか。まず

            TRACE( "整数値じゃないです\n" );

を今の関数に置き換えちゃおうか
そだねー。えーっと、まずストリングテーブルに追加しないと

IDS_E_NONINT=202 : 整数値じゃないです
IDS_E_NONINT_C=1202 : 整数値じゃないです

でいい?
うーん…… IDS_E_NONINT の方は〈ファイル中に整数値以外のデータが含
まれています。\nファイルを確認してください〉の方がいいかな
あ、複数行 OK なんだ。改行には \n を使うんだね
直接書き込むときには、改行は
リターンキー押すとダイアログが消えちゃう!
から、 Ctrl キーを押しながらリターンキーを押せば
改行された!
これでも改行できるし、 \n でもできるから
じゃー前回の〈ファイルがありません〉もそうした方がいいかな
そうだね、だからまとめると

IDS_E_NOFILE=201
 : ファイルが見つかりませんでした。
 \nファイル名を確認してください。
IDS_E_NOFILE_C=1201 : ファイルがありません
IDS_E_NONINT=202
 : ファイル中に整数値以外のデータが含まれています。
 \nファイルを確認してください
IDS_E_NONINT_C=1202 : 整数値じゃありません

ってとこかな。まー実際、この文だけじゃ分かりにくいんだけどね、使っ
てる側からすれば
そだね、なんかでフォローしないと
じゃ、呼び出す部分は?
 ID を変えればいいだけだから

            MessageError( IDS_E_NONINT );

だね。じゃ、今回最後は char chDest[256] について。そうだね、とりあ
えず試してみようか。 while のあとに次の行追加して

    } // while の区間を閉じる中カッコ。
    TRACE( "%s\n", chDest );  // この行を追加。
} // CFileTestDlg::OnBtnShow() を閉じる中カッコ。

あ、 chDest を表示するのだね。んじゃビルドして

error C2065: 'chDest' : 定義されていない識別子です。

げ! エラーになっちゃった
 chDest って while の中で宣言してるでしょ。実は、この chDest の寿
命はこの while のあとの中カッコの中だけなんです
どゆこと?
 Ver 4.13 ( No.063 ) で〈変数の寿命〉を教えたでしょ
うん、関数抜けたら変数がなくなっちゃうってゆーの
実は、正確に言うと〈関数から抜けたら〉じゃないんです
え、そうだったの?
正確には〈対応する { と } から抜けたら〉
だから while の中カッコから抜けたら chDest がなくなってるんだ!
 { が複数回ある場合には、対応する } が来たら変数消える仕組み
つまり関数じゃなくて { } で考えればいいんだよね。っつーかインデン
トで考えればいいってゆーか
そだね、インデントする範囲って考えてもいいかも。ちなみに { } で囲
まれた区域を【ネスト】っていいます
ねすと?
〈何かの中に何かを入れる〉っていう意味。 while とか for とかのも、
ネストだからね
そういえば〈ネストが深い〉とかよくゆーもんね
もひとつ用語言うと、変数が生きてる範囲を【スコープ】っていいます
すこーぷ? あの銃とかに付いてる
それボケじゃなくて当たり。上の例で chDest がなくなっちゃってたら使
えないでしょ
うん使えない
ってことは〈見えない〉
あー、そういう意味でスコープなんだ。あ、それって、他の関数から変数
使えないのと同じ?
そう同じ。というわけで、ネストとスコープ、そして変数の寿命、その辺
を踏まえると、 chDest は while の前で宣言した方がいいことになるよね
どーして?
それは宿題
げげ!

/*
    Preview Next Story!
*/
宿題ってゆーより、スペースがたんなくなったんでしょ
っていうか、ブラッシュアップでこんなに量がかかるなんて
でもさ、この前も言ってたけど、こういうの本に載ってないよね
なんだよね、絶対必要な技術だと思うんだけど……
というわけで次回
< Version 5.21 ファイル読み込みをさらにさらにブラッシュアップ! >
につづく!
もしかしてほとんどのプログラマーはこゆことしてないんじゃない?
あ、ありうる……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。