C言語のきほん|同じ型のデータをまとめる配列

たくさんの値も、ひとまとまりでスッキリ管理。配列を覚えると、C言語のデータ操作がぐっと楽になります

C言語でプログラムを書いていると、同じ種類のデータをいくつもまとめて扱いたい場面がよく出てきます。
たとえば、5人分の点数、7日分の気温、10個の商品価格のように、同じ型の値を複数保存したいことがあります。

もし配列を使わずにこれを処理しようとすると、score1、score2、score3 のように変数をたくさん用意しなければならず、プログラムが長くなってしまいます。
しかも、あとからデータ数が増えたときの修正も大変です。

そんなときに便利なのが 配列 です。
配列を使うと、同じ型のデータをひとまとめにして管理できるようになります。
その結果、プログラムが読みやすくなり、繰り返し処理とも組み合わせやすくなります。

配列は、C言語を学ぶうえでとても大切な仕組みのひとつです。
最初は少し見慣れない書き方に感じるかもしれませんが、考え方はそれほど難しくありません。
同じ型のデータを、番号つきの箱に順番に入れていくイメージを持つと、とても分かりやすくなります。

ここでは、まず配列とは何かをやさしく整理しながら、1次元配列の基本的な使い方を見ていきます。
宣言、代入、参照、初期化の流れをひとつずつ確認しながら、配列の基本をしっかり身につけていきましょう。

配列とは何か

配列とは、同じ型のデータをまとめて扱うための仕組みです。
たとえば int 型の整数を5個、float 型の小数を10個、char 型の文字を20個というように、同じ型の値を並べて保存できます。

配列の大きな特徴は、各要素に番号がついていることです。
この番号を 添字 と呼びます。
C言語では、添字は 0 から始まります。

たとえば、要素数が5個の配列なら、使える添字は次のようになります。

要素の位置添字
1番目0
2番目1
3番目2
4番目3
5番目4

ここはとても大事なポイントです。
C言語では 1 からではなく 0 から始まるので、最初は少し注意が必要です。

配列を使うと何が便利なのか

配列を使わない場合、同じ種類のデータをたくさん扱うには、それぞれ別の変数を用意しなければなりません。

たとえば5人分の点数を保存したいとき、配列を使わないなら次のようになります。

int score1, score2, score3, score4, score5;

これでも保存はできますが、数が増えるととても管理しづらくなります。
また、繰り返し処理でまとめて扱うことも難しくなります。

一方、配列を使えば次のように書けます。

int score[5];

これだけで、5個分の整数をまとめて扱えます。
さらに、for文と組み合わせれば、1つずつ順番に処理することも簡単です。

配列の次元とは

配列には 次元 があります。
最初は 1次元配列 をしっかり理解することが大切ですが、全体像も軽く知っておくと分かりやすいです。

種類イメージ
1次元配列縦に1列に並んだ箱
2次元配列縦と横に並んだ表
3次元配列縦・横・奥行きに並んだ箱の集まり

たとえば、1次元配列は「点数の一覧」のようなイメージです。
2次元配列は「表」や「座席表」のようなイメージです。
3次元配列になると、さらに奥行きが加わったような構造になります。

図でイメージすると、次のように考えられます。

最初の学習では、まず 1次元配列 をしっかり押さえれば大丈夫です。

1次元配列とは

1次元配列は、同じ型のデータを一直線に並べた配列です。
見た目としては、番号つきの箱が横一列または縦一列に並んでいるように考えると分かりやすいです。

たとえば、5個の整数を入れる 1次元配列 は、次のようなイメージになります。

この箱ひとつひとつに整数値を入れていきます。
そして、scores[0] や scores[1] のように、添字を使って個々の要素にアクセスします。

配列を使う流れ

配列を使うときの基本的な流れは、変数とよく似ています。
大きく分けると次の4つです。

手順内容
宣言配列を用意する
代入各要素に値を入れる
参照各要素の値を取り出して使う
初期化宣言と同時に値を入れる

