[C++] vector二次元配列ではpush_back()をどう使う?

C++で二次元配列を扱う際、std::vectorを使用することで動的な配列を作成できます。

二次元配列はstd::vector<std::vector<T>>のように定義します。

新しい行を追加するには、外側のvectorに対してpush_back()を使用します。

例えば、std::vector<int> newRow;を作成し、必要な要素をnewRowに追加した後、matrix.push_back(newRow);とすることで新しい行を追加できます。

この方法により、柔軟に行や列を追加・削除することが可能です。

この記事でわかること
  • push_back()の基本的な役割と構文について
  • 一次元および二次元vectorへのpush_back()の具体的な使用方法
  • 二次元vectorにおける行や列の追加方法
  • 動的に行列を拡張するプログラムの実践例
  • ゲーム開発や科学計算における二次元vectorの応用例

目次から探す

二次元vectorでのpush_back()の基本的な使い方

push_back()の役割と基本構文

push_back()は、C++のSTL(Standard Template Library)におけるvectorクラスのメンバ関数で、vectorの末尾に新しい要素を追加するために使用されます。

これにより、動的に配列のサイズを変更することが可能です。

基本構文は以下の通りです。

#include <vector>
std::vector<int> vec;
vec.push_back(10); // 10をvecの末尾に追加

このように、push_back()を使うことで、vectorに要素を追加することができます。

一次元vectorへのpush_back()

一次元のvectorに対してpush_back()を使用する場合、追加したい要素を引数として渡します。

以下に例を示します。

#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers;
    numbers.push_back(1); // 1を追加
    numbers.push_back(2); // 2を追加
    numbers.push_back(3); // 3を追加
    for (int num : numbers) {
        std::cout << num << " ";
    }
    return 0;
}
1 2 3

この例では、numbersというvectorに対して、push_back()を使って順に1, 2, 3を追加しています。

二次元vectorへのpush_back()の方法

二次元のvectorは、vectorの中にvectorを持つ構造です。

push_back()を使って行を追加する方法を以下に示します。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<int>> matrix;
    std::vector<int> row1 = {1, 2, 3};
    std::vector<int> row2 = {4, 5, 6};
    matrix.push_back(row1); // row1を追加
    matrix.push_back(row2); // row2を追加
    for (const auto& row : matrix) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
1 2 3
4 5 6

この例では、matrixという二次元vectorに対して、row1row2push_back()で追加しています。

push_back()を使う際の注意点

  • メモリの再確保: vectorの容量が不足すると、push_back()は内部的にメモリを再確保します。

これにより、パフォーマンスが低下する可能性があります。

  • 例外の考慮: メモリ不足などでpush_back()が失敗する場合、例外がスローされることがあります。

例外処理を考慮することが重要です。

  • 初期化の確認: 二次元vectorを使用する際、各行のvectorが適切に初期化されていることを確認する必要があります。

未初期化のvectorに対してpush_back()を行うと、予期しない動作を引き起こす可能性があります。

これらの点に注意しながら、push_back()を効果的に活用することが重要です。

二次元vectorにおけるpush_back()の実践

行を追加する方法

二次元vectorに新しい行を追加するには、vectorvectorpush_back()で追加します。

以下の例では、空の二次元vectorに行を追加しています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<int>> matrix;
    std::vector<int> newRow = {7, 8, 9};
    matrix.push_back(newRow); // newRowを追加
    for (const auto& row : matrix) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
7 8 9

この例では、newRowというvectormatrixに追加し、新しい行として扱っています。

列を追加する方法

二次元vectorに列を追加するには、各行に対して要素を追加する必要があります。

以下の例では、既存の行に新しい要素を追加して列を増やしています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<int>> matrix = {{1, 2}, {3, 4}, {5, 6}};
    for (auto& row : matrix) {
        row.push_back(0); // 各行に0を追加
    }
    for (const auto& row : matrix) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
1 2 0
3 4 0
5 6 0

この例では、各行に0を追加することで、列を増やしています。

