cp-7. 配列
C プログラミング入門
URL: https://www.kkaneko.jp/pro/adp/index.html
1
金子邦彦
配列の宣言と使用方法、繰り返し文との組み合わせによ
る多量データの処理
学習内容の構成
1. 配列の基本0ら始まる添字を持つデータの並び、
int型・double型での宣言
2. 配列の読み書き:添字を指定して通常の変数と同様
に使用
3. 配列と繰り返しfor文との組み合わせによるベクト
ル内積・合計点計算
4. 2次元配列:行列データの表現と演算
前提:変数、繰り返し文(for, do-while)、条件分岐
の理解
意義:多量のデータを効率的に扱う技法の習
2
配列
データの並びで,0から始まる番号(添字)
が付いている
添字
3
例題1.月の日数
年と月を読み込んで,日数を求めるプログラ
ムを作る
うるう年の2月ならば29
日数を求めるために,サイズ12の配列を使う
例) 2001 11 30
4
月の日数
#include <stdio.h>
#pragma warning(disable:4996)
int main()
{
int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int y;
int m;
printf( "y=" );
scanf( "%d", &y );
printf( "m=" );
scanf( "%d", &m );
if ( (m == 2) && (((y % 400) == 0) || (((y % 100) != 0) && ((y % 4) == 0)))){
printf( "number of days(%d) = 29¥n", m );
}
else {
printf( "number of days(%d) = %d¥n", m, num_days[m-1] );
}
return 0;
}
配列の宣言
配列からの
読み出し
「m-1」に意味がある
5
月の日数
実行結果の例
y=2001
m=11
number of days(11) = 30
6
プログラムとデータ
メモリ
num_days[0]
num_days[m-1];
配列からの値の
読み出し
num_days[1]
num_days[2]
num_days[3]
num_days[4]
num_days[5]
num_days[6]
num_days[7]
num_days[8]
num_days[9]
num_days[10]
num_days[11]
31
28
31
30
31
30
31
31
30
31
30
31
7
配列の宣言
配列には,名前(データの種類のこと)と
サイズがある
整数データ int
浮動小数データ double
配列を使うには,配列の使用をコンピュータに
伝えること(宣言)が必要
int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
整数
データ
名前は
num_days
配列のサイズ
は12
8
配列の添字
配列の中身を読み書きすると
きには,配列の名前添字
書く
例) num_days[m-1]
添字は0から(サイズー1)
まで
例) サイズ12の配列の
添字は,0から11ま
添字
10
11
これが添字
9
配列の読み書き
添字を付けて,普通の変数と同じように使
例)
v[0]=1.3;
a=v[1];
printf("%f", v[2]);
scanf("%lf", &v[3]);
10
例題2.ベクトルの内積
ベクトル(1.9, 2.8, 3.7)と,ベクトル(4.6,
5.5, 6.4)の内積を表示するプログラムを作る
2つのベクトルの内積の計算のために,サイズ3の
配列を2つ使う
11
例題2.ベクトルの内積
#include <stdio.h>
int main()
{
double u[]={1.9, 2.8, 3.7};
double v[]={4.6, 5.5, 6.4};
int i;
double ip;
ip = 0;
for (i=0; i<3; i++) {
ip = ip + u[i]*v[i];
}
printf("内積=%f¥n", ip);
return 0;
}
配列の宣言
配列からの
読み出し
12
ベクトルの内積
実行結果の例
内積=47.820000
13
プログラムとデータ
メモリ
u[0]
ip = ip + u[i]*v[i];
配列からの値の
読み出し
u[1]
u[2]
1.9
2.8
3.7
v[0]
v[1]
v[2]
4.6
5.5
6.4
14
配列の宣言
double u[]={1.9, 2.8, 3.7};
double v[]={4.6, 5.5, 6.4};
浮動小数
データ
名前は
u v
配列のサイズ
は3
15
プログラム実行順
ip = 0.0;
i < 3
Yes
No
i = 0;
printf("内積=%f¥n",ip);
ip = ip + u[i]*v[i];
i++;
16
ベクトルの内積
繰り返し
1回目
i = 0 i < 3 が成り立つ ip = ip + u[0] * v[0];
繰り返し
2回目
繰り返し
3回目
繰り返し
4回目
i = 1 i < 3 が成り立つ ip = ip + u[1] * v[1];
i = 2 i < 3 が成り立つ ip = ip + u[2] * v[2];
i = 3 i < 3 が成り立たない
i の値
繰り返し条件式
が成り立つか
ip の値
つまり ip の値は u[0]*v[0]
つまり ip の値は u[0]*v[0] + u[1]*v[1]
つまり ip の値は u[0]*v[0] + u[1]*v[1]
+u[2]*v[2]
17
例題3.合計点と平均点
点数を読み込んで,合計点と平均点を表示す
るプログラムを作る.
平均点の計算では,小数点以下切捨て
プログラムは,点数を読み込み続けるが,読み込
んだ点数が「-1」のときには,合計点と平均点
を表示して終了する
読み込んだ点数は,いったんサイズ100の配列
に格納する(点数の数は100を超えないものと
仮定する)
例) 50, 85, 30, 20
合計点 185
平均点 46
18
#include <stdio.h>
#pragma warning(disable:4996)
int main()
{
int x[100];
int sum;
int i;
int n;
n = 0;
do {
printf( "x[%d]=", n );
scanf( "%d", &x[n] );
n++;
} while ( ( x[n-1] >= 0 ) && ( n < 100 ) );
sum = 0;
for (i=0; i<(n-1); i++) {
sum = sum + x[i];
}
printf("合計=%d, 平均=%d¥n", sum, sum/(n-1) );
return 0;
}
配列の宣言
19
合計点と平均点
実行結果の例
x[0]=50
x[1]=85
x[2]=30
x[3]=20
x[4]=-1
合計=185, 平均=46
20
プログラムとデータ
メモリ
scanf("%d",&x[n]);
整数データを
読み込み
x[0]
x[1]
x[2]
x[3]
x[4]
sum = sum + x[i];
合計値の計算
21
プログラム実行順
n = 0;
( x[n-1] >= 0 ) && ( n < 100 )
Yes
No
printf( "x[%d]=", n );
scanf( "%d", &x[n] );
n++;
sum = 0;
i = 0;
No
i < n - 1
sum = sum + x[i];
i++;
Yes
22
合計点と平均点
(5回目で「-1」を読み込んだとき)
繰り返し
1回目
n = 1 (x[0] > 0 && n < 100)が成り立つ x[0]
繰り返し
2回目
n = 2 (x[1] > 0 && n < 100)が成り立つ x[1]
繰り返し
3回目
n = 3 (x[2] > 0 && n < 100)が成り立つ x[2]
繰り返し
4回目
n = 4 (x[3] > 0 && n < 100)が成り立つ x[3]
繰り返し
5回目
n = 5 (x[4] > 0 && n < 100)が成り立たない x[4]
n の値
繰り返し条件式
が成り立つか
読み込まれる
配列の要素
「-1」を読み込んだら
この部分が成り立たない
23
配列の宣言
1. 配列の宣言時にサイズを指定
例)
int x[100];
2. 配列の宣言時に初期値を設定
例)
double u[]={1.9, 2.8, 3.7};
double v[]={4.6, 5.5, 6.4};
int a[]={6,4,7,1,5,3,2};
サイズとして「100」
を書いている
初期値を並べて
書いている
24
例題4.棒グラフを描く
整数の配列から,その棒グラフを表示するプ
ログラムを作る.
ループの入れ子で,棒グラフの表示を行う
25
棒グラフを描く
#include <stdio.h>
int main()
{
int a[]={6,4,7,1,5,3,2};
int i;
int j;
for (i=0; i<7; i++) {
for (j=0; j<a[i]; j++) {
printf("*");
}
printf("¥n");
}
return 0;
}
配列の宣言
配列からの
読み出し
26
棒グラフを書く
実行結果の例
******
****
*******
*
*****
***
**
27
プログラムとデータ
メモリ
a[0]
for (j=0; j<a[i]; j++) {
配列からの値の
読み出し
a[1]
a[2]
6
a[3]
a[4]
a[5]
a[6]
4
7
1
5
3
2
28
配列の宣言
int a[]={6,4,7,1,5,3,2};
整数
データ
名前は
a
配列のサイズ
は7
29
プログラム実行順
j < a[i]
Yes
No
printf("*");
++;
printf("¥n");
i < 7
Yes
i++;
= 0;
i = 0;
No
return 0;
30
ここまでのまとめ
配列の宣言
[] の中に,配列のサイズを書く.但し,配列の初期
値を設定するときには「空」にする.
配列の使用
[]の中に,使用したい配列の添字を書く
[] の意味
31
課題1
n次の多項式
f(x) = a0 + a1x + a2x + ・・・ +anx
について,次数 n と,係数 a0 から an を読み込ん
で,f(x) を計算するプログラムを作りなさい
n は高々20までとする.(ユーザが20以上の数を n
として与えたら,メッセージを表示して止まること).
次ページで説明する Horner法を使うこと
読み込んだ点数は,いったんサイズ21の配列に格納す
x を繰り返し入力できるようなプログラムであること
(つまり f(x) を何度も計算する)
32
Horner
f(x) = a0 + a1x + a2x + ・・・ +anx
= a0 + ( a1 + ( a2 + ・・・ + ( an-1 + an x ) x ・・・) x ) x
例えば, 5 + 6x + 3x
= 5 + ( 6 + 3x ) x
計算手順
an
an-1 + anx
an-2 + ( an-1 + anx ) x
・・・ an まで続ける)
2
n
2
33
課題1のヒント
ここを考える
No
i >= 0
Yes
sum = a[n];
i = n - 1;
i --;
34
課題2.エラトステネスのふる
「エラトステネスのふるい」の原理に基づ
いて100以下の素数を求め,結果を表示する
プログラムを作成せよ.
100以下の素数を求めるために,サイズ10
0の配列を使う
添字が素数の要素に1,そうでない要素に0を代
入する
35
エラトステネスのふるい (1/4)
10 11 ・・・
2×2
2×3 2×4
2×5
まず,2の倍数を消す
36
エラトステネスのふるい (2/4)
10 11 ・・・
3×2
次に,3の倍数を消す
3×3
37
エラトステネスのふるい (3/4)
10 11 ・・・
次に,5の倍数を消す
(「4の倍数」は考えない.
それは,「4」がすでに消えているから)
5×2
38
エラトステネスのふるい (4/4)
10 11 ・・・
以上のように,2,3,5,7の倍数を消す.
10(これは100の平方根)を超えたら,この操作を止める
(100以下で,11,13・・・の倍数はすでに消えている)
39
例題5.行列の和
2行3列の行列の和を計算して表示するプロ
グラムを作る.
2つの行列を扱うために,2行3列の2次元配列
を2つ使う
a 2行3列の2次元配列 浮動小数
b 2行3列の2次元配列 浮動小数
40
2次元配列とは
ary[0][0]
ary[0][1]
ary[1][0]
ary[2][0]
...
41
行列の和
#include <stdio.h>
int main()
{
int a[2][3]={{1,2,3},{4,5,6}};
int b[2][3]={{9,8,7},{6,5,4}};
int i;
int j;
for (i=0; i<2; i++) {
for (j=0; j<3; j++) {
printf("%d, ", a[i][j]+b[i][j]);
}
printf("¥n");
}
return 0;
}
配列の宣言
配列からの
読み出し
42
行列の和
実行結果の例
10, 10, 10,
10, 10, 10,
43
2次元配列の宣言
2次元配列の宣言では,名前型,サイズを指
定することが必要
int a[2][3]={{1,2,3},{4,5,6}};
整数
データ
名前は
a
配列のサイズ
は2×3
2次元以上の配列の宣言では,サイズを書く
(省略できない)ことになっている
44
課題3
3×3行列の積を計算して表示するプログラムを
作成しなさい
2つの行列を扱うために,3行3列の2次元配列を2
つ使う
45
多次元配列についての補足
多次元配列は,普通,最大7次元まで(処理系に
より異なる).
例) 整数型の3次元配列
int a[2][3][4];
46
変数の初期化
変数を宣言すると同時に,値の設定もできます.
int i;
i = 0;
int i = 0;
同じ意味
47