この順番で考えると理解しやすいです。

配列の宣言

まずは配列を宣言します。
整数を5個保存したいなら、次のように書きます。

int data[5];

この意味は、int 型の要素を5個持つ配列 data を用意するということです。

ここでの 5 は要素数です。
つまり、使える添字は 0 から 4 までになります。

配列の宣言を表で整理すると、次のようになります。

記述意味
int data[5];int型の要素を5個持つ配列
double price[10];double型の要素を10個持つ配列
char name[20];char型の要素を20個持つ配列

配列の要素に値を代入する

宣言した配列には、添字を使って値を代入できます。

data[0] = 10;
data[1] = 20;
data[2] = 30;

このように書くと、配列 data のそれぞれの箱に値が入ります。

図にすると次のようなイメージです。

このように、配列名だけではなく、必ず添字をつけて個々の要素を指定します。

配列の要素を参照する

配列の要素を使いたいときも、添字を使います。

printf("%d\n", data[0]);
printf("%d\n", data[1]);
printf("%d\n", data[2]);

これで、data[0]、data[1]、data[2] に入っている値を表示できます。

配列では、変数1個を使うのではなく、
配列名 + 添字
で要素を指定するのが基本です。

配列の初期化

配列は、宣言と同時に初期値を入れることもできます。
これを 初期化 といいます。

int data2[] = {10, 20, 30, 40, 50};

この書き方では、要素数を省略しています。
なぜ省略できるかというと、初期値が5個書かれているので、コンパイラが自動的に要素数を判断してくれるからです。

この場合、data2 の要素数は 5 になります。

表で整理すると、こうなります。

記述意味
int a[3] = {1, 2, 3};要素数3の配列を初期化
int a[] = {1, 2, 3};初期値の個数から要素数を自動決定
int a[5] = {1, 2};残りは 0 で初期化される

サンプルプログラムで見てみよう

元のサンプルでは scores という配列を使っていました。
ここでは内容を変えて、5日分の来店人数を保存するシンプルな例にしてみます。
表示メッセージやコメントもすべて日本語にしています。

サンプルプログラム

ファイル名:10_1_1.c

#include <stdio.h>

int main(void)
{
    // 配列の宣言
    int visitors[5];    // 5日分の来店人数を保存する配列

    // 配列の初期化
    int visitors2[] = {12, 15, 9, 18, 20};    // 初期値を使って配列を作る

    // 配列に値を代入
    visitors[0] = 12;    // 1日目の来店人数
    visitors[1] = 15;    // 2日目の来店人数
    visitors[2] = 9;     // 3日目の来店人数

    // 配列の要素を表示
    printf("%d\n", visitors[0]);
    printf("%d\n", visitors[1]);
    printf("%d\n", visitors[2]);

    printf("%d %d %d %d %d\n",
           visitors2[0], visitors2[1], visitors2[2], visitors2[3], visitors2[4]);

    return 0;
}

実行結果の例

12
15
9
12 15 9 18 20

このプログラムで確認したいこと

このプログラムには、配列の基本がいくつも入っています。
順番に見ていきましょう。

配列の宣言

int visitors[5];

これは、整数を5個保存できる配列 visitors を宣言しています。
まだこの時点では、どの要素にどんな値が入るかは決まっていません。

配列の初期化

int visitors2[] = {12, 15, 9, 18, 20};

こちらは、宣言と同時に値を入れています。
初期値が5個あるので、要素数は自動的に5になります。

要素への代入

visitors[0] = 12;
visitors[1] = 15;
visitors[2] = 9;

配列 visitors の各要素に値を代入しています。
このとき、添字 0 が1番目、添字 1 が2番目、添字 2 が3番目を表します。

要素の参照

printf("%d\n", visitors[0]);

これは、配列の中にある値を取り出して表示しています。
代入するときも、使うときも、どちらも添字が必要です。

添字が0から始まる理由に慣れよう

配列学習で最初に戸惑いやすいのが、添字が0から始まることです。
たとえば5個の要素がある配列では、最後の添字は 5 ではなく 4 です。

