第 2 回 番兵

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

2-1. 前回の演習の復習

プログラム例 4 を改造して次を表示するプログラムを作りなさい。

プログラム例 4
#include <stdio.h>
#define N 10
main(){
  int i,j;
  for(i=0;i<N;i++){
    for(j=0;j<N;j++){
      printf("〇");
    }
    printf("\n");
  }
}
  1. 〇〇〇〇〇
    〇〇〇〇
    〇〇〇
    〇〇
    〇
    

    プログラム例4 では一番内側の j の for 文は〇を書くだけで、その後、改行 を出力します。 つまり、j の for 文で一行の印刷される内容を決めています。 そして、i の for 文で複数の行を印刷しています。 一行目は i=0, 二行目は i=1 と順に i の値が増えます。

    演習では 5 行印刷しますので、 N=5 とします。 その時、 i の値は 0 から 4 まで増えることになりま す。 そして、i=0 の時は 5 個の〇を印刷しなければなりません。 そして i=1 の時は 4 個、i=2 の時は 3 個、i=3 の 時は 2 個、i=4 の時は 1 個印刷しなければなりません。 つまり、 j の for 文での繰返し回数は i が増えるにつれ 5,4,3,2,1 と減る 必要があります。

    i繰返し回数
    05
    14
    23
    32
    41

    ここから繰返し回数と i を足すと 5 になるということがわかり ます。よって繰返し回数は 5-i となります。 従って、下記のプログラムにより目的の図形が表示できることになります。

    
    #include <stdio.h>
    #define N 5
    main(){
      int i,j;
      for(i=0;i<N;i++){
        for(j=0;j<N-i;j++){
          printf("〇");
        }
        printf("\n");
      }
    }
    
  2.    〇
      〇〇〇
     〇〇〇〇〇
    〇〇〇〇〇〇〇
    

    この図形の場合、注意しなければならないのは、〇を書く前に空白を書く必要 があるということです。 従って、〇を書く for 文の前に空白を書く for 文を追加します。 追加したものは次の通りです。

    以下は単純に空白を書いてから〇を書くようにコピーしただけのもの。このま までは動きません。

    
    #include <stdio.h>
    #define N 5
    main(){
      int i,j;
      for(i=0;i<N;i++){
        for(j=0;j<N-i;j++){
          printf(" ");
        }
        for(j=0;j<N-i;j++){
          printf("〇");
        }
        printf("\n");
      }
    }
    

    設問では 4 行書いてますので、 N は 4 とします。 さらに、ここで、各行でいくつ空白と〇を書く必要があるかをまとめます。 表にすると次のようになります。

    i の値空白の数〇の数
    一行目031
    二行目123
    三行目215
    四行目307

    そして、各行の空白の数、〇の数をそれぞれ i を含む式で表すと N-i-1, 2*i+1 となります。

    従って、求めるプログラムは次の通りです。

    完成版
    #include <stdio.h>
    #define N 4
    main(){
      int i,j;
      for(i=0;i<N;i++){
        for(j=0;j<N-i-1;j++){
          printf(" ");
        }
        for(j=0;j<2*i+1;j++){
          printf("〇");
        }
        printf("\n");
      }
    }
    
  3. 〇〇〇〇〇
    〇   〇
    〇   〇
    〇   〇
    〇〇〇〇〇
    

    ここでは一番小さな図形を次で表すことにします。

    〇〇
    〇〇
    

    この場合に N=0 と考えることにします。 従って例題は N=3 となります。 一行目は 〇 を N+2 個書きます。 次に N 行だけ、 「〇を書き、空白を N 個書き、〇を書」きます。 そして最後の行は一行目と同様に 〇 を N+2 個書きます。 そのため、プログラムは次のようになります。

    
    #include <stdio.h>
    #define N 3
    main(){
      int i,j;
      for(j=0;j<N+2;j++){
        printf("〇");
      }
      printf("\n");
      for(i=0;i<N;i++){
        printf("〇");
        for(j=0;j<N;j++){
          printf(" ");
        }
        printf("〇\n");
      }
      for(j=0;j<N+2;j++){
        printf("〇");
      }
      printf("\n");
    }
    

