【C言語入門講座】9章.配列の基本(宣言・初期化・追加・要素数・多次元配列)

C言語入門レッスン

☜前の章へ 関数の呼び出し方から引数と戻り値まで
☞次の章へ 文字列を扱ってみよう


【C言語入門講座】は全13章から構成される、初心者向けのC言語学習コンテンツです。1章から13章まで学習して頂くことでC言語の基礎を学習することができます。

この記事で分かること
  1. 配列とは
  2. 配列の基本的な書き方
  3. 多次元配列(2次元配列)の書き方
  4. sizeof演算子の使い方
  5. ループで配列の値を出力する方法
  6. バブルソートのやり方

変数は、1つの変数につき、1つの値が入る箱の様なものでした。

配列は、1つの配列につき、複数の値が入る箱の様なものです。

配列の基本的な使い方から、多次元配列、バブルソートまで解説します。

配列とは

配列とは、同じ型の複数の値が1つの変数に格納されたものです。

変数

項目Aさん
身長154
変数のイメージ

変数の場合、例えばAさんの身長を変数に格納しようとすると以下のようになります。

int height = 154;

このように変数には1つの値しか格納できません。

配列

項目AさんBさんCさんDさんEさん
身長154178166144161
配列のイメージ

配列の場合は、Aさん、Bさん、Cさん、Dさん、Eさんの身長を格納することができます。

int height[] = {154, 178, 166, 144, 161};

どうですか、意外と簡単に配列を書けますよね。

配列変数の中には、上記の配列のイメージのように5つの値が入っています。

表をイメージすると分かりやすいです。

配列の基本的な書き方

※上記の青い文字から読みたい項目へ移動することができます

①配列を宣言する方法

配列の宣言
  • 型名 変数名[要素数]
int height[5];

変数の宣言とは違い、変数名の後ろに[要素数]が必要です。

要素数の分だけ値を格納することができます。

②宣言された配列を初期化する方法

配列の初期化
  • 変数名[インデックス番号] = 値
height[0] = 154;
height[1] = 178;
height[2] = 166;
height[3] = 144;
height[4] = 161;

既に宣言されている配列を初期化する方法です。

既に宣言されている配列に関しては、1つ1つインデックス番号ごとに初期化する必要があります。インデックス番号とは[0]などの数字のことです。添え字とも呼びます。

配列では1番最初の値はインデックス番号の[0]になります。
[1]は2番目、[2]は3番目になります。

代入も同様の形で行えます。

③配列の値を参照し出力する方法

配列の値を参照する方法
  • printf(“変換指定子”, 変数名[インデックス番号]);
#include <stdio.h>

int main(void) {
    int height[5];

    height[0] = 154;
    height[1] = 178;
    height[2] = 166;
    height[3] = 144;
    height[4] = 161;

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

    return 0;
}

出力結果

154 178 166 144 161

printf()関数で配列のインデックス番号を指定することで、配列の値を出力することができます。

④配列の宣言と初期化を同時に行う方法

配列を宣言と同時に初期化
  • 型名 変数名[要素数] = {0} (全要素が0で初期化される)
  • 型名 変数名[要素数] = {値, 値, …}
int height[5] = {0};
int height[5] = {154, 178, 166, 144, 161};

配列の宣言と初期化を同時に行うこともできます。

右辺を{0}とすると全ての要素に0が代入されます。値を指定したい場合は要素数分の値を書く必要があります。

要素数は省略可能で以下のように書くこともできます。

int height[] = {154, 178, 166, 144, 161};

多次元配列(2次元配列)の書き方

※上記の青い文字から読みたい項目へ移動することができます

①多次元配列のイメージ

配列

項目AさんBさんCさんDさんEさん
身長154178166144161
配列のイメージ

2次元配列

項目AさんBさんCさんDさんEさん
出席番号58131822
身長154178166144161
2次元配列のイメージ

配列のイメージに出席番号が加わりました。

配列の場合、身長だけが保存されていたため、誰の身長かを特定することが出来ませんでした。

出席番号が分かれば、どの出席番号の人の身長かを特定することができます。
それを実現するために2次元配列を使うことができます。

②多次元配列の宣言と初期化を同時にする方法

