初心者から上級者まで完全マスター!C++における二次元配列の使い方10選 – Japanシーモア

初心者から上級者まで完全マスター!C++における二次元配列の使い方10選

C++の二次元配列を使いこなす方法を徹底解説するイメージC++
この記事は約17分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

このサービスは複数のSSPによる協力の下、運営されています。

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事では、C++プログラミングにおいて基本的だが非常に重要な概念である二次元配列について、初心者から上級者までが理解できるように詳しく解説します。

二次元配列はデータを格子状に整理する際に使われ、ゲームの盤面やデータの表など、さまざまな場面で役立ちます。

この記事を読めば、C++での二次元配列の使い方を完全にマスターできるでしょう。

●C++と二次元配列の基本

C++における二次元配列は、基本的には一次元配列を拡張した形です。

一次元配列がデータの列を表すのに対し、二次元配列は行と列の両方を持ち、より複雑なデータ構造を作成することができます。

C++では、配列は連続したメモリ領域にデータを格納し、それぞれのデータはインデックスでアクセスできます。

二次元配列では、これが二次元的に拡張され、行と列のインデックスを使って各要素にアクセスします。

○二次元配列とは

具体的には、二次元配列は「配列の配列」と考えることができます。

たとえば、int型の二次元配列では、各行がint型の一次元配列として格納され、それぞれの行が連続したメモリブロックを形成します。

これにより、[行][列]という形でデータにアクセスすることができ、表やマトリックスのようなデータ構造を簡単に扱うことが可能になります。

○C++における配列の宣言方法

C++で二次元配列を宣言する方法はいくつかありますが、最も基本的な方法は次のとおりです。

例えば、int型の要素を持つ5行3列の配列を宣言する場合、次のように記述します。

int array[5][3];

このコードでは、intは要素の型を表し、[5][3]は配列の大きさを表しています。

この場合、配列は5行3列、合計15のint型要素を持つことになります。

配列の各要素には、0から始まるインデックスを使用してアクセスします。

たとえば、array[0][0]は配列の最初の要素を、array[4][2]は配列の最後の要素を指します。

●二次元配列の作成方法

C++での二次元配列の作成方法は、その用途や状況に応じて様々です。

基本的な静的配列の作成から、より柔軟な動的配列の作成まで、C++の強力な機能を活用してデータを効率的に管理する方法を見ていきましょう。

○サンプルコード1:基本的な配列の作成

最も基本的な二次元配列の作成方法は、静的にサイズを指定する方法です。

たとえば、3行4列のint型の二次元配列を作成するには、下記のように記述します。

int staticArray[3][4];

このコードにより、3行4列、合計12の要素を持つint型の二次元配列が作成されます。

静的配列の場合、サイズはコンパイル時に決定され、実行時には変更できません。

この配列は、特定の行と列のインデックスを使ってアクセスできるため、データの取得や更新が簡単に行えます。

例えば、staticArray[2][3]は配列の最後の要素を指します。

○サンプルコード2:動的な配列の作成

C++では、動的にサイズが変更可能な二次元配列も作成できます。

動的配列は、実行時にサイズが決定され、必要に応じてサイズを変更することが可能です。

動的配列の作成には、ポインタを使用します。

ここでは、動的にサイズが決定される二次元配列を作成するサンプルコードを紹介します。

int** dynamicArray;
int rows = 5; // 行の数
int cols = 4; // 列の数

// 配列の行の確保
dynamicArray = new int*[rows];

// 各行に対して列を確保
for(int i = 0; i < rows; i++) {
    dynamicArray[i] = new int[cols];
}

このコードでは、まずint型のポインタのポインタdynamicArrayを宣言しています。

次に、行数rowsと列数colsを指定し、new演算子を使用して必要なメモリを確保しています。

ループ内で、各行に対して列のメモリを確保し、二次元配列が形成されます。

動的配列を使用する場合は、使用後にメモリを解放することが重要です。

これにはdelete[]演算子を使用します。

●二次元配列の操作方法

C++での二次元配列の操作は、データの構造を理解していることが重要です。

配列の値の設定や取得、さらにはループを使った効率的な処理方法を学ぶことで、プログラムの柔軟性と効率を高めることができます。

○サンプルコード3:配列の値の設定と取得

二次元配列では、特定の行と列を指定して値を設定または取得することができます。

下記のコードは、5行5列のint型二次元配列を作成し、特定の位置に値を設定し、取得しています。

int myArray[5][5];

// 値の設定
myArray[2][3] = 10;

// 値の取得
int value = myArray[2][3];

このコードでは、myArray[2][3]10という値を設定し、同じ位置から値を取得しています。

このように、インデックスを使って配列の各要素にアクセスすることで、データの管理が容易になります。

