文字列関数
毎回自分でループを書かなくていい
前回は終端記号に当たるまで添字を進めて、文字数を自分で数えました。よく使う操作は標準ライブラリにそろっているので、実際には自分で書きません。文字列を扱う関数は string.h にまとまっています。
#include <stdio.h>
#include <string.h>この章で覚えるのは3つだけです。長さを測る strlen、コピーする strcpy、比べる strcmp です。
strlen は終端記号を数えない
char name[20] = "Sato";
printf("%d\n", (int)strlen(name)); // 4strlen が返すのは、終端記号の手前までの文字数です。ですから "Sato" なら 4 で、確保した箱の数である 20 ではありません。中身の長さと箱の大きさは別物という区別が、C の文字列でいちばん大事なところです。
戻り値の型は int ではなく size_t という符号なしの型なので、%d で出すときは (int) を付けて int に直します。第2章でやったキャストです。
strcpy は = の代わり
配列に文字列を入れられるのは宣言のときだけで、あとから = で入れることはできません。
char name[20];
name = "Sato"; // これはコンパイルエラー
strcpy(name, "Sato"); // これが正しいstrcpy(コピー先, コピー元) の順で書きます。代入と同じで、左が受け取る側です。
危ないのは、コピー先の箱が足りない場合です。strcpy は入りきるかどうかを確かめずに、終端記号まで書き込み続けます。
char small[4];
strcpy(small, "Yamada"); // 4個の箱に7個ぶん書き込む。周りが壊れるコンパイルは通ってしまうので、コピー先の大きさは自分で保証するしかありません。
strcmp は同じなら0
文字列どうしを == で比べても、中身は比べられません。strcmp を使います。
if (strcmp(name1, name2) == 0) {
printf("同じ名前です\n");
}返ってくるのは「同じかどうか」の真偽ではなく、辞書順でどちらが先かを表す数です。同じなら 0、name1 のほうが辞書順で前なら負、後ろなら正になります。0 が「同じ」というのは直感に反するので、if (strcmp(a, b)) と書くと意味が反転してしまいます。必ず == 0 を付けてください。
負や正の値そのものは処理系によって違うことがあるので、大小を見たいときは < 0 と > 0 で判定します。
では、3つの関数を使ってみましょう。
要件
- string.h を include する
- Satoの文字数は4です の形で2人ぶん表示する
- 名前が同じなら 2つの名前は同じです、違うなら 2つの名前は違います と表示する
- name1 を backup にコピーして 控えはSatoです の形で表示する
入出力例
main("") → "Satoの文字数は4です
Suzukiの文字数は6です
2つの名前は違います
控えはSatoです"