多次元配列を初期化する方法
  • 型名 変数名[][] = {{値, 値, …},{値, 値, …}}
int height[2][5] = {{5,8,13,18,22},{154, 178, 166, 144, 161}};

配列の宣言と初期化は次のように行いました。

int height[5] = {154, 178, 166, 144, 161};

多次元配列の場合は、[]の数が増えるだけです。

出席番号と身長を格納したいので左の[]は要素数が2です。
5人分のデータを格納したいので右の[]は要素数が5です。

[2][5]と書くと、5つのデータを格納できる配列が2つできます。

③多次元配列の値を参照し出力する方法

多次元配列の値を参照する方法
  • 変数名[インデックス番号][インデックス番号]
#include <stdio.h>

int main(void) {
    int height[2][5] = {{5,8,13,18,22},{154, 178, 166, 144, 161}};

    printf("出席番号\n");
    printf("%d\n", height[0][0]);
    printf("%d\n", height[0][1]);
    printf("%d\n", height[0][2]);
    printf("%d\n", height[0][3]);
    printf("%d\n", height[0][4]);

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

    return 0;
}

出力結果

出席番号 5 8 13 18 22 身長 154 178 166 144 161

多次元配列の値を参照するには、次のように書く必要があります。

height[0][0]

出席番号はheight[0][]に入っており、身長はheight[1][]に入っています。

出席番号を取得したい場合、height[0][]の左の括弧はそのままにして、右の括弧のインデックス番号を指定します。

配列の基本操作と応用

※上記の青い文字から読みたい項目へ移動することができます

①sizeof演算子で配列の要素数を取得する方法

sizeof演算子で配列の要素数を取得する方法
  • sizeof(変数名) (配列全体のバイト数)
  • sizeof(変数名[0]) (配列の1つの要素のバイト数)
  • sizeof(変数名) / sizeof(変数名[0]) (配列の要素数)
#include <stdio.h>

int main(void) {
    
    int height[5] = {154, 178, 166, 144, 161};

    printf("%d\n", sizeof(height) / sizeof(height[0]));
    
    return 0;
}

出力結果

5

配列の要素数を求めるためには、「sizeof(height) / sizeof(height[0])」と書きます。

sizeof(height)で配列全体のバイト数を求め、それをsizeof(height[0])で求めた要素のバイト数で割ります。

今回は配列全体が20バイトで、1つの要素が4バイトです。20を4で割ると要素数が求められます。

出力結果が5になりました。
配列の要素は5個あることが分かります。

②sizeof演算子で多次元配列の要素数等を取得する方法

sizeof演算子で多次元配列の要素数を取得する方法
  • sizeof(変数名) (多次元配列全体のバイト数)
  • sizeof(変数名[0]) (多次元配列の1行のバイト数)
  • sizeof(変数名[0][0]) (多次元配列の1つの要素のバイト数)
  • sizeof(変数名) / sizeof(変数名[0]) (多次元配列の行の数)
  • sizeof(変数名[0]) / sizeof(変数名[0][0]) (多次元配列の列の数)
#include <stdio.h>

int main(void) {

    int height[2][5] = {{5,8,13,18,22},{154, 178, 166, 144, 161}};

    // 多次元配列全体のサイズ
    printf("%d\n", sizeof(height));

    // 多次元配列の1行のサイズ
    printf("%d\n", sizeof(height[0]));

    // 多次元配列の1つの要素のサイズ
    printf("%d\n", sizeof(height[0][0]));

    // 多次元配列の行の数
    printf("%d\n", sizeof(height) /  sizeof(height[0]));

    // 多次元配列の列の数
    printf("%d\n", sizeof(height[0]) /  sizeof(height[0][0]));

    return 0;
}

出力結果

多次元配列全体のサイズ:40 多次元配列の1行のサイズ:20 多次元配列の1つの要素のサイズ:4 多次元配列の行の数:2 多次元配列の列の数:5

配列の場合と少し異なるので注意してください。

③ループで配列の値を出力する方法

ループで配列の値を出力する方法
  • for(int i = 0; i < 配列の要素数; i++) {
    printf(“変換指定子”, 配列の変数名[i]);
    }
#include <stdio.h>

