内 容
- 配列
- 配列の初期化
- 配列と繰り返し処理
- 配列のコピー
- マクロ定義
- 2次元配列
配列
1000個、2000個といった大量のデータを高速に処理することはコンピュータの得意とするところです。では、この大量のデータをプログラムの中でどのように表現したらよいでしょうか。
例えば、ある学校の全生徒1200人分の成績を管理するプログラムを作ろうと思います。各生徒の試験結果を変数に格納して処理するためには、1200個分の変数を用意する必要があります。変数名は、m1, m2, m3、・・・、m1200としました。1200個分の変数をコーディングするのも大変ですが、データの追加や削除などはそれ以上に面倒なプログラムを書かなければならなくなりそうです。数万人の市民や通販サイトの顧客を扱うデータを処理するプログラムならば、実現すること自体、現実的ではなさそうです。
このような大量のデータをまとめて扱うために、
配列(Array)と呼ばれる仕組みが用意されています。配列は、同じ型の変数がいくつも一列に連なった構造をしたもので、一つの名前、
配列名を使ってまとめて操作することができます。
例えば、100個の整数値からなるデータを配列を使って表わしてみましょう。
int m[100];
と記述すると、int型の値100個分を格納することができる配列mが用意されます。配列mの一つ一つ変数を参照するときには、次のように記述します。一つ目の変数は、
m[0]
2つ目の変数は、
m[1]
3つ目の変数は、
m[2]
・・・
100個目の変数は、
m[99]
として指定することができます。
一つ一つの変数を
配列要素もしくは単に
要素(element)と呼びます。配列要素を参照する場合は、配列名の後に角カッコ[ ]とその中に先頭から何番目の要素かを記します。この先頭から何番目を示す数値を
添字(index)と言います。添字は0からはじまります。例えば、100個分の配列を宣言したときは、添字の範囲は0から99になります。
配列は、同じデータ型の変数が一列に並んだもの。
添字は0から始まる。
次のプログラムc7-1a.cは、5人の生徒のテストの得点を扱うために配列を使った例です。
c7-1a.c
#include <stdio.h>
int main(void)
{
int m[5]; // 5個の得点を格納する配列の宣言
int sum = 0; // 合計点
double avg; // 平均点
m[0] = 70; //0番目の要素に値を代入
m[1] = 90;
m[2] = 85;
m[3] = 75;
m[4] = 95;
sum = m[0] + m[1] + m[2] + m[3] + m[4];
avg = (double)sum/5;
printf("合計点 %d¥n", sum);
printf("平均点 %.1f¥n", avg);
return 0;
}
配列を宣言するときの角カッコ[ ]の中の数字は、配列の個数を、
配列を参照するときの角カッコ[ ]の中の数字は、何番目の要素であるかを示す。
配列の初期化
配列の初期化
配列の宣言と同時に各要素に値を設定することができます。これを
配列の初期化と言います。左辺に各要素の値をカンマ(,)で区切って並べ、それを波カッコ{}で囲います。
先の5人の生徒の得点を扱うプログラム例の配列を初期化で書き直した例を以下に示します。
例 c7-1b.c
#include <stdio.h>
int main(void)
{
int m[5] = {70, 90, 85, 75, 95}; // 得点を格納する配列の宣言
int sum = 0; // 合計点
double avg; // 平均点
sum = m[0] + m[1] + m[2] + m[3] + m[4];
avg = (double)sum/5;
printf("合計点 %d¥n", sum);
printf("平均点 %.1f¥n", avg);
return 0;
}
配列の初期化のいろいろ
- すべての要素を0で初期化する例
- int m[5] = {0};
- 残りの要素だけ0で初期化する例
- int m[10] = {0, 1, 2, 3, 4, };
※ 変数宣言した後で、まとめて値を代入することはできない
m[] = {10, 20, 30, 40, 50}; ×これは誤り
m = {10, 20, 30, 40, 50}; ×これも誤り
変数宣言してもその値は0にはならない。
注) C言語の仕様では、変数宣言をした時点でコンパイラがメモリをクリアしなければならないとは規定されていません。それ以前に実行したプログラムが同じメモリ領域を使っていてその残骸が残っていることもあります。変数が0であることを前提とする手続きの場合は、それ以前に0を代入しておくか、0で初期化しておかなければなりません。
配列とくり返し処理
くり返し処理を利用しないで配列を扱う
5人の生徒のテストの得点を入力して、得点一覧とその合計と平均を表示するプログラムを配列を使って実現してみます。
例 c7-2a.c
#include <stdio.h>
int main(void)
{
int m[5]; // 得点
int sum = 0; // 合計
double avg; // 平均
// 得点の読み込み
printf("1人目の得点>> "); scanf("%d", &m[0]);
printf("2人目の得点>> "); scanf("%d", &m[1]);
printf("3人目の得点>> "); scanf("%d", &m[2]);
printf("4人目の得点>> "); scanf("%d", &m[3]);
printf("5人目の得点>> "); scanf("%d", &m[4]);
// 得点の表示
printf("1人目 %d点¥n", m[0]);
printf("2人目 %d点¥n", m[1]);
printf("3人目 %d点¥n", m[2]);
printf("4人目 %d点¥n", m[3]);
printf("5人目 %d点¥n", m[4]);
sum = m[0] + m[1] + m[2] + m[3] + m[4]; // 合計を求める
avg = (double)sum/5; // 平均を求める
printf("合計点 %d¥n", sum);
printf("平均点 %.1f¥n", avg);
return 0;
}
繰り返し処理を使った配列
5人分の得点を読み込み、表示をするために
printfやscanfが繰り返し登場してきます。1人目の得点、2人目の得点、・・・、5人目の得点と入力するに従い、配列の添字も0、1、・・・、4と1ずつ増えています。この添字に、繰り返し構文のカウンタ変数を当てはめれば、生徒の人数に関係なく配列に値を読み込んだり、配列の値を表示するプログラムができそうです。
下記のプログラム例では、繰り返し処理にfor文を使い、そのカウンタ変数iを配列の添字に使っています。
例 c7-2b.c
#include <stdio.h>
int main(void)
{
int m[5]; // 得点
int sum = 0; // 合計
double avg; // 平均
int i;
// 得点の読み込み
for (i=0; i<5; i++) {
printf("%d人目の得点>> ",i); scanf("%d", &m[i]);
}
// 得点の表示
for (i=0; i<5; i++) {
printf("%d人目 %d点¥n", m[i]);
sum += m[i]; // 合計 sum=sum+dt[i]と同じ
}
avg = (double)sum/5; // 平均
printf("合計点 %d¥n", sum);
printf("平均点 %.1f¥n", avg);
return 0;
}
配列のコピー
配列maとmbがあり、配列maの内容を配列mbにコピーしたいと思い、次のように記述しました。
mb = ma ×これは誤り
しかし、これは正しくありません。面倒でも各要素を一つずつコピーする必要があります。
mb[0] = ma[0];
mb[1] = ma[1];
・・・
c7-3.c
#include <stdio.h>
int main(void)
{
int ma[10]={1,2,3,4,5,6,7,8,9,10}; //コピー元
int mb[10]; //コピー先
int i;
for (i=0; i<10; i++) {
mb[i] = ma[i]; //要素のコピー
}
for (i=0; i<10; i++) {
printf("ma[%d]=%2d mb[%d]=%2d¥n", i,ma[i],i,mb[i]);
}
return 0;
}
配列の内容をコピーするためには、各要素を一つずつコピーする。
マクロ定義
配列を利用したプログラムでは、その要素数の変更が生じると複数箇所の書き換えが必要になる可能性があります。また、変更作業が面倒なだけはなくバグを発生させる原因にもなります。このような場合は、プリプロセッサを利用して要素数を定数として事前に定義して利用することができます。変更が生じてもこの部分のみの変更で済ますことができます。
#define マクロ名 文字列
マクロ名はコンパイル前に自動的にプログラム中のマクロ名を文字列に置き換えます。マクロ名には慣習的に半角大文字を使います。
下記は前節のプログラムc7-3.cをマクロを使って書き換えたものです。
c7-4.c
#include <stdio.h>
#define N 10 // マクロ定義
int main(void)
{
int ma[N]={1,2,3,4,5,6,7,8,9,10}; //コピー元
int mb[N]; //コピー先
int i;
for (i=0; i<N; i++) {
mb[i] = ma[i]; //要素のコピー
}
for (i=0; i<N; i++) {
printf("ma[%d]=%2d mb[%d]=%2d¥n", i,ma[i],i,mb[i]);
}
return 0;
}
2次元配列
2重ループと2次元配列
1次元配列は変数を一列に並べた構造をしていましたが、更にこれを何段かに重ねた構造をした配列を2次元配列と言います。
例えば、3つの要素を持つ1次元配列を2段重ねた2次元配列の場合は、
int m[2][3];
と宣言します。

これを、2行3列の2次元配列と呼びます。
それぞれの要素は2つの添え字を使って行と列を指定することでを参照することができます。例えば、左上の1行1列目の要素ならば、
m[0][0]
2行3列目の要素ならば
m[1][2]
となります。
2次元配列の初期化
2次元配列の初期化は、各要素をカンマで区切りそれを行ごとに波カッコで囲い、さらに、その各行をカンマで区切り、全体を波カッコ{}で囲います。
例1)
int m[2][3] = {{11,12,13}, {21,22,23}};
例2)
int m[3][2] = {{11,12}, {21,22}, {31,32}};
以下は、2行3列の2次元配列を整数値で初期化し、その各要素の内容を表示するプログラム例です。
c7-2.c
#include <stdio.h>
int main(void)
{
int m[2][3] = {{10,11,12}, //1行目の初期化
{21,22,23}}; //2行目の初期化
int i,j;
for (i=0; i<2; i++) {
for (j=0; j<3; j++) {
printf("m[%d][%d]=%d", i,j,m[i][j]);
}
}
return 0;
}
二次元配列の宣言 データ型 配列名[行の要素数][列の要素数]
二次元配列の要素の参照 配列名[行位置][列位置]
expand_lessBack to TOP