CプログラミングⅠ
配列,多次元配列
配列
同じ型の値を複数記憶するための箱(変数)
面倒だから配列を使おう!
int a[100];
100個の整数データを記憶したい!
int a;
int b;
int c;
: int z;
配列とは
a a[0]
b
c
d a[1] a[2] a[3] a[99]
やっと25個
あと75個の変数宣言は どうしよう・・・?
配列を宣言することで 複数の整数データが 記憶できる
配列の宣言
配列の宣言
例
int a[5];
b a c 100
116 104
112 108
120 int a;
int b;
int c;
メインメモリでは...
番地
int a[3]; a[0]
a[1]
a[2]
100
116 104
112 108
120
番地
領域の 割り当てが バラバラ
領域の 割り当てが 連続
a[0] a[1] a[2] a[3] a[4]
このように宣言することで 整数データが記憶できる箱が 5個用意される
箱1個のことを配列要素という
各配列の添字番号(インデックス)は 0から(要素数-1)までとなる
型名 配列名 要素数
配列宣言の書式
型名 配列名[要素数];
配列要素への値の代入
配列の利用
配列要素への値の代入 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
#include <stdio.h>
int main(void) {
int i;
int a[5];
a[0] = 10;
a[1] = 20;
i = 3;
a[i] = 30;
printf("a[%d] = %d¥n", 0, a[0]);
printf("a[%d] = %d¥n", 1, a[1]);
printf("a[%d] = %d¥n", i, a[i]);
return 0;
}
添字用変数
添字変数を用いて 値を代入できる
実行結果 a[0] = 10 a[1] = 20 a[3] = 30
a[0] a[1] a[2] a[3] a[4]
10 20 30
添字で指定した番号の要素に 式の値を代入する
配列要素への値の代入
配列名[添字] = 式;
配列の利用
配列の初期化
配列の初期化 1:
2:
3:
4:
5:
#include <stdio.h>
int main(void) {
int a[5] = { 10, 20, 30, 40, 50 };
int b[5] = { 10, 20, 30 };
…
… return 0;
}
a[0] a[1] a[2] a[3] a[4]
10 20 30 40 50
b[0] b[1] b[2] b[3] b[4]
10 20 30 0 0
要素数に対して初期化子が 足りない場合は0が入る
配列の宣言と 値の格納を
同時に行う 配列の初期化
型名 配列名[要素数] = { 値0, 値1, … };
初期化子
配列の利用
繰り返し文による配列の利用
配列の各要素を指定するときには添字に変数を用い,
さらに繰り返し文を用いることでデータ処理が簡単に扱える
繰り返し文による配列の利用 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#include <stdio.h>
int main(void) {
int index;
int a[5] = { 10, 20, 30, 40, 50 };
for(index = 0; index < 5; index++){
printf("%d番目の配列要素の値は%dです.¥n", index, a[index]);
}
return 0;
}
indexの値により,
どの要素に対して処理を行うかが決まる
実行結果
0番目の配列要素の値は10です.
1番目の配列要素の値は20です.
2番目の配列要素の値は30です.
3番目の配列要素の値は40です.
4番目の配列要素の値は50です.
配列の利用
繰り返し文による配列の利用
繰り返し文による配列の利用 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#include <stdio.h>
int main(void) {
int index;
int a[5] = { 10, 20, 30, 40, 50 };
for(index = 0; index < 5; index++){
printf("a[%d] = %d¥n", index, a[index]);
}
return 0;
} 実行結果
a[0] = 10 a[1] = 20 a[2] = 30 a[3] = 40 a[4] = 50
② index ( = 0 ) < 5 は成り立つ?
③ 成り立つので a[0] の値 10 を表示
④ index++ 実行(index に 1 が入る)
① index に 0が代入される
⑤ index ( = 1 ) < 5 は成り立つ?
⑥ 成り立つので a[1] の値 20 を表示
⑦ index++ 実行(index に 2 が入る)
⑭ index ( = 4 ) < 5 は成り立つ?
⑮ 成り立つので a[4] の値 50 を表示
⑯ index++ 実行(index に 5 が入る)
⑧ index ( = 2 ) < 5 は成り立つ?
⑨ 成り立つので a[2] の値 30 を表示
⑩ index++ 実行(index に 3 が入る)
⑪ index ( = 3 ) < 5 は成り立つ?
⑫ 成り立つので a[3] の値 40 を表示
⑬ index++ 実行(index に 4 が入る)
⑰ index ( = 5 ) < 5 は成り立つ?
⑱ 成り立たないので繰り返し終了
配列の利用
配列へのキーボードからの入力
配列へのキーボードからの入力 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdio.h>
int main(void) {
int i;
int test[5];
printf("5人の点数を入力してください.¥n");
for(i = 0; i < 5; i++){
printf("%d人目の点数:", i + 1);
scanf("%d", &test[i]);
}
for(i = 0; i < 5; i++){
printf("%d人目の点数は%dです.¥n", i + 1, test[i]);
}
return 0;
}
普通の変数と同じように
& を忘れないように
実行結果
5人の点数を入力してください.
1人目の点数:80[Enter]
2人目の点数:60[Enter]
3人目の点数:40[Enter]
4人目の点数:90[Enter]
5人目の点数:70[Enter]
1人目の点数は80です.
2人目の点数は60です.
3人目の点数は40です.
4人目の点数は90です.
5人目の点数は70です.
配列要素の添字番号は 0から始まるため+1している
配列の利用
配列を使った計算
配列要素の合計 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
#include <stdio.h>
int main(void) {
int i, sum;
int data[5] = {10, 20, 30, 40, 50};
sum = 0;
for(i = 0; i < 5; i++){
printf("%d + %d = ", sum, data[i]);
sum += data[i];
printf("%d¥n", sum);
}
printf("合計:%d¥n", sum);
return 0;
}
実行結果 0 + 10 = 10 10 + 20 = 30 30 + 30 = 60 60 + 40 = 100 100 + 50 = 150 合計:150
sum に各配列要素の値 data[i]を順次加算していく
配列要素の合計 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
#include <stdio.h>
int main(void) {
int i, sum;
int data[5] = {10, 20, 30, 40, 50};
sum = 0;
for(i = 0; i < 5; i++){ ①
printf("%d + %d = ", sum, data[i]);
sum += data[i]; ②
printf("%d¥n", sum); ③ }
printf("合計:%d¥n", sum);
return 0;
}
配列の利用
配列を使った計算
i = 0 のとき① sum = 0, data[0] = 10 を表示② sumにdata[0]が加算されて10に
③ sum = 10 が表示される
i = 1 のとき
① sum = 10, data[1] = 20 を表示
② sumにdata[1]が加算されて30に
③ sum = 30 が表示される
i = 2 のとき
① sum = 30, data[2] = 30 を表示
② sumにdata[2]が加算されて60に
③ sum = 60 が表示される
i = 4 のとき
① sum = 100, data[1] = 50 を表示
② sumにdata[4]が加算されて150に
③ sum = 150 が表示される
実行結果 0 + 10 = 10 10 + 20 = 30 30 + 30 = 60 60 + 40 = 100 100 + 50 = 150 合計:150
配列の利用
配列利用の注意
添字の値に注意する
配列の大きさを超えて要素を利用することはできないため,
配列の添え字は0~(要素数-1)となる
この範囲の外の添字を指定すると実行時エラーとなる
test[1] test[2] test[3] test[4]
test[0] test[5]
int test[5]; 要素数5 75
範囲外の要素に 代入してはいけない
配列の記述方法
マクロ
文字列の置換えを行うための名前
プログラム中のマクロは翻訳時に指定された文字列に 置換えられる
構文 : #define マクロ 置換する文字列
例 : #define NUM 5 プログラム中に
NUM の記述があれば,
コンパイル時に NUM を 5 に置き換える
配列の要素数など,プログラム中で頻繁に利用する定数を マクロで記述しておくと,プログラム変更(要素数変更)時に
マクロ定義を変更するだけでよい
配列へのキーボードからの入力 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
#include <stdio.h>
#define NUM 5
int main(void) {
int test[ NUM ] = {80, 60, 22, 50, 75};
int i;
for(i = 0; i < NUM ; i++){
printf("%d番目の人の点数は%dです.¥n", i + 1, test[i]);
}
return 0;
}
配列の記述方法
マクロの利用例
マクロの定義
要素数を直接書くかわりに マクロを利用
配列の要素数を変更する場合,
マクロ定義部分のみ変更すればよい
マクロは変数とは異なることに注意!
※コンパイル時にマクロ名がマクロ定義の文字列 に置換されるだけ
多次元配列
多次元配列
2次元以上に並んだ配列のこと
N次元配列の場合,N個の添字で要素を指定する
行列や表などを表現するときに便利
例:
2次元配列の例
科目 5人の学生の4科目の得点を
記録する場合
⇒ 5行4列の2次元配列で 得点を記憶できる
1行2列の要素
⇒ 2人目の学生の 第3科目の得点
※左上隅は0行0列となる
多次元配列
多次元配列の宣言(2次元配列の場合)
例
int a[2][5]; a[0][2]
a[0][3]
a[0][4]
a[1][0]
a[1][1]
112
128 116
124 120
132 int a[2][5];
メインメモリでは...
番地
1行目の要素から順番に連続して 領域が割り当てられる
行数 列数
このように宣言することで 整数データが記憶できる 箱が2×5個用意される
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
多次元配列宣言の書式(2次元配列の場合)
型名 配列名[要素数][要素数];
a[0][0]
a[0][1]
100 104 108
2次元配列の利用
2次元配列要素への値の代入
1次元配列と
同様に記述すれば 値を代入できる
2次元配列要素への値の代入 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
#include <stdio.h>
int main(void) {
int i,j;
int a[2][5];
a[0][3] = 10;
i = 1; j = 2;
a[i][j] = 30;
printf("a[%d][%d] = %d¥n", 0, 3, a[0][3]);
printf("a[%d][%d] = %d¥n", i, j, a[i][j]);
return 0;
}
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
10
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
1次元配列と同様に 30 要素番号を指定して 値を代入できる 2次元配列要素への値の代入
配列名[添字][添字] = 式;
2次元配列の利用
2次元配列の初期化
2次元配列の初期化 1:
2:
3:
4:
5:
6:
7:
8:
#include <stdio.h>
int main(void) {
int a[2][5] = { {10, 20, 30, 40, 50}, {11, 21, 31, 41, 51} };
… return 0;
}
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
40 50
30 20
10
41 51
31 21
11
行ごとに
{ }で囲む
多次元配列宣言の書式(2次元配列の場合)
型名 配列名[要素数][要素数] = { { 値00, 値01, … }, { 値10, 値11, … },
:
{ 値(n-1)0, 値(n-1)1, … } };
カンマ 忘れずに
2次元配列要素の値の出力 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdio.h>
#define SUB 2
#define NUM 5 int main(void) {
int d[SUB][NUM];
int i,j;
d[0][0] = 80; d[0][1] = 60; d[0][2] = 22;
d[0][3] = 50; d[0][4] = 75;
d[1][0] = 90; d[1][1] = 55; d[1][2] = 68;
d[1][3] = 72; d[1][4] = 58;
for(i = 0; i < NUM; i++){
printf("%d番目の人の国語の点数は%dです.¥n",i+1, d[0][i] );
printf("%d番目の人の数学の点数は%dです.¥n",i+1, d[1][i] );
}
return 0;
}
2次元配列の利用
2次元配列の利用例 : 配列要素の値を出力
ここでは,配列の0行を国語の得点,1行を数学の得点,
各列を各学生に対応させている
d[0][i] ← 国語の得点 d[1][i] ← 数学の得点
i ← 各学生(0,1,…,4)
科目数のマクロ定義 人数のマクロ定義
科目数×人数の2次元配列を用意
国語(0行目)の得点を代入 数学(1行目)の得点を代入
列(学生)に関する繰り返し 国語の得点を出力 数学の得点を出力 実行結果
1番目の人の国語の点数は80です.
1番目の人の数学の点数は90です.
2番目の人の国語の点数は60です.
2番目の人の数学の点数は55です.
3番目の人の国語の点数は22です.
3番目の人の数学の点数は68です.
4番目の人の国語の点数は50です.
4番目の人の数学の点数は72です.
5番目の人の国語の点数は75です.
5番目の人の数学の点数は59です.
2次元配列の行ごとの参照 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdio.h>
int main(void) {
int i,j;
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%2d", a[i][j]);
}
printf("¥n");
}
return 0;
}
i は行方向,
j は列方向を 制御している
2次元配列の利用
行ごとの参照
i = 0
i = 1
i = 2
j = 0 j = 1 j = 2
a[0][0] a[0][1] a[0][2]
a[1][0] a[1][1] a[1][2]
2 3 1
5 6 4
a[2][0] a[2][1] a[2][2]
9 8
7
実行結果 1 2 3 4 5 6 7 8 9
2次元配列の 行ごとに 値を出力 j の繰り返しが終わるごとに改行を出力することで
2次元配列の行ごとの参照 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdio.h>
int main(void) {
int i,j;
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%2d", a[i][j]);
}
printf("¥n");
}
return 0;
}
2次元配列の利用
行ごとの参照
実行結果 1 2 3 4 5 6 7 8 9
i = 0
j = 0 a[0][0] = 1 が出力される j = 1 a[0][1] = 2 が出力される j = 2 a[0][2] = 3 が出力される 改行が出力される
i = 1
j = 0 a[1][0] = 4 が出力される j = 1 a[1][1] = 5 が出力される j = 2 a[1][2] = 6 が出力される 改行が出力される
i = 2
j = 0 a[2][0] = 7 が出力される j = 1 a[2][1] = 8 が出力される j = 2 a[2][2] = 9 が出力される 改行が出力される
処理の流れ
2次元配列の列ごとの参照 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdio.h>
int main(void) {
int i,j;
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%2d", a[j][i]);
}
printf("¥n");
}
return 0;
}
i は列方向,
j は行方向を 制御している
2次元配列の利用
列ごとの参照
i = 0
i = 1
i = 2
j = 0 j = 1 j = 2
a[0][0] a[0][1] a[0][2]
a[1][0] a[1][1] a[1][2]
2 3 1
5 6 4
a[2][0] a[2][1] a[2][2]
8 8
7
実行結果 1 4 7 2 5 8 3 6 9
2次元配列の 列ごとに 値を出力
2次元配列の列ごとの参照 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
#include <stdio.h>
int main(void) {
int i,j;
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%2d", a[j][i]);
}
printf("¥n");
}
return 0;
}
2次元配列の利用
列ごとの参照
実行結果 1 4 7 2 5 8 3 6 9
i = 0
j = 0 a[0][0] = 1 が出力される j = 1 a[1][0] = 4 が出力される j = 2 a[2][0] = 7 が出力される 改行が出力される
i = 1
j = 0 a[0][1] = 2 が出力される j = 1 a[1][1] = 5 が出力される j = 2 a[2][1] = 8 が出力される 改行が出力される
i = 2
j = 0 a[0][2] = 3 が出力される j = 1 a[1][2] = 6 が出力される j = 2 a[2][2] = 9 が出力される 改行が出力される
処理の流れ
講義のまとめ
配列
同じ型の値を複数格納できる
配列一つ一つを配列要素という
要素番号は
0から始まる
配列への代入,初期化,入力
配列の利用
配列は繰り返し処理(主にfor文)により扱われる
多次元配列
2次元以上の配列