第9回
制御構造と変数(5)~forとwhileに関するあれこれ

forとwhileの特別な書き方

forとwhileにはここまでに紹介した一般的な書き方の他にも、ちょっと特別な書き方があります。

for~複数の式を列挙する

forでは、続く( )の中に『初期設定・継続条件・再設定』を記述します。前回はそれぞれ単独の式だけを記述しましたが、これらには複数の式を記述しても構いません。その場合、初期設定と再設定では式を,で区切ります。継続条件では論理演算子の&&または||を使って、複数の条件式をつなぐことになります。

単独の式:for (i=0; i<10; i++) { ...
複数の式:for (i=0, j=200; (i<10) || (j>=100); i++, j-=10) {...
(a) (b) (c)
上のfor文では、(a)(b)(c)のところでそれぞれ以下のような設定を行っています。

(a)初期設定:iを0、jを200に設定。
(b)継続条件:iが10未満またはjが100以上である間処理を続ける。
(c)再設定:1回ループを終えるごとにiを1加算し、jから10を減算する。

while~継続条件の簡略記法

whileでは、続く( )の中に継続条件だけを記述しました。継続条件が真である間処理を続けるというシンプルな構造なので、( )内にはループを処理するうちにその結果が『真から偽へと変化する式』を書けばよいことになります。

前段で少し触れた、継続条件の簡略記法を紹介しておきましょう。

キーボード(標準入力)から1文字ずつ読み取って変数cに保存し、それをループ内で処理する場合、まず、以下のような書き方が思い浮かびます。
c = getchar();
while(c != EOF) { ...
       :
  c = getchar();
}

getcharは標準入力から1文字ずつ読み取る関数、EOFはEnd Of Fileの略でファイルの終端を示す記号定数です。標準入力では[Ctrl]+[Z](Ctrlキーを押したままZキーを押す)がこれにあたります。

上の式では、whileの継続条件で変数cの値を調べるため、whileループに入る前にまずc = getchar()として1文字取得し、さらにループの最後で次の繰り返しに備えてもう一度c = getchar()と、同じ処理を実行しています。

この冗長な書き方は、以下のように単純化できます。
while ((c = getchar()) != EOF) { ...
            (a)         (b)
まず(a)の箇所で変数cに1文字を受け取り、続いて(b)の箇所でそれがEOFかどうかを調べています。このように、whileで用いる継続条件には複数の式を記述して、ソースをシンプルにできます。

文字列の処理に便利

文字列から1文字ずつ切り出す処理ではEOFの代わりに終端のNULLを調べるため、以下のような書き方がよく用いられます。
char *p;
p = str;   /* ポインタpを文字列変数の先頭に */
while(*p) { ...

whileの継続条件では、文字列の先頭を示すポインタpの示す値(1文字)を調べるだけですが、この式は、*pの示す1文字が0(NULL)でなければ真、0(NULL)なら偽となるので、継続条件として『文字列が終端のNULLになるまで繰り返す』という意味になるのです。

この書き方を使って、入力された文字列(間にスペースやタブを挟まない、連続した半角英数の文字列)を縦に表示するプログラムの例をリスト5に掲げておきます。入力された文字列を1文字ずつ取り出しては改行(\n)を付け足して出力するだけの処理です。

例えば“Hello!”と入力すると、以下のように表示されます。

H
e
l
l
o
!

リスト5:入力された文字列を縦に表示するプログラム(ex0903.cex0903.exe)
#include <stdio.h>

int main(void)
{
  char str[256 + 1];  /* 入力された文字列を保存 */
  char *p;            /* 縦表示用の1文字を示すポインタ */

  printf("Input String : ");
  scanf("%s", str);
  p = str;

  while (*p) {  /* 文字がNULL(0)でない間繰り返す */
    printf("%c\n", *p++);  /* 1文字に改行を付け足して出力 */
  }
  return (0);
}

あとがき

hiropの『ちょっと気になる専門用語』~《入力・出力》

本文で、標準入力・標準出力という言葉を使いました。入力・出力は工業製品でよく用いられる言葉で一般にもなじみがあるため、特に「?」と感じる人は少ないでしょう。電気製品では、電源が入力で壁のコンセントが電気の出力となります(コンセントは英語では“AC outlet”です)。自動車などのエンジンでは、回転する軸の発揮する力を出力といいます。いずれにせよ、入力・出力の『力』が何らかの働きを行う(または促す)物理的な『力』というイメージと重なっています。

ところがコンピュータ用語の場合、コンピュータ本体に入ってくる情報が入力、コンピュータの処理結果が出力となります。つまり、ただのデータ、単なる信号のことです。コンピュータの中では電子という物理的な存在が動いているのですが、人間の目には見えません。だから、『力』という言葉を充てられるとなんだかピンとこないように感じてしまいます。

また、コンピュータの中でも特にパソコンは人間が直接操作する道具なので、コンピュータにとっての入力は人間の出力であり、コンピュータにとっての出力はそれを利用する人間にとっての入力となります。この連綿と続く入力と出力の関係も、自動車やテレビなど他の道具とは異なる図式ですね。

強いて言えば、電話などの通信機器がこれに似た図式で表されます。Aさんの発した音声(出力)が電話機への入力であり、それを受け取ったBさんの電話機から音声が出力されると、それはBさんへの入力となります。

この構造を見れば、コンピュータ――特にパソコンが通信機能と結びついてメディアの一種となるのは、ごく当たり前のことだったのだと思えてきます。