#pragma twice

KAB-studio > プログラミング > #pragma twice > 070 Version 5.05 配列と文字列

#pragma twice 070 Version 5.05 配列と文字列

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

 Version 5.05
配列と文字列

前回は文字と文字列について見てきました
よーするに文字は数字で、 char 変数の中に1文字ずつ入るのよね
で、文字列はその char の配列
そうそう
さて、まず最初は TRACE() で文字列全体を表示する方法
あ、そういえばまだだよね。文字一個は %c だったけど
文字列の時は %s にします。そうすれば変数を〈文字列だ〉って見なして
くれるから

void StringArray()
{
    char chAry[] = "ABC";
    TRACE( "%s\n", chAry );
    // ABC
}

あら簡単
さて問題です!!
げげ!!
これ、 %s じゃなく %c だけで文字列全体を表示するとしたら、どうすれ
ばいいと思う?
え? それって前回やったじゃん

void CharsArray()
{
    char chAry[] = "ABC";
    TRACE( "%c, %c, %c\n", chAry[0], chAry[1], chAry[2] );
    // A, B, C
}

でもこれじゃ、 chAry が3文字入ってるときしかうまく働かないでしょ
あ、そっか。つまり、 chAry の中に何文字入ってるか分かればいいんだ
よね。だったら sizeof で
 sizeof は不可
ええっ、なんでぇ!?
前に言ったでしょ、 sizeof じゃ、ポインタから配列の要素数を調べるこ
とはできないって。配列じゃなく、ポインタが渡された場合って事で
なんかずるいー
後になればなんでか分かるから。じゃあ代わりにヒント

41 42 43 00 8C F5 64 00 E2 19 40 00 2C F8 64 00 C0 01 52 00  ABC....

これもこの前の、文字列の入ってるメモリ見たのじゃない
この他にも、 A や AB 、 ABCD で見てみると……

41 00 CC CC 8C F5 64 00 E2 19 40 00 2C F8 64 00 C0 01 52 00  A......  
41 42 00 CC 8C F5 64 00 E2 19 40 00 2C F8 64 00 C0 01 52 00  AB.....
41 42 43 00 8C F5 64 00 E2 19 40 00 2C F8 64 00 C0 01 52 00  ABC....
41 42 43 44 00 CC CC CC 8C F5 64 00 E2 19 40 00 2C F8 64 00  ABCD...

文字列のすぐ後の数字が……
あ、全部 00 になってる!!
そのとーり!! じゃ、この関数を試してみて

void StringSize()
{
    char chAry[] = "ABC";
    TRACE( "%X, %X, %X, %X\n", chAry[0], chAry[1], chAry[2], chAry[3] );
    // 41, 42, 43, 0

    TRACE( "%d\n", sizeof( chAry ) );
    // 4
}

最初の TRACE() は、さっきのメモリ見たのと同じのだよね。2番目は、
あ、 sizeof 使っちゃいけないって言ってたのに使ってる!!
あーもう、ここだけだから! で、どうなってる?
4。って、なんで!? そいや、この前もそんなこと言ってたね
メモリで見たでしょ、 00 
うん、最初の TRACE() でも4番目の要素に0入ってるね
つまり!
つまり?
 "ABC" って感じに文字列をダブルコーテーションで囲むと、その最後に
値が0の文字が自動的に追加されるってこと
自動的に追加?
そう。この関数見てみて

void NullChar()
{
    char chAry[] = "";
    TRACE( "%X\n", chAry[0] );
    // 0
    TRACE( "%d\n", sizeof( chAry ) );
    // 1
}

うわ、 "" なのにサイズが1個ちゃんとある! カラじゃないんだ。で、
そんなかに0が……
そう、だから3文字でも要素数は4個になるわけ。この、値が0の文字を
〈終端文字〉とか〈 NULL 文字〉とか言います
はて、どっかで聞いたような……
ちなみにこの終端文字は \0 って書きます
あ、なんだか \n みたい
そう、 \0 も \n もれっきとした文字。もちろん値でもあるし
 '\0' は0ってことだよね。 '\n' は?
 0x0A だから10進数だと10だね。調べればすぐ判るよ
 TRACE() で %X とか %d ですればいいんだよね