既存の行に要素を追加する方法

既存の行に要素を追加するには、その行を指定してpush_back()を使用します。

以下の例では、特定の行に要素を追加しています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<int>> matrix = {{1, 2, 3}, {4, 5, 6}};
    matrix[0].push_back(10); // 1行目に10を追加
    for (const auto& row : matrix) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
1 2 3 10
4 5 6

この例では、matrixの1行目に10を追加しています。

push_back()を使った動的配列の構築

push_back()を使うことで、動的に配列を構築することができます。

以下の例では、ユーザーからの入力に基づいて二次元vectorを構築しています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<int>> matrix;
    int rows, cols, value;
    std::cout << "行数を入力してください: ";
    std::cin >> rows;
    std::cout << "列数を入力してください: ";
    std::cin >> cols;
    for (int i = 0; i < rows; ++i) {
        std::vector<int> row;
        for (int j = 0; j < cols; ++j) {
            std::cout << "値を入力してください: ";
            std::cin >> value;
            row.push_back(value);
        }
        matrix.push_back(row);
    }
    for (const auto& row : matrix) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
行数を入力してください: 2
列数を入力してください: 2
値を入力してください: 1
値を入力してください: 2
値を入力してください: 3
値を入力してください: 4
1 2
3 4

この例では、ユーザーの入力に基づいて二次元vectorを動的に構築しています。

push_back()を使うことで、行と列のサイズを動的に変更することが可能です。

応用例

動的に行列を拡張するプログラム

動的に行列を拡張するプログラムは、データの追加や削除が頻繁に行われるアプリケーションで役立ちます。

以下の例では、ユーザーの入力に基づいて行列を動的に拡張します。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<int>> matrix;
    int choice, value;
    while (true) {
        std::cout << "1: 行を追加, 2: 終了: ";
        std::cin >> choice;
        if (choice == 2) break;
        std::vector<int> newRow;
        std::cout << "新しい行の要素を入力 (終了は-1): ";
        while (true) {
            std::cin >> value;
            if (value == -1) break;
            newRow.push_back(value);
        }
        matrix.push_back(newRow);
    }
    for (const auto& row : matrix) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
1: 行を追加, 2: 終了: 1
新しい行の要素を入力 (終了は-1): 1 2 3 -1
1: 行を追加, 2: 終了: 1
新しい行の要素を入力 (終了は-1): 4 5 6 -1
1: 行を追加, 2: 終了: 2
1 2 3
4 5 6

このプログラムでは、ユーザーが行を追加するたびに新しい行がmatrixに追加されます。

データの読み込みと動的配列への格納

ファイルや外部データソースからデータを読み込み、動的配列に格納することは、データ処理アプリケーションでよく行われます。

以下の例では、標準入力からデータを読み込み、二次元vectorに格納します。

