今回は《配列について学ぼう》というテーマで記事をまとめます。
「配列」を習得すると、プログラムを組む上でのバリエーションがかなり増えます。頑張りましょう!
尚、現在執筆中のC言語入門記事は以下の人を対象としています。
- プログラミング未経験の人
- C言語プログラミングの学習をこれから始めたい人
- C言語プログラミングの学習を始めたばかりの人
配列について学ぼう
配列とは
配列とは「同じ型の変数の塊」みたいなものです。
少し具体的に言うと、通常の変数は「1つの変数に1つのデータを保存しておけるもの」であったのに対し、配列変数は「1つの変数に複数のデータを保存しておけるもの」となります。
配列の要素と添字
配列のデータ1つ1つのことを「要素」と呼びます。
そして、配列の要素にはそれぞれ番号が割り振られ、要素の値を取得したり、要素に値を代入するにはその番号を指定します。この番号のことを「添字(そえじ)」と呼びます。
また、C言語において、「添字」は0番から始まります。つまり、要素数がN個である配列の最後の添字は「N-1」となります。
※補足※「オリジン」について
ソフトウェア開発において、連番を数えるときに「0番から始まること」を「0オリジン」と呼び、「1番から始まること」を「1オリジン」と呼びます。
配列の変数定義と使用方法
それでは、配列の変数定義と使用方法について解説していきます。
まず、基本的な書式は次のようになります。
/* 配列の変数定義 */ 変数の型 変数名[要素数];
/* 配列の使用方法 */ 変数名[添字] = 値;
上記を見ていただければわかる通り、要素数と添字以外は通常の変数と同じ方法で定義及び使用することができます。
サンプルを用意したので確認してみてください。
#include<stdio.h> void main(){ int array[5]; array[0] = 8; array[1] = 2; array[2] = 12; array[3] = 7; array[4] = 4; printf("array[0] = %d\n", array[0]); printf("array[1] = %d\n", array[1]); printf("array[2] = %d\n", array[2]); printf("array[3] = %d\n", array[3]); printf("array[4] = %d\n", array[4]); }
配列の初期化
通常の変数では定義と同時に値を代入する「初期化」が実装可能でした。配列でも同様に「初期化」を実装することができます。
書式は次のようになります。
変数の型 変数名[要素数] = { 値0, 値1, 値2, ... };
具体的なコード例は次のようになります。
int values[3] = { 2, 5, 8 };
要素数を省略して初期化
配列は要素数を省略して初期化することができます。この場合、初期値の数が要素数となります。
int values[] = { 2, 5, 8 };
上記サンプルの場合、valuesの要素数は3個となります。
要素数より少ない数の初期値を指定
配列の初期化は、定義されている要素数よりも少ない数の初期値を指定することもできます。例えば、次のような場合です。
int values[6] = { 2, 5, 8 };
上記サンプルの場合、valuesの0~2番目は各初期値が代入されますが、3~5番目は初期化されていない状態となります。(開発環境によっては、初期化されていない変数は『どんな値が格納されているかわからない状態』となるので注意してください。)
多次元配列
多次元配列とは
C言語を始めとする様々な言語では、「配列の配列」を定義することができます。
この「配列の配列」を「2次元配列」と呼びます。当然ながら、「配列の配列の配列の・・・」と、3次元以上の配列も定義できる為、2次元以上の配列のことを「多次元配列」と呼びます。
まずは、一番簡単な2次元配列を使って多次元配列のイメージを掴んでもらいたいと思います。
通常の配列はただの「連続データ」といったイメージでしたが、2次元配列のイメージは「行列データ」となります。
そして、3次元配列は「複数の行列データ」、4次元配列はさらにそれを複数もつ配列といったイメージになります。
多次元配列の変数定義と使用方法
多次元配列の変数定義と使用方法の基本的な書式は次のようになります。
/* 多次元配列の変数定義 */ 変数の型 変数名[要素数1][要素数2][要素数3]...[要素数N];
/* 多次元配列の使用方法 */ 変数名[添字1][添字2][添字3]...[添字N] = 値;
上記を見ていただければわかる通り、多次元配列は1次元配列と比べて要素数と添字の個数が増えただけであり、変数定義も使用方法も基本的には同じです。
2次元配列を例にして学習
上記の書式だとイマイチわからない人もいるかと思います。
なので、まずは一番簡単な2次元配列に着目して変数定義と使用方法を学びましょう。2次元配列の基本的な書式は次のようになります。
/* 2次元配列の変数定義 */ 変数の型 変数名[要素数1][要素数2];
/* 2次元配列の使用方法 */ 変数名[添字1][添字2] = 値;
サンプルを用意したので確認してみてください。
#include<stdio.h> void main(){ int array[2][3]; array[0][0] = 8; array[0][1] = 2; array[0][2] = 12; array[1][0] = 7; array[1][1] = 4; array[1][2] = 4; printf("array[0][0] = %d\n", array[0][0]); printf("array[0][1] = %d\n", array[0][1]); printf("array[0][2] = %d\n", array[0][2]); printf("array[1][0] = %d\n", array[1][0]); printf("array[1][1] = %d\n", array[1][1]); printf("array[1][2] = %d\n", array[1][2]); }
多次元配列の初期化
次に、多次元配列の「初期化」について、2次元配列と3次元配列を例に挙げて解説します。
2次元配列の初期化
2次元配列における初期化の書式は次のようになります。
変数の型 変数名[要素数1][要素数2] = { { 値00, 値01, 値02, ... }, { 値10, 値11, 値12, ... } };
上記の書式では若干わかりにくいと思います。
意味合いとしては、次のようなコードと同じです。
変数の型 変数名[要素数1][要素数2]; 変数名[0][0] = 値00; 変数名[0][1] = 値01; 変数名[0][2] = 値02; ... 変数名[1][0] = 値10; 変数名[1][1] = 値11; 変数名[1][2] = 値12; ...
具体的なコード例は次のようになります。
int values[2][3] = { { 2, 5, 8 }, { 5, 3, 9 } };
3次元配列の初期化
3次元配列の初期化も2次元配列とほぼ同じです。書式は次のようになります。
変数の型 変数名[要素数1][要素数2][要素数3] = { { { 値000, 値001, 値002, ... }, { 値010, 値011, 値012, ... } }, { { 値000, 値001, 値002, ... }, { 値010, 値011, 値012, ... } } };
具体的なコード例は次のようになります。
int values[2][3][4] = { { { 2, 5, 8, 9 }, { 5, 3, 9, 1 }, { 7, 6, 4, 2 } }, { { 1, 3, 4, 7 }, { 4, 1, 6,11 }, { 3, 6, 1, 8 } } };
要素数を省略して初期化
多次元配列は先頭のみ要素数を指定せずに初期化することができます。裏を返せば、2つ目以降の要素は要素数の指定が必須となります。
int values2d[][3] = { { 2, 5, 8 }, { 3, 9, 4 } };
上記サンプルの場合、values2dの先頭の要素数は2個となります。
要素数より少ない数の初期値を指定
多次元配列の初期化もまた、定義されている要素数よりも少ない数の初期値を指定することができます。
int values2d[3][5] = { { 2, 5, 8, 1, 4 }, { 3, 9, 4 } };
上記サンプルの場合、初期化の実行結果は次のようになります。
- values2d[0][0~5]は初期化される(各初期値が代入される)
- values2d[1][0~2]は初期化される(各初期値が代入される)
- values2d[1][3~4]は初期化されない
- values2d[2][0~4]は初期化されない
【応用】配列とループ制御文の組み合わせ
配列はループ制御文と組み合わせると簡潔なコードが書けます
配列はループ制御文と組み合わせることで、何も考えずに記述すると冗長になってしまうコードを簡潔なコードへと書き換えることができます。
例えば、『要素数が9個の配列に"3の段"の結果を格納する』というプログラムを作成する場合、何も考えずに記述すると次のようになると思います。
int array[9]; array[0] = 3; array[1] = 6; array[2] = 9; array[3] = 12; array[4] = 15; array[5] = 18; array[6] = 21; array[7] = 24; array[8] = 27;
しかし、ループ制御文を使用すると次のように書くことができるワケです。
int i; int array[9]; for( i = 0; i < 9; i++ ) { array[i] = 3 * (i + 1); }
随分簡潔なコードになりましたね。簡潔なコードは仕様変更に対して柔軟に対応できます。
例えば、今回は『要素数が9個の配列に"3の段"の結果を格納する』という仕様でプログラムを作成しましたが、それに対して「"4の段"に変更してほしい」という要求があった場合に修正量は後者のほうが少ないですね。
勿論、今回のプログラムの場合は前者・後者どちらでも大した修正量ではありません。しかし、『要素数が100個の配列に値を代入する』といったようなプログラムの場合、その修正量は一目瞭然となりますね。
配列の簡単な表示方法
ここでは、ループ制御文を利用した”配列の簡単な表示方法"を紹介・解説します。
その前に、まずはprintf関数についてもう少し詳しく解説をしておきたいと思います。
printf関数は『フォーマット指定子』と『引数』を記述することで変数の値を画面上に表示することができる関数であることは知っていますね。
そして、これまではこの『フォーマット指定子』と『引数』を1組のみ記述してきたと思います。
実はコレ、複数組を記述することができるのです。サンプルを用意しました。
printf("%d, %f, %c, %d", num1, flt1, chr1, num2 );
1番目の引数内のテキストに複数のフォーマット指定子が記述され、その数の分だけ2番目以降の引数が記述されていますね。
ここまで解説すると、賢い皆さんならお察しかもしれませんが、”配列の簡単な表示方法”は次のようになります。
int i; int array[10]; for( i = 0; i < 10; i++ ){ printf("array[%d] = %d\n", i, array[i] ); }
ここではコードの紹介のみ行いますが、皆さんは是非一度実行してみてくださいね。
次回は「文字列」について
文字列とは「文字型(char)の配列」です。
文字列は通常の配列と比べて少しだけ考え方が特殊です。また、文字列操作に特化した関数がいくつか用意されています。それらを紹介と解説をしたいと思います。
ご期待ください。