[C++] vectorで2次元配列を生成する方法をわかりやすく解説
C++で2次元配列を生成するには、std::vectorをネストして使用します。
具体的には、外側のvectorが行を、内側のvectorが列を表します。
例えば、std::vector<std::vector<int>> matrix(rows, std::vector<int>(cols, 初期値));のように記述します。
ここでrowsは行数、colsは列数、初期値は各要素の初期値を指定します。
この方法により、動的なサイズ変更が可能な2次元配列を簡単に作成できます。
vectorで2次元配列を生成する基本的な方法
C++のvectorを使用して2次元配列を生成する方法は非常にシンプルです。
vectorは動的配列であり、サイズを変更できるため、2次元配列を扱うのに適しています。
以下に基本的な生成方法を示します。
1. vectorの初期化
まず、2次元配列を生成するために、vectorのベクトルを使用します。
以下のコードでは、3行4列の2次元配列を生成しています。
#include <iostream>
#include <vector>
int main() {
    // 3行4列の2次元配列を生成
    std::vector<std::vector<int>> array(3, std::vector<int>(4));
    // 配列に値を代入
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            array[i][j] = i * j; // 行と列のインデックスの積を代入
        }
    }
    // 配列の内容を表示
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            std::cout << array[i][j] << " "; // 各要素を表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}0 0 0 0 
0 1 2 3 
0 2 4 62. vectorのサイズ変更
vectorの特性を活かして、後からサイズを変更することも可能です。
以下のコードでは、最初に2行3列の配列を生成し、その後に行数を増やしています。
#include <iostream>
#include <vector>
int main() {
    // 2行3列の2次元配列を生成
    std::vector<std::vector<int>> array(2, std::vector<int>(3));
    // 配列に値を代入
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < 3; ++j) {
            array[i][j] = i + j; // 行と列のインデックスの和を代入
        }
    }
    // 行数を増やす
    array.push_back(std::vector<int>(3, 0)); // 新しい行を追加
    // 配列の内容を表示
    for (int i = 0; i < array.size(); ++i) {
        for (int j = 0; j < array[i].size(); ++j) {
            std::cout << array[i][j] << " "; // 各要素を表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}0 1 2 
1 2 3 
0 0 0このように、vectorを使うことで、簡単に2次元配列を生成し、操作することができます。
動的にサイズを変更できるため、柔軟なデータ構造として非常に便利です。
2次元配列の操作方法
C++のvectorを使用した2次元配列の操作は、基本的な配列と同様に行えますが、動的なサイズ変更や便利なメソッドを利用できる点が特徴です。
ここでは、2次元配列の基本的な操作方法について解説します。
1. 要素のアクセス
2次元配列の要素には、行と列のインデックスを使用してアクセスします。
以下のコードでは、特定の要素にアクセスし、その値を表示しています。
#include <iostream>
#include <vector>
int main() {
    // 2行3列の2次元配列を生成
    std::vector<std::vector<int>> array = {
        {1, 2, 3},
        {4, 5, 6}
    };
    // 特定の要素にアクセス
    int value = array[1][2]; // 2行目3列目の要素を取得
    std::cout << "2行目3列目の要素: " << value << std::endl; // 値を表示
    return 0;
}2行目3列目の要素: 62. 行の追加と削除
vectorを使用すると、行の追加や削除が簡単に行えます。
以下のコードでは、行を追加し、特定の行を削除する方法を示しています。
#include <iostream>
#include <vector>
int main() {
    // 2行3列の2次元配列を生成
    std::vector<std::vector<int>> array = {
        {1, 2, 3},
        {4, 5, 6}
    };
    // 新しい行を追加
    array.push_back({7, 8, 9}); // 3行目を追加
    // 1行目を削除
    array.erase(array.begin()); // 1行目を削除
    // 配列の内容を表示
    for (const auto& row : array) {
        for (const auto& elem : row) {
            std::cout << elem << " "; // 各要素を表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}4 5 6 
7 8 93. 行列の転置
行列の転置は、行と列を入れ替える操作です。
以下のコードでは、2次元配列の転置を行っています。
#include <iostream>
#include <vector>
int main() {
    // 2行3列の2次元配列を生成
    std::vector<std::vector<int>> array = {
        {1, 2, 3},
        {4, 5, 6}
    };
    // 転置行列を生成
    std::vector<std::vector<int>> transposed(array[0].size(), std::vector<int>(array.size()));
    for (int i = 0; i < array.size(); ++i) {
        for (int j = 0; j < array[i].size(); ++j) {
            transposed[j][i] = array[i][j]; // 行と列を入れ替え
        }
    }
    // 転置行列の内容を表示
    for (const auto& row : transposed) {
        for (const auto& elem : row) {
            std::cout << elem << " "; // 各要素を表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}1 4 
2 5 
3 64. 2次元配列の初期化
2次元配列を初期化する際に、特定の値で埋めることも可能です。
以下のコードでは、すべての要素を0で初期化しています。
#include <iostream>
#include <vector>
int main() {
    // 3行4列の2次元配列を0で初期化
    std::vector<std::vector<int>> array(3, std::vector<int>(4, 0)); // すべての要素を0で初期化
    // 配列の内容を表示
    for (const auto& row : array) {
        for (const auto& elem : row) {
            std::cout << elem << " "; // 各要素を表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}0 0 0 0 
0 0 0 0 
0 0 0 0このように、vectorを使用した2次元配列の操作は非常に柔軟で、さまざまな方法でデータを管理できます。
応用的な使い方
C++のvectorを使用した2次元配列は、基本的な操作に加えて、さまざまな応用が可能です。
ここでは、いくつかの応用的な使い方を紹介します。
1. 2次元配列を使ったグリッドの表現
2次元配列は、ゲームやシミュレーションなどでグリッドを表現するのに便利です。
以下のコードでは、簡単な迷路を表現しています。
#include <iostream>
#include <vector>
int main() {
    // 迷路を表現する2次元配列
    std::vector<std::vector<char>> maze = {
        {'#', '#', '#', '#', '#'},
        {'#', ' ', ' ', '#', '#'},
        {'#', '#', ' ', ' ', '#'},
        {'#', ' ', '#', ' ', '#'},
        {'#', '#', '#', '#', '#'}
    };
    // 迷路の内容を表示
    for (const auto& row : maze) {
        for (const auto& cell : row) {
            std::cout << cell; // 各セルを表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}#####
#  ##
##  #
# # #
#####2. 2次元配列を使った行列計算
行列の加算や乗算などの計算も、2次元配列を使って実装できます。
以下のコードでは、2つの行列の加算を行っています。
#include <iostream>
#include <vector>
int main() {
    // 2つの2次元配列を定義
    std::vector<std::vector<int>> matrixA = {
        {1, 2, 3},
        {4, 5, 6}
    };
    std::vector<std::vector<int>> matrixB = {
        {7, 8, 9},
        {10, 11, 12}
    };
    // 行列の加算
    std::vector<std::vector<int>> result(matrixA.size(), std::vector<int>(matrixA[0].size()));
    for (int i = 0; i < matrixA.size(); ++i) {
        for (int j = 0; j < matrixA[i].size(); ++j) {
            result[i][j] = matrixA[i][j] + matrixB[i][j]; // 各要素を加算
        }
    }
    // 結果の行列を表示
    for (const auto& row : result) {
        for (const auto& elem : row) {
            std::cout << elem << " "; // 各要素を表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}8 10 12 
14 16 183. 2次元配列を使ったデータの集計
2次元配列を使用して、データの集計や統計処理を行うこともできます。
以下のコードでは、各行の合計を計算しています。
#include <iostream>
#include <vector>
int main() {
    // 2次元配列を定義
    std::vector<std::vector<int>> data = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    // 各行の合計を計算
    for (int i = 0; i < data.size(); ++i) {
        int sum = 0;
        for (int j = 0; j < data[i].size(); ++j) {
            sum += data[i][j]; // 各要素を加算
        }
        std::cout << "行 " << i + 1 << " の合計: " << sum << std::endl; // 合計を表示
    }
    return 0;
}行 1 の合計: 6
行 2 の合計: 15
行 3 の合計: 244. 2次元配列を使った画像処理
2次元配列は、画像データの表現にも使用されます。
以下のコードでは、簡単なグレースケール画像を表現し、明るさを調整しています。
#include <iostream>
#include <vector>
int main() {
    // グレースケール画像を表現する2次元配列
    std::vector<std::vector<int>> image = {
        {100, 150, 200},
        {50, 75, 100},
        {0, 25, 50}
    };
    // 明るさを調整
    int brightnessAdjustment = 50;
    for (int i = 0; i < image.size(); ++i) {
        for (int j = 0; j < image[i].size(); ++j) {
            image[i][j] = std::min(255, image[i][j] + brightnessAdjustment); // 明るさを調整
        }
    }
    // 調整後の画像を表示
    for (const auto& row : image) {
        for (const auto& pixel : row) {
            std::cout << pixel << " "; // 各ピクセルを表示
        }
        std::cout << std::endl; // 行の終わりで改行
    }
    return 0;
}150 200 250 
100 125 150 
50 75 100このように、vectorを使用した2次元配列は、さまざまな応用が可能であり、特にデータの表現や計算において非常に便利です。
実践例:vectorで2次元配列を使ったプログラム
ここでは、C++のvectorを使用して2次元配列を活用した実践的なプログラムの例を紹介します。
このプログラムでは、簡単な成績管理システムを作成し、学生の成績を管理・表示します。
プログラムの概要
- 学生の数と科目の数を指定し、各学生の成績を2次元配列で管理します。
- 成績を入力し、各学生の平均点を計算して表示します。
コード例
#include <iostream>
#include <vector>
#include <iomanip> // std::setprecisionを使用するために必要
int main() {
    int numStudents, numSubjects;
    // 学生数と科目数の入力
    std::cout << "学生の数を入力してください: ";
    std::cin >> numStudents;
    std::cout << "科目の数を入力してください: ";
    std::cin >> numSubjects;
    // 2次元配列を生成
    std::vector<std::vector<int>> grades(numStudents, std::vector<int>(numSubjects));
    // 成績の入力
    for (int i = 0; i < numStudents; ++i) {
        std::cout << "学生 " << (i + 1) << " の成績を入力してください:\n";
        for (int j = 0; j < numSubjects; ++j) {
            std::cout << "科目 " << (j + 1) << ": ";
            std::cin >> grades[i][j]; // 成績を入力
        }
    }
    // 各学生の平均点を計算して表示
    std::cout << std::fixed << std::setprecision(2); // 小数点以下2桁まで表示
    for (int i = 0; i < numStudents; ++i) {
        int sum = 0;
        for (int j = 0; j < numSubjects; ++j) {
            sum += grades[i][j]; // 成績を合計
        }
        double average = static_cast<double>(sum) / numSubjects; // 平均を計算
        std::cout << "学生 " << (i + 1) << " の平均点: " << average << std::endl; // 平均点を表示
    }
    return 0;
}プログラムの説明
- 学生数と科目数の入力: ユーザーから学生の数と科目の数を入力してもらいます。
- 2次元配列の生成: vectorを使用して、学生数×科目数の2次元配列を生成します。
- 成績の入力: 各学生の成績を入力します。
- 平均点の計算: 各学生の成績を合計し、平均点を計算して表示します。
以下は、プログラムを実行した際の例です。
学生の数を入力してください: 2
科目の数を入力してください: 3
学生 1 の成績を入力してください:
科目 1: 80
科目 2: 90
科目 3: 85
学生 2 の成績を入力してください:
科目 1: 70
科目 2: 75
科目 3: 80
学生 1 の平均点: 85.00
学生 2 の平均点: 75.00このプログラムは、vectorを使用した2次元配列の実践的な利用例を示しており、成績管理の基本的な機能を実装しています。
vectorの特性を活かすことで、動的にサイズを変更できる柔軟なデータ構造を利用しています。
よくあるエラーとその対処法
C++のvectorを使用した2次元配列のプログラミングでは、いくつかの一般的なエラーが発生することがあります。
ここでは、よくあるエラーとその対処法について解説します。
1. インデックスの範囲外アクセス
エラー内容
vectorのインデックスが範囲外の場合、プログラムがクラッシュすることがあります。
たとえば、存在しない行や列にアクセスしようとすると、未定義の動作が発生します。
対処法
インデックスが有効な範囲内であることを確認するために、条件文を使用してチェックします。
以下のように、インデックスを使用する前にサイズを確認することが重要です。
if (i >= 0 && i < array.size() && j >= 0 && j < array[i].size()) {
    // 有効なインデックスの場合の処理
}2. 初期化されていない要素の使用
エラー内容
vectorの要素を初期化せずに使用すると、未定義の値が出力されることがあります。
特に、数値型の要素は初期化されていない場合、ゴミ値が含まれることがあります。
対処法
vectorを初期化する際に、デフォルト値を指定することができます。
以下のように、初期化時に値を設定することで、未定義の値を防ぐことができます。
std::vector<std::vector<int>> array(rows, std::vector<int>(cols, 0)); // すべての要素を0で初期化3. メモリ不足エラー
エラー内容
非常に大きな2次元配列を作成しようとすると、メモリ不足エラーが発生することがあります。
特に、vectorは動的にメモリを確保するため、サイズが大きくなると問題が発生します。
対処法
必要なサイズを見積もり、メモリの使用量を最適化することが重要です。
また、プログラムの実行環境に応じて、メモリ制限を確認し、適切なサイズの配列を使用するようにします。
4. 行数や列数の不一致
エラー内容
2次元配列を操作する際に、行数や列数が一致しない場合、計算や表示が正しく行われないことがあります。
たとえば、行列の加算を行う際に、サイズが異なるとエラーが発生します。
対処法
行数や列数が一致していることを確認するために、条件文を使用してチェックします。
以下のように、サイズを比較することが重要です。
if (matrixA.size() == matrixB.size() && matrixA[0].size() == matrixB[0].size()) {
    // 行列の加算処理
}5. 参照の無効化
エラー内容
vectorの要素を参照している場合、元のvectorが変更されると、参照が無効になることがあります。
これにより、予期しない動作が発生することがあります。
対処法
参照を使用する際は、元のvectorが変更されないことを確認するか、必要に応じてコピーを作成することが重要です。
以下のように、コピーを作成することで安全に操作できます。
std::vector<int> copy = originalVector; // コピーを作成これらのエラーとその対処法を理解することで、C++のvectorを使用した2次元配列のプログラミングがよりスムーズに行えるようになります。
エラーを事前に防ぐためのチェックを行い、適切な初期化やサイズ管理を心がけましょう。
まとめ
この記事では、C++のvectorを使用して2次元配列を生成し、操作する方法について詳しく解説しました。
基本的な使い方から応用的な利用法、実践例、よくあるエラーとその対処法まで幅広く取り上げ、実際のプログラミングに役立つ情報を提供しました。
これを機に、2次元配列を活用したプログラムを自分で作成し、さらなるスキル向上に挑戦してみてください。
 
![[C++] 配列の要素数を動的に変更する方法](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47463.png)
![[C++] 配列の要素数を定数として扱う方法(constexprの活用)](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47462.png)
![[C++] 配列の要素数を指定せず、後で要素数を決める方法](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47460.png)
![[C++] 配列に定義できる最大要素数はいくらまで?](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47458.png)
![[C++] 要素数0の配列を作成する方法 – std::vectorの応用](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47456.png)
![[C++] 配列の要素数を取得する方法](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47455.png)
![[C++] 二次元配列の使い方をマスターする](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47454.png)
![[C++] 動的配列と静的配列の違いについて解説](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47453.png)
![[C++] 動的に作成した配列を初期化する方法](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47452.png)
![[C++] 配列を動的に生成して可変長配列を実装する方法](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47451.png)
![[C++] 配列に様々な方法で値を代入する方法](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47450.png)
![[C++] 配列の宣言と初期化について解説](https://af-e.net/wp-content/uploads/2024/10/thumbnail-47449.png)