第7回 配列と繰り返し(for文) (12/15)


今回は,配列の学習を中心に,繰り返しのもう一つ,for 文の演習を行う.


for文による繰り返し表現

(例)1から,入力した値 n までの和を求めるプログラムを作成せよ.

考え方:

 この問題は,1 から n までの値を自動的に作るプログラムを土台にする.



#include <stdio.h>
void main()
{
    /* 変数の定義 */
    int i, n;
 
    /* 入力 */
    printf("n=");
    scanf("%d", &n);
 
    /* 初期化 */
    i = 1;                   /* カウンターの値を1に */
 
    /* 出力 */
    while(i <= n) {          /* カウンターの値が n 以下の場合,以下を繰り返す */
        printf("%d¥n", i);   /* 画面にカウンターの値を表示する */
        i++;                 /* カウンターの値に1加える */
    }
}
 

 ここで,ループの回数を数えるカウンタは,1 から n まで変化する.

i
1
2
...
n

別の変数 wa を用意し,ループで作成したカウンタを順番に加えていく.

i
wa
1
1
2
1+2
...
...
n
1+2+...+n

#include <stdio.h>
void main()
{
    /* 変数定義 */
    int i, n, wa;
 
    /* 入力 */
    printf("n=");
    scanf("%d", &n);
 
    /* 初期化 */
    wa = 0;   /* 和をあらかじめ 0 に */ 
    i = 1;    /* カウンターの値を1に */
 
    /* 処理 */
    while(i <= n) {      /* カウンターの値が n 以下の場合,以下を繰り返す */
        wa += i;         /* wa = wa + i */
        i++;             /* カウンターの値に1加える */
    }

    /* 出力 */
    printf("和は %d です¥n", wa);     /* 結果を表示する */ 
}


同じプログラムを,for文を用いて作成すると,


#include <stdio.h>
void main()
{
    /* 変数定義 */
    int i, n, wa;
 
    /* 入力 */
    printf("n=");
    scanf("%d", &n);
 
    /* 初期化 */
    wa = 0;
 
    /* 処理 */
    for(i=1; i<=n; i++) {
        wa += i;
    }
 
    /* 出力 */
    printf("和は %d です.¥n", wa);
}

となる

while文と比較してみよう.


while for

式1;
while ( 式2 ) {
文1;
式3;
}

for(式1; 式2; 式3) {
文1;
}

式1 初期値設定 繰り返し実行の直前に1度だけ実行される.カウンタの初期値設定などに使う.
式2 反復条件 while分と同様,繰り返しを継続する条件を書く.この条件式がの間は繰り返す
式3 付加実行式 繰り返しを1度行うごとに実行したいことを書く.
文1 実行文 繰り返し実行する文


while 文と for 文の使い分けのめやす

for 文は,あらかじめ繰り返しの回数がわかっているときに,利用する.

while 文は,ある条件になるまで繰り返すという場合に,利用する.

ただし,どちらも書き換えが可能なので,必ずというわけではない.


配列

これまでに学んだ繰り返しの課題では,多くのデータを扱う場合でも,プログラム内で覚えておく値は,入力したばかりの値と,和などの計算途中の値など2〜3個程度でした.入力した値を(たとえば10個)すべて覚えておいて処理するためには,10個分の変数を用意する必要があります.しかし,10個も変数を用意し,別々の名前がついていては,せっかく習った繰り返しが使えません.


#include <stdio.h>
void main()
{
	int a1,a2,a3,a4,a5,a6,a7,a7,a9,a10,i,sum;

	sum = 0;

	printf("10個の整数値を入力します¥n");
	printf("1番目:"); scanf("%d", &a1); sum+=a1;
	printf("2番目:"); scanf("%d", &a2); sum+=a2;
	printf("3番目:"); scanf("%d", &a3); sum+=a3;
....

}

これが,100個や1000個になったら,とても対応できません.

「配列」は,同じ型のデータを一つの名前で表し,まとめて扱うために用意されたデータ構造である.配列のデータを扱う場合は,通常繰り返し文 (for, while) と組み合わせて用いられる.
何故か?・・・配列すべての要素,あるいは各要素に順次アクセスして計算や値の変更をするので,「繰り返し」処理が必要となる.


例えば,int 型一つ分の数値を入れることのできる箱を 8_1.pngで表す.4つの int 型変数を用意するには,例えば

int a, b, c, d;

と宣言すればよいが,

8_2.png

この図のように,まったく無関係の箱が4つ用意される. これでは変数の数だけ名前が必要となるので,変数の個数が増えると対応できなくなる.

そこで,複数の変数(ここでは a, b, c, d )が同じ型である場合,これらをまとめて扱うために「配列」を用いる.例えば4つの int 型変数を格納できる配列 a,100個の float 型変数を配列 dataは,


    int a[4];
    float data[100];

と宣言する.

8_3.png

配列はメモリー上で図のようなイメージとなり,これら複数の変数をまとめて配列 a として扱うことができる.

ここで,配列の中身 a[0] から a[3] (0番目~3番目の 4 個であることに注意)を配列 a の要素とよび,
要素の番号(例えば a[2] ならば 2 のこと)を,添字またはインデックスと呼ぶ.配列の添字は常に0から始まる事に注意!