int main(void) {

    int height[5] = {154, 178, 166, 144, 161};

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

    return 0;
}

出力結果

154 178 166 144 161

ループでは簡潔に書いて出力することが出来ます。

④多重ループで多次元配列の値を出力する方法

ループで多次元配列の値を出力する方法
  • for(int i = 0; i < 配列の1次元目の要素数; i++) {
    for(int j = 0; j < 配列の2次元目の要素数; j++) {
    printf(“変換指定子”, 配列の変数名[i][j]);
    }
    }
#include <stdio.h>

int main(void) {

    int height[2][5] = {{5,8,13,18,22},{154, 178, 166, 144, 161}};

    for(int i = 0; i < sizeof(height) / sizeof(height[0]); i++) {
        for(int j = 0; j < sizeof(height[0]) / sizeof(height[0][0]); j++) {
            printf("%d\n", height[i][j]);
        }
    }

    return 0;
}

出力結果

5 8 13 18 22 154 178 166 144 161

内側のループは、外側のループ1回につき5回ループします。
多重ループを使えば、多次元配列の値を全て取得できます。

⑤配列をバブルソートする方法

バブルソートとは
  • 配列の値を大きい順(降順)または小さい順(昇順)で並び替えること

配列の値が並び替えられる際に値が泡のように浮かび上がる様子からバブルソートと呼ばれています。

配列の[0]と[1]を比較して、[1]が小さい場合[1]の値は[0]に入り、[0]の値は[1]に入ります。
次は[1]と[2]を比較、次は[2]と[3]を比較といったように順番に最後まで行います。

今回はバブルソードで昇順に並べ替えてみます。
昇順とは小さい順のことです。

#include <stdio.h>

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            // 隣接する要素を比較して順序を入れ替える
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main() {
    int height[5] = {154, 178, 166, 144, 161};
    int n = sizeof(height) / sizeof(height[0]);

    // ソート前の配列を表示
    printf("元々の配列: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", height[i]);
    }
    printf("\n"); // 改行を追加

    // バブルソートを適用
    bubbleSort(height, n);

    // ソート後の配列を表示
    printf("昇順に並び替えた配列: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", height[i]);
    }
    printf("\n"); // 改行を追加

    return 0;
}

出力結果

元々の配列: 154 178 166 144 161 昇順に並び替えた配列: 144 154 161 166 178

関数bubbleSort()では、外側で4回ループ、内側で4回ループしています。

バブルソート1

外側で4回ループする理由は、[4]の値が一番小さい場合、[0]まで移動させるためです。

バブルソート2

内側のループを4回する理由は、[0]の値が一番大きい場合、[4]に移動させるためです。

バブルソート3

arr[j]とarr[j + 1]は隣同士の要素を表しています。

もし、インデックス番号が小さい要素の値が大きい場合、一時的に変数tempに値を退避させることで、値の入れ替えを行っています。


練習問題

int型の配列を宣言し、10、11、12、13、14、15を代入し、表示してみましょう

#include <stdio.h>

int main() {
    // int型の配列を宣言し、初期化
    int numbers[] = {10, 11, 12, 13, 14, 15};

    // 配列の要素を表示
    printf("配列の要素: ");
    for (int i = 0; i < 6; i++) {
        printf("%d ", numbers[i]);
    }

    printf("\n");

    return 0;
}

出力結果

配列の要素: 10 11 12 13 14 15

int型の2次元配列を、温度と湿度で初期化し、表示しましょう

#include <stdio.h>

int main() {
    // int型の2次元配列を宣言し、初期化
    int weatherData[2][3] = {
        {25, 28, 30},  // 温度(摂氏)
        {60, 65, 70}   // 湿度(パーセント)
    };

    // 配列の要素を表示
    printf("天気データ:\n");

    printf("温度(摂氏): ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", weatherData[0][i]);
    }

    printf("\n湿度(パーセント): ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", weatherData[1][i]);
    }

    printf("\n");

    return 0;
}

出力結果

天気データ: 温度(摂氏): 25 28 30 湿度(パーセント): 60 65 70

☜前の章へ 関数の呼び出し方から引数と戻り値まで
☞次の章へ 文字列を扱ってみよう