○サンプルコード4:二次元配列を用いたループ処理

二次元配列の各要素に対して操作を行う場合、ループを用いると効率的です。

下記のコードでは、二次元配列の各要素に対して値を設定し、その後で全要素の値を表示しています。

int array[4][3];

// 二次元配列に値を設定
for(int i = 0; i < 4; i++) {
    for(int j = 0; j < 3; j++) {
        array[i][j] = i + j;
    }
}

// 二次元配列の値を表示
for(int i = 0; i < 4; i++) {
    for(int j = 0; j < 3; j++) {
        std::cout << array[i][j] << " ";
    }
    std::cout << std::endl;
}

このコードでは、まず二重ループを使用して配列の各要素に値を設定し、続いて別の二重ループを使用してこれらの値を表示しています。

二次元配列を操作する際には、このようにループを効果的に使うことが重要です。

●二次元配列の応用例

C++における二次元配列は、その用途が非常に多岐にわたります。

プログラミング初心者から上級者まで、多くの方々が二次元配列を利用して、データの整理やアルゴリズムの実装に取り組んでいます。

ここでは、具体的な応用例をいくつか紹介し、二次元配列の可能性を広げる方法について考えてみましょう。

○サンプルコード5:行列の加算

二次元配列は数学的な問題を解決するのに適しています。

たとえば、行列の加算は二次元配列を使用して簡単に実装できます。

下記のサンプルコードは、二つの行列を加算するプログラムです。

#include <iostream>
using namespace std;