配列の要素の代入と参照

配列の各要素への代入や要素の値の参照は,普通の変数と同じである.


    int a[4];         /* aという配列を宣言.要素数は4,a[0], ... , a[3] が利用可能になる. */

    a[0] = 1;           /* 配列aの最初の要素 a[0] に 1 を代入 */
    a[3] = -10;         /* 要素a[3]に -10 を代入 */

    printf("%d ¥n", a[0]);        /* 配列 a の最初の要素 a[0] の値を画面に表示 */

注意1:添字は,「0」 から 「要素数 - 1」 の範囲.この範囲外の要素を参照しようとすると,プログラムが不正終了する(しない場合もある).

注意2:一般の変数と同じく,配列も宣言しただけでは中身は不定(=ゴミが入っている).


配列の添え字

配列の添字には,変数も使うことができる(これが重要).つまり,forやwhile文のカウンタ変数を添字に指定することができる.

例1:


    int a[10];
    int n;

    n = 1;
    printf("%d¥n", a[n]);

例2:


    int a[10];
    int i;

    for(i=0; i<10; i++) {          /* 添字に使う場合は範囲に注意! */
        a[i] = i * i;                /* i 番目の要素に i * i を代入 */
        printf("%d¥n", a[i]);
    }


配列への入力

キーボードからデータを入力する場合を考えます.データ数が5個の和を出すプログラムをキーボードから入力した形に変更すると以下のようになります.


#include <stdio.h>
void main()
{
    /* 変数定義 */
    float a[5];
    float sum;
    int i;

    /* 初期化 */
    sum = 0;
 
    /* 処理 */
    for(i=0; i<5; i++){
        printf("a[%d]=",i);
        scanf("%f",&a[i]);
        sum += a[i];
    }

    /* 出力 */
    printf("和:%f¥n",sum);
}

これを実行すると,自分の任意のデータの和が求められます.


配列の宣言と初期化を同時に行う方法

配列は宣言と同時に初期化することができる.{ } を使って値を列挙する.


    int a[4] = { 1, 2, 3, 4 };

ただし,宣言と同時に初期化を行う場合のみ可能である.

即ち,以下のようにプログラムの途中では出来ない.


    a[4] = { 1, 2, 3, 4 };    /* これは不可 */

例:10個の整数の和を求めるプログラム(配列版)


#include <stdio.h>

void main()
{
    /* 変数定義 */
    int a[10] = {5,2,3,4,9,6,7,8,1,10};         /* 宣言と同時に初期化 */
    int i, sum;

    /* 初期化 */
    sum = 0;

    /* 処理 */
    for(i=0; i<10; i++){
        sum += a[i];        /* 配列の参照 */
    }

    /* 出力 */
    printf("合計 = %d ¥n", sum);
}


練習1

整数型配列に初期値として,{10,20,30,40,50}を設定する.

キーボードから配列の「要素番号」を入力すると,その配列要素の「値」を表示するプログラム.


#include <stdio.h>

void main()
{
    /* 変数定義 */
    int a[5] = {10, 20, 30, 40, 50};
    int num;

    /* 入力 */
    printf("添字の番号を入力してください(0 から 4 まで):");
    scanf("%d", &num);
    
    /* 処理・出力 */
    if (0 <= num && num <= 4) {          /* 添字の範囲をチェック.0から4まではO.K. */
        printf("Data  = %d¥n", a[num]);
    } else {
        printf("入力エラー:添字は配列の範囲を超えています.¥n");
    }
}


 

演習課題

要素数 10 個の整数型配列 {-4, 6, 7, 2, -7, 5, 3, 9, 0, 7}がある.


#include <stdio.h>

void main()
{

    /* 変数定義 */
    int a[10] = {-4, 6, 7, 2, -7, 5, 3, 9, 0, 7};

    /* 初期化 */

    /* 入力 */

    /* 処理 */

    /* 出力 */

}

(1) 配列の要素すべての値を表示するプログラムを作成せよ.

(2) 配列の要素すべての数の積を計算し,結果を表示するプログラムを作成せよ.

(3) 配列の中に数字の 7 がいくつあるかを数えるプログラムを作成せよ.

ヒント:配列から7を見つけるには,配列の各要素を順番に 7 かどうか調べる.別の変数(たとえばhantei)を用意しておき,利用すると便利.

(4) 配列 の中から数字の 5 を探し,5が「存在する」または「存在しない」と表示するプログラムを作成せよ.

ヒント:5が存在する = 5のカウントが0以外.

(5) 配列の最大値を表示するプログラムを作成せよ.(アルゴリズムをまず考えよう)

 

授業終了時までのプログラムと完成した提出用プログラムをoh-meijiシステムを使って提出すること
授業終了時に送るのは出席の確認用である.完成した課題は提出用の回に送ること
(提出期限を厳守し,提出用の回に提出しないと採点を行わない)

 


宿題

来週は,集大成として,配列にしまわれた数字を小さい順に並べ替えるプログラムを作成します。AからKまでのトランプ13枚が,でたらめな順番で並んでいます。これを,Aから順にKまで並べ替える際の手順を考えてきてください。


演習:解答例