strlenを自作する

文字列の終わりは誰が決めているか

第2章では、malloc で確保した領域が「何バイトあるか」を自分で覚えておく必要がありました。ところが文字列だけは事情が違います。char の並びの最後に ヌル文字 '\0' という番人が置かれていて、長さを覚えていなくても終わりが分かるようになっています。

char name[7] = "Tanaka";

この配列の中身は 'T' 'a' 'n' 'a' 'k' 'a' '\0' の7バイトです。見えている文字は6つですが、必ず1バイト余分に要ります。要素数を7ではなく6と書くと終端が入らず、文字列として扱った瞬間にどこまでも読み続けてしまいます。

'\0' は数値としては 0 です。'0'(ゼロという文字、値は48)とは別物なので、比べるときに書き間違えると条件が一生成立しません。

strlen は数えているだけ

strlen は長さをどこかに保存しているわけではありません。呼ばれるたびに先頭から '\0' が出るまで1バイトずつ歩いて、歩数を返しています。だから同じ文字列に対して何度も呼べば、そのたびに走査が走ります。

自分で書くと次のようになります。

int my_strlen(const char *s) { int n = 0; while (*s != '\0') { n++; s++; } return n; }

第1章でやったポインタの歩き方がそのまま出てきます。s++ で1文字ぶん進み、*s でそこの1バイトを見ています。char は1バイトなので、s++ は素直に隣の番地へ移ります。

引数に付いている const は「この関数は指す先を書き換えません」という宣言です。呼ぶ側から見ると、渡した文字列が壊されない保証になります。読むだけの引数には付ける習慣を付けておくと、あとで自分を助けます。

戻り値が '\0' を含まない意味

my_strlen("Tanaka") は 6 を返します。終端の1バイトは数に入りません。この「見えている文字数」と「必要なバイト数」が1ずれることが、このあとの回でずっと効いてきます。文字列をコピーする器を用意するときは strlen + 1 バイト要る、と体に入れておいてください。

なお、ここで扱う名前はアルファベットに限ります。日本語の文字は1文字が複数バイトになるので、strlen が返すのは文字数ではなくバイト数になります。この違いは今は脇に置いて、1文字1バイトの世界で仕組みを掴みます。

では、自作の my_strlen を書いて、純正の strlen と同じ答えになるか確かめてみましょう。

要件

  1. my_strlen という関数を自分で書く。引数は const char *、戻り値は int
  2. 添字 [] ではなくポインタを進める形で走査する
  3. 1行目に 自作の結果は6です の形で表示する
  4. 2行目に strlenの結果は6です の形で表示する

入出力例

main("Tanaka") → "自作の結果は6です strlenの結果は6です" main("Ito") → "自作の結果は3です strlenの結果は3です" main("Yamamotokurosawa") → "自作の結果は16です strlenの結果は16です"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.c
学習モード

メモ

strlenを自作する

⌘S で保存