C言語基礎|文字列の表示

printf に頼らず、1文字ずつ描く! putchar で身につく「文字列走査の基本」

文字列は「まとめて表示」だけじゃない

文字列の表示といえば printf や puts が定番ですが、C言語らしさを味わうなら 1文字ずつ表示する方法もぜひ押さえておきたいところです。

なぜなら、C言語の文字列は「終端の \0 まで並んだ char の列」だからです。
つまり、先頭から順に見ていって、\0 が来たら終わり——この考え方が、表示にもそのまま使えます。

ここでは putchar を使って、文字列を自分の手で表示してみましょう。

文字列を putchar で表示する考え方

printf は まとめて表示してくれますが、putchar は 1文字だけを表示する関数です。
だから、文字列を表示したいなら、こう考えます。

  • i = 0 から始める
  • s[i] が \0 ではない間、s[i] を putchar で出す
  • i を増やして次へ

文字列走査と表示の流れ

図の説明

  • 文字列は \0 で終わるので、\0 を見つけたら表示終了
  • \0 自体は「終わりの目印」なので画面には出しません

サンプルプログラム

プロジェクト名:chap9-8-1 ソースファイル名:chap9-8-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

// putchar だけで文字列を表示する

#include <stdio.h>

// 文字列 s を表示(改行しない)
void put_string(const char s[])
{
    int i = 0;
    while (s[i])
        putchar(s[i++]);
}

int main(void)
{
    char word[128];

    printf("合言葉を入力してください:");
    scanf("%127s", word);

    printf("受け取った合言葉は【");
    put_string(word);
    printf("】です。\n");

    return 0;
}

実行例

合言葉を入力してください:Open
受け取った合言葉は【Open】です。

登場する命令の書式と「何をする命令か」

putchar の書式と役割

  • 書式
    int putchar(int c);
  • 何をする?
    1文字だけ標準出力に書き出します。
    文字は内部では数値として扱われるので、引数は int になっています。

while の書式と役割

  • 書式
    while (条件式) 文;
  • 何をする?
    条件式が真のあいだ、文を繰り返します。
    今回は s[i] が 0 ではない間だけ表示を続けるために使います。

scanf の書式と役割(今回の注意点つき)

  • 書式
    scanf(書式文字列, 格納先, ...);
  • 何をする?
    標準入力から読み取って、格納先に書き込みます。
    %s は空白までを文字列として読み込みます。
  • 今回のポイント
    word は配列なので、scanf の格納先に word を渡すときは & を付けません。
    さらに %127s のように長さを指定すると、配列あふれを避けやすいです。

printf の書式と役割

  • 書式
    printf(書式文字列, 実引数1, ...);
  • 何をする?
    書式に従って整形しながら表示します。
    今回は見た目を整えるための飾り(【 】や文)に使っています。

while (s[i]) が意味すること

C言語では、0 は偽、0以外は真として扱われます。
だから

while (s[i])

while (s[i] != '\0')

とほぼ同じ意味になります。

条件式の読み替え

書き方意味使いどころ
while (s[i])s[i] が 0 ではない間文字列走査でよく使う省略形
while (s[i] != '\0')s[i] が \0 ではない間意味を明示したいとき

表の説明
どちらも動きは同じです。最初は明示形でもOK、慣れてきたら省略形が自然に読めます。

put_string の動作を図で確認(\0 は出さない)

たとえば s が "CAT" なら、内部は次の並びです。

"CAT" の格納イメージと表示範囲

図の説明

  • putchar で表示するのは 'C' 'A' 'T'
  • '\0' は表示しない
  • '\0' を見つけたらループを止める

演習問題

演習9-6:特定の文字の出現回数を数える

文字列 s の中に、文字 c が含まれている個数を返す関数を作成せよ。
int str_chnum(const char s[], int c);

解答例

プロジェクト名:chap9-8-2 ソースファイル名:chap9-8-2.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int str_chnum(const char s[], int c)
{
    int i = 0;
    int count = 0;

    while (s[i]) {
        if (s[i] == c)
            count++;
        i++;
    }

    return count;
}

int main(void)
{
    char s[128];

    printf("文字列を入力してください:");
    scanf("%127s", s);

    printf("文字 a の個数は %d です。\n", str_chnum(s, 'a'));

    return 0;
}

解説

  • 走査の止めどころは \0
  • 1文字ずつ見て一致したら count を増やす
  • 文字列走査の基本練習にぴったりです

演習9-7:文字列を n 回連続して表示する

文字列 s を n 回だけ連続して表示する関数を作成せよ。
void put_stringn(const char s[], int n);

解答例

プロジェクト名:chap9-8-3 ソースファイル名:chap9-8-3.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

void put_string(const char s[])
{
    int i = 0;
    while (s[i])
        putchar(s[i++]);
}

void put_stringn(const char s[], int n)
{
    for (int k = 0; k < n; k++)
        put_string(s);
}

int main(void)
{
    char s[128];
    int n;

    printf("文字列:");
    scanf("%127s", s);

    printf("回数:");
    scanf("%d", &n);

    put_stringn(s, n);
    putchar('\n');

    return 0;
}

解説

  • 外側の for が「回数」
  • 内側(put_string)が「1回分の表示」
  • 役割分担すると見通しがよくなります。