★文字と文字列(文字列3)★


そろそろプログラムを考えてもらいましょう。

文字列に関するプログラムも色々ありますが、これまでに「文字」「文字列」で説明したことを全て思い出して作ってみてください。

※なお、scanfを使う時は「scanf("%s", str);」のように使います。


では、枠組みを書きます。

<sample program 083-00>

#include <stdio.h>

#define MAX_STRING 10

int main(void)
{
    char str[MAX_STRING];

    int length;

    scanf("%s", str);
    
    /* ここにプログラムを追加する */

    printf("length = %d\n", length);

    return 0;
}

これを元に、入力した文字数を数えるプログラムを作ってください。

length とは「長さ」という意味ですが、「文字列の文字数」という意味でよく使われる単語です。

string 自体が「ひも」という意味なので「長さ」という表現が使われているのでしょう。

完成後のプログラムの実行結果はこの通りです。

<実行結果>

ABC    ←scanfの入力
length = 3
続行するには何かキーを押してください・・・

新しい変数を追加したりすることも問題ありません。

とりあえずはノーヒントでやってみましょうか。









































ヒントです。


何文字入っているかは配列を調べることで分かります。

「文字列」の最後に必ず入っているモノを思い出してください。









































解答例です。


<sample program 083-01>

#include <stdio.h>

#define MAX_STRING 10

int main(void)
{
    char str[MAX_STRING];

    int length;

    int i;

    scanf("%s", str);

    length = 0;

    for (i = 0; i < MAX_STRING; i++) {
        
        if (str[i] == '\0') {
            break;
        }

        length++;
    }

    printf("length = %d\n", length);

    return 0;
}

<実行結果>

ABC    ←scanfの入力
length = 3
続行するには何かキーを押してください・・・

やり方は色々ありますが、今回は次のように考えました。

配列を順番に調べなければなりませんでしたので、変数iを用意して

for (i = 0; i < MAX_STRING; i++) {

}

このようなループを作りました。

また、length に文字数を入れるためカウンターのように扱うことにしました。

0で初期化し、1ずつカウントアップします。

後は配列の中身が文字かどうかという判断なのですが、「文字列」の最後にはヌル文字が入っています。

ヌル文字はC言語のエスケープシーケンスで書くと「'\0'」です。

配列の中身を先頭から順番に調べ、ヌル文字であれば調べるのを止め、ヌル文字でなければ length を1増やします。

これで入力した「文字数」を知ることが出来ました。


少し改良を加えます。

上の繰り返しの条件は、変数iがMAX_STRINGより小さい間繰り返す、です。

しかし、どこかに必ずヌル文字が入っているはずですから、下のように変えることも出来ます。

<sample program 083-02>

#include <stdio.h>

#define MAX_STRING 10

int main(void)
{
    char str[MAX_STRING];

    int length;

    int i;

    scanf("%s", str);

    length = 0;

    for (i = 0; str[i] != '\0'; i++) {
        length++;
    }

    printf("length = %d\n", length);

    return 0;
}

<実行結果>

ABCD    ←scanfの入力
length = 4
続行するには何かキーを押してください・・・

繰り返しの条件を、配列strのi番目がヌル文字では無い間繰り返す、に変えました。

break文が無くても、繰り返し条件が不成立(strのi番目がヌル文字)になればループを終了します。


もう少し深く考えてみます。

scanfでの文字列入力後の配列は↓のようになっています。

str  0 1 2 3 4 5 6 7 8 9
  +−+−+−+−+−+−+−+−+−+−+
  | A| B| C|\0|不|不|不|不|不|不|
  +−+−+−+−+−+−+−+−+−+−+
  ※不:不定

入力文字数は3ですから、配列の3番目に「'\0'」が入るはずです。

ということは、ヌル文字が入っている「添え字」が分かれば「文字数」が分かります。

配列の時にやった「線形探索」を覚えていますか?

配列の先頭から順番にヌル文字があるかどうか調べればよい訳です。

ヌル文字が発見された時の添え字が「文字数」になります。


上記のことを踏まえ、さらに改良を加えたプログラムが↓です。

<sample program 083-03>

#include <stdio.h>

#define MAX_STRING 10

int main(void)
{
    char str[MAX_STRING];

    int i;

    scanf("%s", str);

    for (i = 0; str[i] != '\0'; i++) {
    }

    printf("length = %d\n", i);

    return 0;
}

<実行結果>

ABCD    ←scanfの入力
length = 4
続行するには何かキーを押してください・・・

配列の「添え字」は変数iがカウントしていますので、ヌル文字が見つかった時のiがそのまま「文字数」になります。

for文で配列のi番目がヌル文字では無い間繰り返していますが、探索と考えるとヌル文字が見つかったら繰り返しを終わるということです。

「添え字」に使っていた変数iが「文字数」も表しているため、変数lengthは不要になりました。

そのため、for文の中身は空っぽになってしまいました。

空のfor文は↓のように書くこともありますので、覚えておいてください。

/* 書き方1 */

for (i = 0; str[i] != '\0'; i++);

/* 書き方2 */

for (i = 0; str[i] != '\0'; i++)
    ;

セミコロンの位置が違うだけですが、個人的には<書き方2>の方が見間違いが少なくなると感じています。


3つの例を書きましたが、色々な作り方があるということを再度認識しておいてください。

1つの方法だけ知っているのと、複数の方法を知っているのではプログラムの幅が違ってきます。

次回は文字列のコピーに挑戦しましょう。


次へ

戻る

目次へ