要素数使える添字
1個0
2個0 ~ 1
5個0 ~ 4
10個0 ~ 9

このルールに慣れていないと、つい最後に data[5] のように書いてしまうことがあります。
でも、要素数が5なら最後は data[4] です。
ここはとても重要です。

添字の範囲外を使うと危険

配列では、用意した要素数の範囲内でしか使ってはいけません。
たとえば次の配列があるとします。

int data[5];

このとき使えるのは data[0] から data[4] までです。
data[5] や data[-1] のような指定は不正です。

このような範囲外アクセスは、予想外の動作やバグの原因になります。
C言語では特に注意が必要です。

配列と繰り返し処理は相性がよい

配列が便利なのは、for文などの繰り返し処理と相性がよいからです。
たとえば、5個の要素を順番に表示するなら、次のように書けます。

for (int i = 0; i < 5; i++) {
    printf("%d\n", visitors2[i]);
}

これなら、同じような printf を何回も書かなくて済みます。
配列は、単に値をまとめるだけでなく、ループでまとめて処理しやすくする仕組みでもあります。

配列を使わない場合との比較

同じ5件のデータを、配列あり・配列なしで比べると違いが見えやすいです。

配列を使わない場合

int a1 = 12;
int a2 = 15;
int a3 = 9;
int a4 = 18;
int a5 = 20;

配列を使う場合

int a[] = {12, 15, 9, 18, 20};

配列を使ったほうが、値がまとまりとして見えやすく、あとでループ処理もしやすいです。

1次元配列の書き方を整理しよう

ここまでの内容を、よく使う書き方として表にまとめます。

目的書き方
配列を宣言するint data[5];
要素に値を代入するdata[0] = 10;
要素の値を参照するprintf("%d\n", data[0]);
初期化しながら宣言するint data[] = {10, 20, 30};

この4つを押さえると、1次元配列の基本はかなり見えてきます。

初期化と代入の違い

配列の学習では、初期化と代入の違いも意識しておくとよいです。

項目タイミング
初期化宣言と同時int a[] = {1, 2, 3};
代入宣言したあとa[0] = 1;

初期化は、配列を作るときに最初の値をまとめて入れる方法です。
代入は、あとから各要素に値を入れる方法です。

変数と配列の違い

普通の変数と配列の違いも整理しておきましょう。

項目普通の変数配列
保存できる値1個複数個
取り出し方変数名配列名と添字
用途単一の値を扱う同じ型の複数データをまとめる

つまり、配列は「たくさんの同じ型の変数をまとめて扱う仕組み」と考えると分かりやすいです。

これから配列を学ぶときの視点

配列を学び始めたばかりのときは、次の3つを意識すると理解しやすいです。

視点内容
何個分の箱があるか要素数を見る
どの箱を使うか添字を見る
何を入れて何を取り出すか代入と参照を見る

この3つを落ち着いて確認すれば、配列のコードはかなり読みやすくなります。

配列の学習でよくあるつまずき

配列でつまずきやすいポイントも見ておきましょう。

つまずきやすい点内容
添字を1から始めてしまうC言語では0から始まる
要素数と最後の添字を混同する要素数5なら最後は4
配列名だけで要素にアクセスしようとする添字が必要
範囲外を使ってしまうバグの原因になる

このあたりを意識しておくと、配列に対する苦手意識がかなり減ってきます。

配列は今後の学習の土台になる

1次元配列は、それだけでも十分に便利ですが、今後さらに学ぶ2次元配列、文字列、関数への配列の受け渡し、ポインタなどにもつながっていきます。
つまり、配列はこの先のC言語学習の土台になる重要なテーマです。

最初のうちは、難しく考えすぎず、
同じ型の値を、番号つきの箱に並べて保存する仕組み
としてつかんでおけば大丈夫です。

配列を使えるようになると、複数のデータをまとめて扱えるようになり、C言語らしいプログラムがぐっと書きやすくなります。