int main() {
    int matrixA[2][2] = {{1, 2}, {3, 4}};
    int matrixB[2][2] = {{5, 6}, {7, 8}};
    int sum[2][2];

    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            sum[i][j] = matrixA[i][j] + matrixB[i][j];
        }
    }

    cout << "行列の和:" << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            cout << sum[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

このコードでは、まず2×2の行列matrixAmatrixBを定義し、それぞれの要素の和を計算してsum行列に格納しています。

そして、計算結果を出力しています。

二次元配列を使うことで、行列の加算という数学的な操作を直感的にコードに落とし込むことができます。

○サンプルコード6:ゲームの盤面の表現

二次元配列は、ゲーム開発においても非常に有効です。

例えば、チェスや将棋の盤面を二次元配列で表現することができます。

下記のサンプルコードは、簡単なチェス盤の初期配置を表しています。

#include <iostream>
using namespace std;

int main() {
    char chessBoard[8][8] = {
        {'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'},
        {'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'},
        {'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'}
    };

    cout << "チェス盤の初期配置:" << endl;
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            cout << chessBoard[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

このコードでは、8×8の二次元配列chessBoardを使ってチェス盤を表現しています。

各要素には、チェスの駒を示す文字が格納されています。

このように二次元配列を利用することで、ゲームの盤面を簡単かつ効率的にコードで扱うことができます。

●二次元配列の高度な利用法

C++の二次元配列は、単にデータを格納するだけでなく、より複雑なアルゴリズムの実装にも用いられます。

これにより、データの処理や分析を効率的に行うことが可能になります。

ここでは、二次元配列を用いた高度な利用法の一例として、配列のソートと検索処理について詳しく解説します。

○サンプルコード7:配列のソート

二次元配列の要素をソートすることは、データを整理しやすくするための重要な手法です。

下記のサンプルコードでは、簡単な二次元配列のソート処理を表しています。

#include <iostream>
#include <algorithm> // sort関数を使用するために必要
using namespace std;

int main() {
    int array[3][3] = {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}};
    int rows = 3;
    int cols = 3;

    // 二次元配列の各行をソート
    for (int i = 0; i < rows; i++) {
        sort(array[i], array[i] + cols);
    }

    // ソート後の配列を表示
    cout << "ソート後の配列:" << endl;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cout << array[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

このコードでは、sort関数を用いて二次元配列の各行を個別にソートしています。

これにより、各行が昇順に並び替えられ、データが整理されます。

○サンプルコード8:二次元配列の検索処理

二次元配列内の特定のデータを見つけるための検索処理も、プログラミングにおいて重要な役割を果たします。

下記のサンプルコードでは、指定した値を二次元配列から検索する方法を表しています。

#include <iostream>
using namespace std;

int main() {
    int array[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int target = 5; // 検索する値
    bool found = false;

    // 二次元配列内で値を検索
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (array[i][j] == target) {
                cout << "値 " << target << " が見つかりました。位置:[" << i << "][" << j << "]" << endl;
                found = true;
                break;
            }
        }
        if (found) break;
    }

    if (!found) {
        cout << "値 " << target << " は配列内に存在しません。" << endl;
    }

    return 0;
}

このコードでは、二重ループを用いて配列の各要素を順に調べ、目的の値targetが見つかった場合にその位置を表示しています。

このような検索処理は、データ分析やデータベース操作など、多くの分野で応用されます。

●二次元配列のエラー対処法

C++プログラミングにおいて、二次元配列の使用は非常に便利ですが、それに伴うエラーを適切に処理することも重要です。

二次元配列を扱う際には、特にメモリの確保と解放、例外処理が重要なポイントとなります。

ここでは、これらのエラー対処法に焦点を当て、具体的なサンプルコードを通じて解説します。

○サンプルコード9:メモリの確保と解放

動的な二次元配列を使用する場合、メモリの確保と解放は非常に重要です。

下記のサンプルコードでは、動的に確保したメモリの解放方法を表しています。

#include <iostream>
using namespace std;

int main() {
    int rows = 3;
    int cols = 4;
    int** dynamicArray = new int*[rows];

    for (int i = 0; i < rows; i++) {
        dynamicArray[i] = new int[cols];
    }

    // 何らかの処理
    // ...

    // メモリの解放
    for (int i = 0; i < rows; i++) {
        delete[] dynamicArray[i];
    }
    delete[] dynamicArray;

    return 0;
}

このコードでは、まずnewを用いてメモリを確保しています。

その後、処理が完了したらdelete[]を用いて各行と最終的に配列全体のメモリを解放しています。

このように適切にメモリを管理することで、メモリリークや他のエラーを防ぐことができます。

○サンプルコード10:例外処理の実装

プログラムにおいて例外が発生した場合、それを適切に処理することも重要です。

C++における例外処理は、trycatchブロックを用いて行われます。

下記のサンプルコードでは、二次元配列操作中に発生する可能性のある例外を処理する方法を表しています。

#include <iostream>
using namespace std;

int main() {
    int rows = 3;
    int cols = 4;
    int** dynamicArray = nullptr;

    try {
        dynamicArray = new int*[rows];
        for (int i = 0; i < rows; i++) {
            dynamicArray[i] = new int[cols];
        }
        // 何らかの処理
        // ...
    } catch (bad_alloc& e) {
        cout << "メモリ割り当てエラー: " << e.what() << endl;
        // 必要な場合は、ここでメモリを解放
    }

    // プログラムの終了前にメモリを解放
    if (dynamicArray != nullptr) {
        for (int i = 0; i < rows; i++) {
            delete[] dynamicArray[i];
        }
        delete[] dynamicArray;
    }

    return 0;
}

このコードでは、newによるメモリ割り当て中に例外が発生した場合、catchブロックでそれを捕捉し、エラーメッセージを出力しています。

このような例外処理を行うことで、プログラムが予期せぬ状況でクラッシュするのを防ぐことができます。

●二次元配列のカスタマイズ方法

C++の二次元配列は非常に柔軟性が高く、さまざまな方法でカスタマイズすることが可能です。

ここでは、特定のニーズに合わせて二次元配列をカスタマイズするアイディアと実用例を提供します。

これらの例は、特定の問題を解決するための出発点として、または新しいアプリケーションのインスピレーションとして役立つでしょう。

○カスタマイズのアイディア

二次元配列のカスタマイズには、下記のようなアイディアがあります。

  1. 例えば、数値データ、文字データ、またはオブジェクトデータに応じて、intchar、またはクラス型の配列を使用する
  2. 二次元配列をさらに拡張して、3次元以上の多次元配列を作成し、より複雑なデータ構造を表現する
  3. 動的配列を使用して、実行時に配列のサイズを変更できるようにする

○実用例とコード

ここでは、二次元配列を使用して簡単なデータ表を作成する実用例を紹介します。

この例では、商品とその価格を表す表を作成しています。

#include <iostream>
#include <string>
using namespace std;

int main() {
    const int rows = 3;
    const int cols = 2;
    string products[rows][cols] = {{"りんご", "100円"}, {"バナナ", "150円"}, {"オレンジ", "200円"}};

    cout << "商品と価格の表:" << endl;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cout << products[i][j] << "\t";
        }
        cout << endl;
    }

    return 0;
}

このコードでは、string型の二次元配列を使用して、商品の名前と価格を格納しています。

ループを用いてこの表を出力することで、見やすい形式のデータ表が表示されます。

まとめ

この記事では、C++における二次元配列の基本から応用、カスタマイズ方法に至るまでを詳細に解説しました。

初心者から上級者までが理解できるよう、具体的なサンプルコードを交えながら、二次元配列の宣言、操作、エラー対処法について紹介してきました。

二次元配列はデータの整理や処理に非常に強力で、C++プログラミングの幅を広げる重要な要素です。

本記事が、読者の皆様のC++におけるプログラミング技術の向上に役立つことを願っています。