#pragma twice

KAB-studio > プログラミング > #pragma twice > 208 Version 11.08 文字列クラスふたたび

#pragma twice 208 Version 11.08 文字列クラスふたたび

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

 Version 11.08
文字列クラスふたたび

ふたたび?
そう。前回は Version 5.22 ( No.087 ) で
そういえばそのときも配列とか CString とか使ったね
そのときも言ったけど、文字列を配列じゃなくクラスで操作すると、いろ
んなメリットがあります

・可変長だからサイズを気にしなくていい。
・便利な関数を使うことができる。
・演算子で操作できる。

対してデメリットは次のようなものがあります

・文字列を受け取るのが苦手。
・使えない環境もある。
・演算子を使うと間違った操作をすることがある。
・仕組みを知らないで使うと危険。

デメリットの方が多いじゃん!
そうなんだけど

・可変長だからサイズを気にしなくていい。

のメリットが計り知れないんです
なんで?
それはあとのお楽しみ
全然楽しみじゃないし……
とりあえず、今回は文字列クラスについて慣れておきます。復習も兼ねて

はーい
まずは普通に使ってみます

void UseCString()
{
    CString cStr;
    cStr = "あいうえお";
    TRACE( "%s\n", cStr );
    // あいうえお
}

今回、文字列クラスは CString を使います
他にもあるの?
うん、 std::string っていうのもあるんだけど、そっちはちょっと上級
者向けだから。で

    CString cStr;

で、 CString の変数 cStr を作ります。この中に文字列を入れられま

入れてるのが

    cStr = "あいうえお";

ってわけね。 = で入れられるのは便利よねー
それに

    TRACE( "%s\n", cStr );

というふうに、文字列として使えるところはすべてそのまま使えます
便利よね
で、これと同じ事を char の配列で試してみます
便利じゃない例ってわけね

void UseCharAry()
{
    char pch[256];
    strcpy( pch, "あいうえお" );
    TRACE( "%s\n", pch );
    // あいうえお
}

まず、 char の配列を作ります

    char pch[256];

当然、この配列には 256 文字以上は入りません
でも CString はそういうの関係なく入ります、と
そういうこと。それが CString のアドバンテージのひとつ。次に

    strcpy( pch, "あいうえお" );

と、文字列を入れる時にはランタイムを使わなくちゃいけません
 CString なら = で簡単にできる、と
まぁ最後の TRACE() で出力は同じようにできるってことで
たったこれだけで見ると CString の方がむっちゃ便利よねー
じゃあ苦手な方もしておこうか。まず、普通に文字列を受け取ることがで
きません

void UseCStringForRecieveBad()
{
    CString cStr;
    strcpy( cStr, "あいうえお" );
    TRACE( "%s\n", cStr );
}

あ、エラーだ

error C2664: 'strcpy' : 
 1 番目の引数を 'class CString' から 'char *' に変換できません。
 この変換を実行可能なユーザー定義変換演算子がないか、
 または演算子を呼び出せません。

なんでこうなるかっていうと、 strcpy() の型がこうなってるから

 char *strcpy( char *string1, const char *string2 );

1番目の引数は char * 、2番目の引数は const char * 。で、 CString 
には const char * が来た時に自動的に中の文字列を渡す機能はあるんだけ
ど、 char * に対する機能はないんです
なんで?
だって

    CString cStr;

この時点で、中に入ってる文字列は空。配列で言えば、この中に入ってる
配列は

    char pch[0];

げ、これじゃ文字列受け取れないね
そういうこと。受け取るためには

    char pch[256];

って感じに領域を確保しなきゃいけないんです。そのためのメンバ関数が
CString::GetBuffer() と CString::ReleaseBuffer() です。というわけで
これを使って文字列を受け取ってみます

void UseCStringForRecieve()
{
    CString cStr;
    strcpy( cStr.GetBuffer( 256 ), "あいうえお" );
    cStr.ReleaseBuffer();
    TRACE( "%s\n", cStr );
    // あいうえお
}

お、ちょっと長いけど受け取れてる
 CString::GetBuffer() は、引数で渡されたサイズ分、文字列を置く領域
を確保します
つまり

    char pch[256];

ってするってことね
そういうこと。で、この戻り値の型は char * だから、これをそのまま渡
す事ができます
で、受け取れるわけね。そのあとの CString::ReleaseBuffer() ってなに
やってんの?
これは後始末。たとえば文字列のサイズの取り直しとか
文字列のサイズ?
 CString の中に持っている〈文字列サイズ〉を取得し直してるんです。
中に入ってる文字列が変わったわけだから、そういう情報も取り直さないと
いけないから
なるほどねー
で、これをもう一度見て欲しいんだけど

    strcpy( cStr.GetBuffer( 256 ), "あいうえお" );

文字列を受け取るために、中身を広げてるとこだね
でも、これって無駄なんです。サイズはわかってるんだから

void UseCStringForRecieveOptimizeSize()
{
    CString cStr;
    strcpy
        ( cStr.GetBuffer( strlen( "あいうえお" ) + 1 )
        , "あいうえお" 
        );
    cStr.ReleaseBuffer();
    TRACE( "%s\n", cStr );
    // あいうえお
}

 strlen() で文字列のサイズを取得……して、それ使って中身広げれば絶
対に受け取れるサイズになるってわけね。あれ? でもさ、同じ事を配列で
もすればいいんじゃないの?
ところが、これは配列では使えないんです

void UseCharAryBad()
{
    char pch[ strlen( "あいうえお" ) ];
    strcpy( pch, "あいうえお" );
    TRACE( "%s\n", pch );
}

あ、エラーだ

error C2057: 定数式が必要です。

配列のサイズは、コンパイルするときに判っていないといけないんです。
だから、プログラムの途中でサイズを変えたくても変えられないんです
でも CString はできてたよね
そう、もちろんその方法はあって、でもそれが面倒なんです。というわけ
で次回に続く!

/*
    Preview Next Story!
*/
 CString ってやっぱり便利ねー
でもそのためには仕組みを知らなくちゃ
知らなくちゃいけないの?
下手な使い方するとまずいことになるから
プログラミングってそういうの多いよね
でも、多い割には知られてない事も結構……

というわけで次回
< Version 11.09 メモリを動的に確保する >
につづく!
というわけでやっぱり仕組みを勉強してもらいます
やっぱり面倒そう……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。