2-2. 数をかぞえる

i=i+1や、k++のような構文は、変数を一つ増やします。 特定の条件の時、この構文を実行することにより、その条件が何回起きたが数 えることができます。 例えば次のプログラムでは、配列変数中の偶数の数を数えることができます。

x%yは x を y で割った時の余りを求めます。

#include <stdio.h>
#define N 5
main(){
  int a[N]={5, 2, 6, 3, 1};
  int i,kazu;
  kazu=0;
  for(i=0;i<N;i++){
    printf("%d ",a[i]);
    if((a[i]%2)==0){
      kazu++;
    }
  }
  printf("の中に偶数は %d 個\n",kazu);
}

2-3. 番兵

データの列の最後に、データの終りを示す特別な値を入れることを考えます。 すると、プログラムはデータの数を知らなくてもデータの終りがわかります。 その結果、あらかじめデータの数がわからなくてもデータを全て読むことがで きます。 このようなデータの終りを示す特別な値を「番兵」と呼びます。 ここでは番兵を使った処理を学びます。

配列変数 a[] で最後に番兵がある場合、プログラムは次のようになります。


#include <stdio.h>
main(){
  int a[]={xx,xx,xx,番兵};
  int i;
  for(i=0;a[i]!=番兵;i++){
    a[i] に関する処理
  }
}

なお、ここで番兵というのは「番兵」という文字列ではありません。 例えば、上の例だと int 型のデータの配列に入れなければならないので、当 然データであろうと、番兵であろうと int 型の数でなければなりません。 ですから、配列の要素として、データとして解釈すべき値は番兵にはなりませ ん。 例えば、データが全て 0 以上と仮定できれば、負の値を番兵として使うこと ができます。

これを利用して、番兵を -1 、正の値を持つ配列変数の値を全て出力するプロ グラムは次のように書きます。


#include <stdio.h>
main(){
  int a[]={5, 2, 6, 3, 1, -1};
  int i;
  for(i=0;a[i]!=-1;i++){
    printf("%d\n",a[i]);
  }
}

2-4. 演習

以下の問題を解決するプログラムを書きなさい。 但し、与える変数は次の 2 種類あるとし、それぞれのどちらかを完成したプ ログラムの冒頭に配置します。プログラムはその行以外の変更なしに動くよう にしなさい。

  1. int a[]={5, 2, 6, 3, 1, -1};
  2. int a[]={10, 1, 3, 6, 4, 9, -1};

問題

  1. 与えられた配列変数が番兵を除いていくつあるか表示するプログラムを書 きなさい。
  2. 与えられた配列変数の合計を求めるプログラムを書きなさい。
  3. 与えられた配列変数の平均を求めるプログラムを書きなさい。

出来る人への暇潰し演習

  1. 与えられた配列変数のそれぞれの数分だけ〇を書き、棒グラフを作りなさ い。
  2. 次の図形を書きなさい。
    〇〇〇〇〇〇〇〇〇
    〇       〇
    〇 〇〇〇〇〇 〇
    〇 〇   〇 〇
    〇 〇 〇 〇 〇
    〇 〇   〇 〇
    〇 〇〇〇〇〇 〇
    〇       〇
    〇〇〇〇〇〇〇〇〇
    
  3. 次の図形を書きなさい(激ムズ)。
    〇〇〇〇〇〇〇〇〇
    〇       〇
    〇 〇〇〇〇〇 〇
    〇 〇   〇 〇
    〇 〇 〇 〇 〇
    〇 〇 〇 〇 〇
    〇 〇 〇〇〇 〇
    〇 〇     〇
    〇 〇〇〇〇〇〇〇
    

坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科