#include <vector>
#include <iostream>
#include <sstream>
int main() {
    std::vector<std::vector<int>> data;
    std::string line;
    std::cout << "データを入力してください (行ごとにスペース区切り、終了は空行):" << std::endl;
    while (std::getline(std::cin, line) && !line.empty()) {
        std::istringstream iss(line);
        std::vector<int> row;
        int num;
        while (iss >> num) {
            row.push_back(num);
        }
        data.push_back(row);
    }
    for (const auto& row : data) {
        for (int num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
データを入力してください (行ごとにスペース区切り、終了は空行):
1 2 3
4 5 6
1 2 3
4 5 6

このプログラムでは、ユーザーが入力したデータを行ごとに読み込み、dataという二次元vectorに格納しています。

ゲーム開発におけるマップデータの管理

ゲーム開発では、マップデータを二次元vectorで管理することが一般的です。

以下の例では、簡単なマップデータを二次元vectorで表現しています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<char>> map = {
        {'#', '#', '#', '#', '#'},
        {'#', ' ', ' ', ' ', '#'},
        {'#', ' ', '#', ' ', '#'},
        {'#', ' ', ' ', ' ', '#'},
        {'#', '#', '#', '#', '#'}
    };
    for (const auto& row : map) {
        for (char cell : row) {
            std::cout << cell;
        }
        std::cout << std::endl;
    }
    return 0;
}
#####
#   #
# # #
#   #
#####

この例では、mapという二次元vectorを使って、簡単なマップを表現しています。

#は壁、 (スペース)は通路を示しています。

科学計算における行列演算の準備

科学計算では、行列を扱うことが多く、二次元vectorを使って行列を表現することができます。

以下の例では、行列を初期化し、表示しています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<double>> matrix = {
        {1.0, 2.0, 3.0},
        {4.0, 5.0, 6.0},
        {7.0, 8.0, 9.0}
    };
    for (const auto& row : matrix) {
        for (double num : row) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0

この例では、matrixという二次元vectorを使って、3×3の行列を表現しています。

GUIアプリケーションでのデータ管理

GUIアプリケーションでは、表形式のデータを管理するために二次元vectorを使用することができます。

以下の例では、簡単なデータテーブルを二次元vectorで表現しています。

#include <vector>
#include <iostream>
int main() {
    std::vector<std::vector<std::string>> table = {
        {"名前", "年齢", "職業"},
        {"田中", "30", "エンジニア"},
        {"鈴木", "25", "デザイナー"},
        {"佐藤", "28", "マネージャー"}
    };
    for (const auto& row : table) {
        for (const std::string& cell : row) {
            std::cout << cell << "\t";
        }
        std::cout << std::endl;
    }
    return 0;
}
名前    年齢    職業
田中    30      エンジニア
鈴木    25      デザイナー
佐藤    28      マネージャー

この例では、tableという二次元vectorを使って、簡単なデータテーブルを表現しています。

各行は異なるデータレコードを示しています。

よくある質問

push_back()を使うときのパフォーマンスはどうですか?

push_back()は、vectorの末尾に要素を追加する際に非常に便利ですが、パフォーマンスに影響を与える場合があります。

vectorの容量が不足すると、内部的に新しいメモリ領域を確保し、既存の要素をコピーする必要があります。

この再確保は、時間がかかる操作です。

頻繁にpush_back()を使用する場合、reserve()関数を使って事前に必要な容量を確保することで、再確保の回数を減らし、パフォーマンスを向上させることができます。

二次元vectorのサイズを変更する他の方法はありますか?

二次元vectorのサイズを変更する方法として、resize()関数を使用することができます。

resize()は、vectorのサイズを指定した大きさに変更し、必要に応じて新しい要素をデフォルト値で初期化します。

例えば、matrix.resize(newRows, std::vector<int>(newCols))のように使用することで、行と列のサイズを一度に変更することが可能です。

また、assign()関数を使って、vector全体を新しいサイズと値で再初期化することもできます。

vectorと配列の違いは何ですか?

vectorと配列にはいくつかの違いがあります。

  • サイズの変更: vectorは動的にサイズを変更できるのに対し、配列は固定サイズです。
  • メモリ管理: vectorは自動的にメモリを管理し、必要に応じて再確保しますが、配列は手動でメモリ管理を行う必要があります。
  • 機能の豊富さ: vectorはSTLの一部であり、多くの便利なメンバ関数(例:push_back(), resize(), insert()など)を提供しますが、配列は基本的な操作しかサポートしていません。
  • パフォーマンス: 配列は固定サイズであるため、メモリの再確保が不要で、特定の状況ではvectorよりも高速です。

しかし、vectorは柔軟性が高く、一般的な用途においては使いやすい選択肢です。

まとめ

この記事では、C++における二次元vectorpush_back()の使い方について詳しく解説し、基本的な操作から応用例までを紹介しました。

push_back()を活用することで、動的に配列を拡張し、さまざまなデータ構造を効率的に管理する方法を学ぶことができました。

これを機に、実際のプログラムで二次元vectorを活用し、より柔軟なデータ管理を実践してみてはいかがでしょうか。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • URLをコピーしました!
目次から探す