#pragma twice

KAB-studio > プログラミング > #pragma twice > 248 Version 13.12 コレクションを使ってみよう

#pragma twice 248 Version 13.12 コレクションを使ってみよう

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

 Version 13.12
コレクションを使ってみよう

バリエーションの最後として、今回は配列以外のものを使ってみます
配列以外?
配列には〈サイズを変えられない〉〈サイズがわからない〉などのデメ
リットがあります。そこで、配列の機能を持ったクラスが作られました
それが配列以外のものってことね
そう。一般には【コレクション】って呼ばれます
コレクションって、集めるとかゆー意味の?
そのコレクション。コレクションには色々な種類があるんだけど、とりあ
えず MFC にある CString 専用コレクション CStringArray を紹介します

void Use_CStringArray()
{
    CStringArray cStrAry;
    cStrAry.Add( "CCC" );
    cStrAry.Add( "BBB" );
    cStrAry.Add( "AAA" );
    cStrAry.Add( "EEE" );
    cStrAry.Add( "DDD" );

    for( int iF1 = 0; iF1 < cStrAry.GetSize(); ++iF1 )
    {
        TRACE( "%s ", cStrAry.GetAt( iF1 ) );
    }
    TRACE( "\n" );
    // CCC BBB AAA EEE DDD 
}

 Add() ってメンバ関数で追加して、 GetSize() ってメンバ関数で数が取
得できるのね
このふたつが配列との違い、かな。データを削除することもできるから
で、 GetAt() でデータを取り出すわけね。この CStringArray を使う
と、ソートするときにいいことあるの?
あんまりない
え”
前も言ったように、ソートはサイズは変わらないから、データの追加や削
除は特に必要ないんです。サイズ取得が便利っていうくらいかな
じゃあ使う意味ないんじゃ……
でも、ソートを使う側は便利だと思うよ。 Version 13.10 ( No.246 ) の
この例と比べてみて

    const char *ppchAry[5];
    ppchAry[0] = "CCC";
    ppchAry[1] = "BBB";
    ppchAry[2] = "AAA";
    ppchAry[3] = "EEE";
    ppchAry[4] = "DDD";

 "CCC" とかは【文字列リテラル】、 Version 5.06 ( No.071 ) で説明し
たようにメモリ上に置かれた文字列。でも、普通ソートするのって普通の文
字列でしょ
そうだね
そうなると、数とかサイズ普通可変だから
 CString が使えて、しかも追加できる CStringArray の方が便利……
そういうこと。では、 CStringArray を使う場合のソートの例

// p_pchL > p_pchR なら true を、
// それ以外は false を返すようにしてください。
bool CompareTo( const char *p_pchL, const char *p_pchR )
{
    if( strcmp( p_pchL, p_pchR ) > 0 )
    {
        return true;
    }

    return false;
}

void DoBubbleSortToCStringArray( CStringArray &p_rcStrAry )
{
    // 入れ替え先のループです。
    for( int iOut = 0; iOut < p_rcStrAry.GetSize() - 1; iOut++ )
    {
        // 最後から先頭方向へのループです。
        // ただし入れ替え先までです。
        for( int iIn = p_rcStrAry.GetSize() - 1; iOut < iIn; iIn-- )
        {
            if( CompareTo
                    ( p_rcStrAry.GetAt( iIn - 1 )
                    , p_rcStrAry.GetAt( iIn )
                    )
                == true )
            {
                // 前の方が大きいので入れ替えます。
                CString cTempStr = p_rcStrAry.GetAt( iIn );
                p_rcStrAry.SetAt( iIn, p_rcStrAry.GetAt( iIn - 1 ) );
                p_rcStrAry.SetAt( iIn - 1, cTempStr );
            }
        }
    }
}

使用例はこんな感じ