そうそう。で、 \0 って何のためにあるか分かる?
んー……もしかして、これで sizeof 使わないで文字列の長さが分かるっ
てこと?
そういうこと。そのために自動的に追加されるんです
でもどうやって?
配列の要素を先頭からひとつずつ調べていけば分かるでしょ
あー、うーん、分かりそうな気もするけど……
そだね、考えながら作っていこうか。まずは雛形

void GetLengthWithIndex()
{
    char chAry[] = "ABC";

    // ここを作る。

    TRACE( "%d\n", /* 要素数の入った変数 */ );
    // 3
}

うん、で、配列の各要素を調べるんだよね
とりあえず1番目の要素に固定して考えようか
1番目の要素が '\0' かどうか調べるんだから、えーっと…… if だ!
そう、値が同じかどうか調べるのは if 。詳しくは Ver 2.8 ( No.019 )
を見てください
ってことは……

    if( chAry[0] == '\0' )
    {
        TRACE( "0文字だよ!\n" );
    }

そうそう、そんな感じ
……でもこっから先が……
各要素を調べるんだから、 chAry[0] だけじゃなく chAry[1] や chAry[2] 
も調べればいいんでしょ
……

    else if( chAry[1] == '\0' )
    {
        TRACE( "1文字だよ!\n" );
    }
    else if( chAry[2] == '\0' )
    {
        TRACE( "2文字だよ!\n" );
    }
    // ずっと続く……。

んなわけないやん! ははっ!!
いや、それほど遠くないよ
え”、そうなの?
つまりさ、 chAry の要素指定が0から1ずつ増えていって、増えるたびに 
if でチェックするんでしょ? 前にそういうのやったでしょ
今調べるっ!! …… for ?
そう。 Ver 2.9 ( No.020 ) でやったでしょ
あ、 if の次の回だ……えーっと、 for ってこんな感じだよね

    for( int iBox = 1; iBox < 6; ++iBox )
    {
        TRACE( "%d ", iBox );
    }

ここで増やしたいのは、 chAry の要素の番号だよね。この番号の変数の
名前を iNo にすると

    for( int iNo = 0;

続ける条件は……あれ? これはどうすればいいのかな
この for は配列を先頭から調べていって、0が入ってたら止めるように
するんでしょ
あ、そっか。あれ、でもそれってさっきの if と同じじゃん
そう。だからここは if に任せることにして、ここは空白にしましょう
く、空白ぅ!? そんなことできるの?
できるよ。ただ、チェックされないから、他で for から抜けるようにし
ないと
 for の中回りっぱなし……それって無限ループってヤツよね
そうそう。逆に言うと、その抜けるのはどこですればいいと思う?
あ、 if のとこですればいいんだ!
そういうこと。その辺をイメージできるようにね
ほーい。で、最後は1ずつ増やすんだから普通に ++ 使えばいい、から

    for( int iNo = 0; ; ++iNo )
    {
    }

って感じかな
その中に無理矢理さっきの if を入れて、整形すれば
んじゃぼちゃんっ

    for( int iNo = 0; ; ++iNo )
    {
    if( chAry[0] == '\0' )
    {
        TRACE( "0文字だよ!\n" );
    }
    }

中カッコが増えたらインデントね。見やすくなるから
インデントって最初のタブのことだよね。あと、 chAry の要素の番号を 
0 から iNo に変えて、あとは TRACE() を……そう、 for から抜けるのに
すればいいんだよね
何使えばいいか分かる?
ちょっと調べる……あ、 Ver 2.9 に出てた。 break 使うんだ。だから
関数全体で見ると

void GetLengthWithIndex()
{
    char chAry[] = "ABC";
    for( int iNo = 0; ; ++iNo )
    {
        if( chAry[iNo] == '\0' )
        {
            break;
        }
    }
    TRACE( "%d\n", iNo );
    // 3
}

ビルドして実行、うわ、ちゃんと3になる! 文字数変えても大丈夫!
こういうふうにすれば、文字列の長さが判るわけ

/*
    Preview Next Story!
*/
あー、なんか今日はちゃんとしたプログラム組んだって感じ!
教えなきゃかなりわかんなかったっぽいけど
ウルサイわねー、水希ちゃんが参考書代わりだからいーの
さ、参考書代わり……
というわけで次回
< Version 5.06 文字列とポインタ >
につづく!
未来のロボット家庭教師とかこんな感じだろうしー
火美ちゃんに言われるとなんかムカツク……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。