ppt file

プログラミング入門2
第4回
配列
for文
変数宣言
初期化
情報工学科 篠埜 功
今日の内容
•
•
•
•
配列
for文
変数宣言
初期化
配列とは、同じ型のデータを格納する箱(領域)を一列
に並べて添え字でアクセスできるようにしたもの。
配列の宣言
• 3人分の点数を格納するint型の変数を用意したい場合
int型の変数の宣言
型名
変数名
int x ;
x
int型のデータの格納場
所が1つ用意される。
int型を要素とする配列の宣言
要素の型名 変数名 [ 要素数 ]
int a [3] ;
a [0]
a [1]
a [2]
a[0] ~a[2]までの3個
のint型のデータの格
納場所が用意される。
[ ]内に書く番号(添え字という)
は0から始まる。
配列の各要素へのアクセス
変数の場合の例
配列の場合の例
int x;
x = 3;
printf (“%d\n”, x + 2);
int x [10];
x[0] = 3;
printf (“%d\n”, x[0] + 2);
配列の各要素は、x[0]のように、配列名に続けて添え字を[ ]内
に入れて表す。添え字は数字でなくても変数などの式でも構
わない。ポインタの回にもう一度説明する。
変数の場合と同様に、配列の各要素がint型やdouble型の場
合には、そこへ値を代入したり、そこに格納されている値を参
照したりできる。
変数宣言の記法について(1)
これまで変数宣言は1つずつ書いてきたが、同じ型
の変数はまとめて宣言することができる。
(例)
int x;
int y;
int z;
double a;
double b;
は、
int x,y,z;
double a, b;
のように、コンマで区切って一度に宣言してよい。
変数宣言の記法について(2)
配列の宣言もまとめて書いてよい。
(例)
int x;
int a[3];
int b[10];
double y;
double c[20];
は、
int x, a[3], b[10];
double y, c[20];
のようにコンマで区切って一度に宣言してよい。
変数宣言と初期化
変数宣言時に、変数の初期値を書くことができる。
(例)
int x;
int y;
x=3;
y=10;
は、
int x=3, y=10;
のようにまとめて書いてよい。
変数宣言時に初期化をすることによって、その変数の
値を代入前に参照するという状況が起こらなくなる。
配列の初期化(1)
変数と同様、配列も宣言時に初期化できる。
宣言時に、右辺に中括弧で囲んで値を並べる。
例えば、
int a[3];
a[0] = 10;
a[1] = 5;
a[2] = 7;
は、
int a[3] = {10, 5, 7};
のようにまとめて書くことができる。
配列の要素数について
配列を宣言する際、要素数は定数でなければならない。
(教科書 p. 111 参照)
例えば、
int n = 5;
int a[n];
のように要素数を変数で指定することは(1990年のISO規
格(C89)では)許されていない。
ただし、1999年のISO規格(C99)では定数でなくてもよく
なったので、上記のような宣言は許されている。
講義では1990年のISO規格(C89)に従うが、試験ではどち
らでもよいことにする。
配列の初期化(2)
配列の初期化において、右辺の要素数が少ないとき
は、足りない部分は0 (double型の場合は0.0) で初期
化される。たとえば、
int a[3] = {10, 5};
のように書くと、a[0]が10, a[1]が5, a[2]が0で初期化さ
れる。
配列の初期化(3)
配列の初期化において、右辺に初期化子がある場合、
要素数を省略できる。例えば、
int a [ ] = {10, 5, 7};
のように書くと、
int a [3] = {10, 5, 7};
と書いたのと同じ意味になる。
例(打ち込んで確認)
#include <stdio.h>
int main (void) {
int a[3] = {10,5}; a[0]が10, a[1]が5, a[2]が0で初期化さ
れる。
int b[3] = {0};
int c[ ] = {3,4,5}; b[0], b[1], b[2]が0で初期化される。
int i=0;
c[0]が3, c[1]が4, c[2]が5で初期化される。
while (i<3) {
printf ("a[%d] = %d\n", i, a[i]);
printf ("b[%d] = %d\n", i, b[i]);
printf ("c[%d] = %d\n", i, c[i]);
i=i+1;
}
return 0;
}
for文
これまでは繰り返しのための構文としてはwhile文を
使用していた。繰り返し構文は配列を扱う場合によく
使われる。
配列の処理の典型的な形:
i = 0;
while (条件式) {
… 配列に関する計算 …
i = i + 1;
}
このような形のプログラムを見やすく書くための構文と
してfor文がある。
for文の例(左のプログラムを
打ち込んで確認)
#include <stdio.h>
int main (void) {
int i, a[5]={1,2,3,4,5};
for (i=0; i<5; i=i+1)
printf ("a[%d]=%d\n", i, a[i]);
return 0;
}
#include <stdio.h>
int main (void) {
int i, a[5]={1,2,3,4,5};
i=0;
while (i<5) {
printf ("a[%d]=%d\n", i, a[i]);
i=i+1;
}
return 0;
}
左と右のプログラムは同じ意味である。
for文の構文(基本形)
for文の構文
for (式; 式; 式) 文
for文 for (e1; e2; e3) s の意味
e1;
while (e2) {
s
e3;
}
と同じ意味である。
(注意)1999年のISO規格
(C99)においてはe1のところ
に変数宣言(for文内部での
み有効)が書けるようにfor
文の定義が拡張されている。
e1のところが変数宣言の場
合は、左の置き換えはでき
ない(変数の有効範囲が変
わってしまうので)。
例
#include <stdio.h>
int main (void) {
int i, sum=0, a[5]={1,2,3,4,5};
for (i=0; i<5; i=i+1) {
printf ("a[%d]=%d\n", i, a[i]);
sum = sum + a[i];
}
printf ("sum=%d\n", sum);
return 0;
}
配列aの要素の
和を表示するプ
ログラムである。
この例では、for文
の本体(赤字部分)
が複合文である。
while文を使った場合
#include <stdio.h>
int main (void) {
int i, sum=0, a[5]={1,2,3,4,5};
i=0;
while (i<5) {
{
printf ("a[%d]=%d\n", i, a[i]);
sum = sum + a[i];
}
i=i+1;
}
printf ("sum=%d\n", sum);
return 0;
}
前ページのプログラ
ムをさきほどの説明
の通りwhile文で置き
換えると左のプログ
ラムになる。
(注)赤字の複合文の
中括弧 { } を取り除いて
も同じ意味である。
for文の構文
さきほどfor文の構文を以下のように定義したが、
括弧内の3つの式はそれぞれ省略可能である。
for (式; 式; 式) 文
1番目の式がない場合は、繰り返しの実行前に何も
しないということである。
3番目の式がない場合は、各繰り返しにおいて、for
文の本体の実行後、何もしないということである。
2番目の式がない場合は、繰り返しの条件が常に
真という意味である。
例(左のプログラムを
打ち込んで確認)
#include <stdio.h>
int main (void) {
for (;;)
printf ("hello\n");
return 0;
}
#include <stdio.h>
int main (void) {
while (1)
printf ("hello\n");
return 0;
}
式を3つとも省略すると、while(1)で置き換えたプロ
グラムと同じ意味である。
(無限にhelloと出力し続けるので、Ctrl-Cで終了させ
る。)
配列のコピー
配列のコピーを行う場合は、各要素を
コピーする必要がある。
間違った例
int a[3] = {10, 5, 7};
int b[3];
b=a;
b=aの代入式はコンパイル時にエラーになる。
詳しくはポインタの回に説明する。
配列のコピー(打ち込んで確認)
#include <stdio.h>
int main (void) {
int a[5] = {3,4,5,6,7};
int b[5];
int i;
for (i=0; i<5; i=i+1) b[i] = a[i]の代入式によって各
要素ごとに代入を行っている。
b[i] = a[i];
for (i=0; i<5; i=i+1)
printf (“a[%d]=%d, b[%d]=%d\n”, i, a[i], i, b[i]);
return 0;
}
多次元配列
配列の要素は配列でもよい。
例えば、int型を要素にもつ長さ3の配列を要素に
もつ長さ2の配列は、
int a [2] [3] ;
のように宣言する。これは2次元配列である。(3
次元以上も同様に宣言できる。2次元以上の配
列を多次元配列と呼ぶ。)
各要素は、a[0][1]のように、[ ] を並べて書くことに
よって表す。これは(a[0])[1]を括弧を省略して書
いたものである。a[0]はaの0番目の要素(int型を
要素にもつ長さ3の配列)を表し、a[0][1]は、配列
a[0]の1番目の要素を表す。
多次元配列のメモリ上での配置
int a [2] [3] ;
のように宣言された2次元配列の各要素は以下の
ようにメモリ上に配置される。
配列 a[0]
配列 a[1]
a[0][0]
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
多次元配列の例(打ち込んで確認)
/* 2*3の配列の各要素に1を代入し、各要素の値を表示 */
#include <stdio.h>
int main (void) {
int i, j;
int a[2][3];
for (i=0; i < 2; i=i+1)
for (j=0; j < 3; j=j+1)
a[i][j] = 1;
for (i=0; i < 2; i=i+1)
for (j=0; j < 3; j=j+1)
printf ("a[%d][%d] = %d\n“, i, j, a[i][j] );
return 0;
}
多次元配列の初期化
1次元配列と同様に初期化できる。
(例)
int a [2][3] = { {1,2,3}, {4,5,6} };
のように宣言、初期化すると、配列 a[0] が{1,2,3}で
初期化され、配列 a[1] が{4,5,6}で初期化される。
プログラム例(打ち込んで確認)
/* 初期化した値を表示して確認 */
#include <stdio.h>
int main (void) {
int a[2][3] = { {1,2,3}, {4,5,6} };
int i, j;
for (i=0; i < 2; i=i+1)
for (j=0; j < 3; j=j+1)
printf ("a[%d][%d] = %d\n", i, j, a[i][j]);
return 0;
}
基本課題1
キーボードから5人分の点数(100点満点)を受け取り、80点
以上の人数を表示するプログラムを書け。ただし、点数格納
用の配列を用いることを条件とする。
[実行例]
5人分の点数を入力してください
1人目: 10
2人目: 80
3人目: 38
4人目: 60
5人目: 90
80点以上の人は2人です。
基本課題2
キーボードから5人分の点数を読み取り、60点以上と60点未満
に分けて表示するプログラムを書け。同じ点数の人がいた場合
はその人数分表示せよ。点数の表示の順番は自由とする。た
だし、点数格納用の配列を用いることを条件とする。
[実行例]
5人分の点数を入力してください
1人目: 10
2人目: 60
3人目: 38
4人目: 90
5人目: 38
60点以上: 60 90
60点未満: 10 38 38
発展課題1
キーボードから5人分の点数(100点満点)を読み取り、平均
点以上と平均点未満に分けて表示せよ。平均点はdouble型
で求めよ。同じ点数の人がいた場合はその人数分表示せよ。
点数の表示の順番は自由とする。ただし、点数格納用の配
列を用いることを条件とする。
[実行例]
5人分の点数を入力してください
1人目: 68
2人目: 59
3人目: 80
4人目: 72
5人目: 73
平均点: 70.400000
平均点以上: 80 72 73
平均点未満: 68 59
発展課題2
2次元配列を3つ使って、2*2の行列の積を計算して表示す
るプログラムを書け。行列の各要素の値はint型とし、キー
ボードから読み込むようにせよ。ただし、2次元配列を使うこ
とを条件とする。(3重ループを使うのが望ましいが、そうで
なくても正解とする。)
[実行例]
行列aを入力してください:
a[0][0] = 1
a[0][1] = 2
a[1][0] = 3
a[1][1] = 4
行列bを入力してください:
b[0][0] = 1
b[0][1] = 1
b[1][0] = 1
b[1][1] = 1
行列a,bの積は
p[0][0] = 3
p[0][1] = 3
p[1][0] = 7
p[1][1] = 7
です。
発展課題3
2*2のint型の行列のn乗を計算し、表示するプログラム
を書け。行列の値およびnはキーボードから読み込むよ
うにせよ。ただし、2次元配列を使うことを条件とする。
(行列の掛け算部分は3重ループで書くのが望ましいが、
そうでなくても正解とする。)
[実行例]
行列aを入力してください:
a[0][0] = 1
a[0][1] = 2
a[1][0] = 3
a[1][1] = 4
何乗しますか: 3
行列aの3乗は
p[0][0] = 37
p[0][1] = 54
p[1][0] = 81
p[1][1] = 118
です。
(ヒント) 単位行列にaをn回掛ける形にすると分かりやすい。
参考課題1
キーボードから10人分の点数(100点満点)を受け取って長さ
10の配列に格納し、最高点、最低点、平均点を計算して表示
するプログラムを書け。平均点はdouble型で計算し、表示せよ。
[実行例] 点数を10人分入力してください:
1人目: 10
2人目: 50
3人目: 38
4人目: 80
5人目: 60
6人目: 90
7人目: 38
8人目: 100
9人目: 45
10人目: 87
最高点は100点, 最低点は10点, 平均点は59.800000点です。
参
考
課
題
1
解
答
例
#include <stdio.h>
int main (void) {
int a[10];
int i,max,min,sum=0;
printf ("点数を10人分入力してください: \n");
for (i=0; i<10; i=i+1) {
printf("%d人目: ", i+1);
scanf ("%d", &a[i]);
}
max = min = a[0];
for (i=0; i<10; i=i+1) {
sum = sum + a[i];
if (max < a[i]) max = a[i];
if (min > a[i]) min = a[i];
}
printf ("最高点は%d点, ", max);
printf ("最低点は%d点, ", min);
printf ("平均点は%f点です。\n", (double)sum/10);
return 0;
}
参考課題2
2次元配列を3つ使って、2*2の行列の和を計算して表示す
るプログラムを書け。行列の各要素の値はint型とし、キー
ボードから読み込むようにせよ。
[実行例]
行列aを入力してください:
a[0][0] = 1
a[0][1] = 2
a[1][0] = 3
a[1][1] = 4
行列bを入力してください:
b[0][0] = 1
b[0][1] = 1
b[1][0] = 1
b[1][1] = 1
行列a,bの和は
s[0][0] = 2
s[0][1] = 3
s[1][0] = 4
s[1][1] = 5
です。
参考課題2 解答例
#include <stdio.h>
int main (void){
int a[2][2], b[2][2], s[2][2], i, j;
printf("行列aを入力してください:\n");
for (i=0; i<2; i=i+1)
for (j=0; j<2; j=j+1) {
printf("a[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
printf("行列bを入力してください:\n");
for (i=0; i<2; i=i+1)
for (j=0; j<2; j=j+1) {
printf("b[%d][%d] = ", i, j);
scanf("%d", &b[i][j]);
}
/* 続き */
for (i=0; i<2; i=i+1)
for (j=0; j<2; j=j+1)
s[i][j] = a[i][j] + b[i][j];
printf("行列a,bの和は\n");
for (i=0; i<2; i=i+1)
for (j=0; j<2; j=j+1)
printf("s[%d][%d] = %d\n", i, j, s[i][j]);
printf("です。\n");
return 0;
}