void Use_DoBubbleSortToCStringArray()
{
    CStringArray cStrAry;
    cStrAry.Add( "CCC" );
    cStrAry.Add( "BBB" );
    cStrAry.Add( "AAA" );
    cStrAry.Add( "EEE" );
    cStrAry.Add( "DDD" );

    // ソートします。
    DoBubbleSortToCStringArray( cStrAry );

    for( int iF1 = 0; iF1 < cStrAry.GetSize(); ++iF1 )
    {
        TRACE( "%s ", cStrAry.GetAt( iF1 ) );
    }
    TRACE( "\n" );
    // AAA BBB CCC DDD EEE 
}

使用例はさっきとほとんど同じね
ソートの部分もほとんど同じ。違うところは、まず引数にサイズを渡して
ない点
サイズは GetSize() で取得できるんだものね
だから、ソートの部分もこう変わります

    // 入れ替え先のループです。
    for( int iOut = 0; iOut < p_rcStrAry.GetSize() - 1; iOut++ )
    {
        // 最後から先頭方向へのループです。
        // ただし入れ替え先までです。
        for( int iIn = p_rcStrAry.GetSize() - 1; iOut < iIn; iIn-- )
        {

あ、ここって変わらないはずなのに……
サイズの取得方法が変わったからね。やってることは一緒
うーん……
他も基本的には同じかな。比較関数も今までと同じだし
ん……質問!
はい火美ちゃん
入れ替える部分がよくわかんない

                CString cTempStr = p_rcStrAry.GetAt( iIn );
                p_rcStrAry.SetAt( iIn, p_rcStrAry.GetAt( iIn - 1 ) );
                p_rcStrAry.SetAt( iIn - 1, cTempStr );

基本的には、配列の時と同じ。 CStringArray::GetAt() でデータを取得
して、 CStringArray::SetAt() でデータをセット。 SetAt() は第1引数が
インデックスナンバー、第2引数がセットする値

                p_rcStrAry.SetAt( iIn, p_rcStrAry.GetAt( iIn - 1 ) );



                p_rcStrAry[iIn] = p_rcStrAry[iIn - 1];

が同じってこと
ちょっとややこしい……
それは言えるかも。ちなみに

                CString cTempStr = p_rcStrAry[iIn];
                p_rcStrAry[iIn] = p_rcStrAry[iIn - 1];
                p_rcStrAry[iIn - 1] = cTempStr;

でも、実はできちゃいます
え!? なんで配列みたいに [] が使えるの?
それは、演算子のオーバーロードをしてるから
あ、 Version 7.09 ( No.129 ) でやったやつ?
そう。 CStringArray は [] をオーバーロードしていて、配列のように
データを返してくれるんです
へー
まぁ実はそれだけじゃなくて、かなり複雑な仕組みだったりするんだけど

え?
まぁそれはまたの機会に
むー。あ、そうそう、もうひとつ質問!
はい火美ちゃん
これって、 CString のコピーしてるじゃない。ポインタのコピーしてな
いんだから重くなるんじゃない?
それはちょっと複雑な部分だね。まず、この処理では文字列のコピーは行
われていません
え、そうなの?
 CString から CString にコピーすると、中に持っている文字列ポインタ
だけをコピーするんです
ってことは同じ……? それって、ふたつの CString が同じ文字列ポイ
ンタを持つってこと? それじゃ、一方が文字列書き換えたらもう一方も書
き換わっちゃうんじゃない?
その辺はちゃんとしていて、文字列の中身が変えられる時には新しく文字
列領域を確保するから
一緒に書き換わることはないわけね……
そういうこと。 CStringArray の使い方はこんな感じかな
え? コレクションってこれだけ?
ううん、まだいっぱいあるよ。というわけで次回に続く!

/*
    Preview Next Story!
*/
文字列追加ってよくありそうだから、これは便利だよね
これを利用すればエディタとかも作れるかな
1行1要素みたいな?
そういうこと。次回のポインタ用のも使うと、さらに幅が広がるから
というわけで次回
< Version 13.13 ポインタ用コレクション >
につづく!
じゃあもう new しなくても大丈夫?
ううん、それは必要

 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。