#pragma twice

KAB-studio > プログラミング > #pragma twice > 071 Version 5.06 文字列とポインタ

#pragma twice 071 Version 5.06 文字列とポインタ

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

 Version 5.06
文字列とポインタ

まず、前回最後に見た
あたしが作った関数を見てみてみてーっ!!

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

どう、どうどう?
うん、悪くないよ。でももう少し良くできるかな?
良くできる?
たとえば、 chAry の中身って書き換えないでしょ
あー、そういえばそうね。文字の数数えるだけだもん
そういう場合は const にすれば、間違って書き換えることがなくなるか


    const char chAry[] = "ABC";

うお、 const が付くと難しそう!
 const char の配列、って考えれば大丈夫でしょ。 const char は?
 char の値変えられないの。ってことは、 chAry[0] とかがそれぞれ変え
られないってことだね
そうそう。 const にしておけば
書き換えようとしたらエラーになるんだもんね
そうそう。さらにもう一歩進めてみようか
もう一歩?
ここでは "ABC" って直接書いてるけど、これを関数の引数として受け取
るようにすると、他でも使えるようになるでしょ
他って?
ひとつのプログラムの中で、 ABC の長さだけ調べるってことはないでしょ。
プログラムのいろんな所から、いろんな文字列の長さを調べられるようにす
れば
それは便利だよね。んっと、引数でってことは……

void GetLengthWithIndex( const char p_chAry[] )

みたいな?
違うんだよねー。基本的に、配列は引数にできないって考えた方がいいか

どして?
呼び出すたびに、配列の長さが違うでしょ。配列ってそういうふうにフレ
キシブルに使えないんだよね
使いづらいってことなんだ
その代わりに、ポインタを使います。配列から [] を取ると?
ポインタになる!
だから

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

ってことができます
 const char の配列から [] を取ると const char のポインタになるんだ
ね。……あーっ!!
な、なに?
だから sizeof ダメって言ったんだ!!
そういうこと。文字列を関数に渡すときとかはポインタで渡すからね、
sizeof は使えないわけ
ほー。ってことは

void GetLengthWithIndex( const char *p_pch )

にすればいいのかな。で、中身の chAry を p_pch にすればいいんだね
そうそう
あ、でも待って! これじゃ

    GetLengthWithIndex( "ABC" );

ってできないじゃん!!
いや、これができるんだよね
へ?
この辺がややこしくて複雑なんだけど、 "" で囲んだ文字列って、 char 
のポインタ型なんだわ
あ、だからこれもOKなの?
そう、さらにこれもOK

void StringPointer()
{
    const char *pch = "ABC";
    TRACE( "%s\n", pch );
    // ABC
}

ええっ!? な、なんか変くない? だってさ、配列の時は、配列の char
ひとつひとつに文字入れたけど、これだと、どっかにある "ABC" ってポイ
ンタ使うだけだから、なんか……
うん、言いたいことは分かるよ。これは "ABC" がどうなってるか、が鍵
うん、どーなってるの?
 "" で囲んだ文字列とか、直に書いた 100 みたいな数字とかを〈リテラル〉
って言います
あ、 Ver 4.09 ( No.059 ) でやったね
リテラルもコンピューター世界のものだから、当然メモリに置かれるで
しょ。 "ABC" も、そんな感じにメモリ上に置いてあるわけ
だからアドレスもあるから、そのポインタもあるってことなんだ!
そういうこと。しかーし! これはダメ

void ArrayToPointerBad()
{
    const char *pch = "ABC";
    const char chAry[] = pch;
    // error C2440: 
    // 'initializing' : 'const char *' から 'const char []' 
    // 変換することはできません。
    // この変換が可能なコンテキストはありません。
}

ええっ!? だって "ABC" はポインタなんでしょ?
複雑でしょう。さっきも言ったけど、配列ってフレキシブルにできてない
んだよね。配列のサイズを決めるときに、 "ABC" だと4つって決められる
んだけど
ポインタだと決められない?
そ。この辺はコンパイラとかのこと知らないと分かんないよね
ってゆーかコンパイラ知らない
だね。この辺も、ポインタ難しいって言われる原因かな
この前水希ちゃんも言ってたけど、結局配列が難しいんだよね
そういうことになるかも。ま、先に進むと配列使うこと少なくなるし。話
を戻すと?
あ、関数作ってる途中だったんだよね。結局、引数はポインタにすればい
いんだよね
そうそう。あともうひとつ変える部分。文字数を TRACE() でアウトプッ
トに出してるけど、これを戻り値として返すとすると?
すると

int GetLengthWithIndex( const char *p_pch )

みたいになるんだよね。そうなると……

int GetLengthWithIndexNew( const char *p_pch )
{
    for( int iNo = 0; ; ++iNo )
    {
        if( p_pch[iNo] == '\0' )
        {
            break;
        }
    }

    return iNo;
}

って感じになって、使うと……

void UseGetLengthWithIndexNew()
{
    TRACE( "%d\n", GetLengthWithIndexNew( "ABC" ) );
    // 3
}

おお、なんかうまくいった!
これで、 GetLengthWithIndexNew() は〈文字列の長さ〉を調べる関数に
なったから、何か他の所から使いたい場合でも
これ呼び出せば文字列の長さ分かるんだ。 "ABC" とかやってたらそーゆー
のダメだったもんねー
こんな感じに、外からデータを受け取って、中で処理して、結果を返す
文字列受け取って、長さを返す
そういうのが関数の一番基本的な形式。こういうふうに、関数の〈入力〉
と〈出力〉を考える事を〈設計〉って言います
設計、なんか建築用語みたい
実際そんな感じだね。今回は引数少ないからいいんだけど、引数が増えて
くると、どういう風に引数を取るかとかが結構重要
どんなふーに?
それはまた今度
ぶー
そういう、関数の外の面に対して、中の部分を〈実装〉って言います。最
近は英語で〈インプリメント〉って言う方が多いかも
あの宇宙人がやってくってゆー

いや、なんでもないっす。で、設計と実装って別々なの?
それが理想。まず関数やクラスの設計だけして、そのあとその中身を実装
する、っていうのが理想的な方法だね
確かに家作るときってそう作るよね……
ちなみに、中の実装を〈プログラミング〉じゃなく〈コーディング〉って
呼んだりします
あ、コーディングって良く聞く言葉! つまり関数の中身書くことをコー
ディングって言うんだ
一応ね
一応?
なんかプログラム書くこと、つまりプログラミング=コーディングって使
われてることもしばしば
じゃー意味ないじゃん
音的に、プログラミングよりコーディングの方がかっこいいってことなの
かなぁ
さて!
今火美ちゃんは、関数を作ったわけだ。でも、関数を作る上で最も重要な
ことがあります!
最も重要なこと!? そ、それは?
もう誰かが作っているのなら、自分は作らないこと
へ?
これを見て

void ReplaceTo_strlen()
{
    TRACE( "%d\n", strlen( "ABC" ) );
    // 3
}

……ああっ、 strlen() ってなに? これがあるからあたしの関数は要ら
ないの!?
というわけでつづく!

/*
    Preview Next Story!
*/
あ”あ”〜、私の苦労はいったい!?
でもその苦労は無駄にはならないよ
けっ、そんな気休め要らないわい!
そうじゃなくって、ちゃんと勉強になる苦労をさせてあげたんだよ
そ、そなの?
というわけで次回
< Version 5.07 C ランタイムライブラリ >
につづく!
僕なんか、どれだけ意味のない苦労をさせられてきたか……
はいはい、ありがとうねー、もう……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。