「C++の基礎 - STL(vector)」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
編集の要約なし
編集の要約なし
160行目: 160行目:


== vectorを関数の引数にする ==
== vectorを関数の引数にする ==
vectorは簡単に関数の引数にすることができる。<br>
vectorは、関数の引数にすることができる。<br>
また、vectorのメンバ関数から要素数を参照することができるため、関数内で簡単にループ数を指定できる。<br>
また、vectorのメンバ関数から要素数を参照することができるため、関数内で簡単にループ数を指定できる。<br>
ここでは、総和を求めるプログラムとvectorの全要素を表示するプログラムを例として挙げる。<br>
ここでは、総和を求めるプログラムとvectorの全要素を表示するプログラムを例として挙げる。<br>
ただし、処理時間などの理由から参照渡しを使用して、vectorの内容を変更しない場合はconstを付加する。<br>
ただし、処理時間などの理由から参照渡しを使用して、vectorの内容を変更しない場合はconstを付加する。<br>
<br>
===== 配列の総和を求めるプログラム =====
  <source lang="c++">
  <source lang="c++">
// 配列の総和を求めるプログラム
  T SumVector(const vector<T> &v)
  T SumVector(const vector<T> &v)
  {
  {
178行目: 177行目:
     return sum;
     return sum;
  }
  }
  </source>
   
<br>
// vectorの全要素を表示するプログラム
===== vectorの全要素を表示するプログラム =====
  // 一次元vectorの場合
<source lang="c++">
  // 1次元vector
  void view(const vector<T> &v)
  void view(const vector<T> &v)
  {
  {
192行目: 189行目:
  }
  }
   
   
  // 2次元vector
  // 二次元vectorの場合
  void view(const vector<vector<T>> &vv)
  void view(const vector<vector<T>> &vv)
  {
  {
201行目: 198行目:
           cout << vv[i][j] << " ";
           cout << vv[i][j] << " ";
       }
       }
      cout << endl;
    }
}
</source>
<br><br>
== 関数の戻り値にする ==
vectorは、戻り値にも使用できる。<br>
しかし、戻り値にするとvectorをコピーするために時間が掛かるので、引数として参照渡しする方がよい<br>
以下のサンプルコードでは、ventorの全要素をscale倍している。<br>
<source lang="c++">
vector<int> ScalarVen(const vector<int> &v, int scale)
{
    vector<int> mul(v.size());
    for(int i = 0; i < mul.size(); i++)
    {
      mul[i] = v[i] * scale;
    }
    return mul;
}
</source>
<br><br>
== ソート ==
vectorでは、sort関数を使用することで昇順ソートおよび降順ソートを行うことができる。<br>
<source lang="c++">
// 昇順ソート
sort(v.begin(), v.end());
// 降順ソート
sort(v.begin(), v.end(), greater<int>());
</source>
<br><br>
== 指定要素の削除 ==
vectorでは、erase関数を使用することで任意の要素を削除することができる。<br>
<source lang="c++">
// 先頭の要素を削除する
v.erase(v.begin());
// 末尾を削除する
v.erase(v.end());
// 先頭からi番目の要素を削除する
v.erase(v.begin() + i);
</source>
<br><br>
== コマンドライン引数(argv)をvectorに格納する ==
コマンドライン引数(int argcとchar *argv[])を取得する。<br>
vector<string>を使用すると良い。<br>
<source lang="c++">
#include <vector>
#include <string>
int main(int argc, char *argv[])
{
    vector<string> args(argv, argv + argc);
    return 0;
}
</source>
<br><br>
== Range-Based-for-loopの例
vectorに対するループ文は、インデックスを使用するよりもRange Based Loopを使用した方が良い。<br>
以下のサンプルコードに、Range Based Loopを使用したループ文を記述する。<br>
<source lang="c++">
// 1次元vectorの場合
void view(const vector<T> &v)
{
    for(const auto &element : v)
    {
      cout << e << " ";
    }
    cout << endl;
}
// 2次元vectorの場合
void view(const vector<vector<T>> &vv)
{
    for(const auto &v : vv)
    {
      for(const auto &element : v)
      {
          cout << element << " ";
      }
       cout << endl;
       cout << endl;
     }
     }

2020年1月31日 (金) 19:24時点における版

概要

C++ STLでは、vectorクラス(以下、vectorと呼ぶ)が存在する。
ここでは、vectorの基本的な使い方や利点について記載する。


vectorの利点

  • size()で配列要素数を参照できるため、関数に渡しやすい。(アドレス渡し、参照渡しが可能)
  • size()でインデックスの上限を指定すると境界エラーが起きない。
  • resize(要素数)で要素数を変更できる。
  • push_back(データ)で1つずつ要素を追加できる。
  • =(代入演算子)でvecorクラスがコピーできる。
  • 関数の戻り値に指定できる。
  • STLのalgorithmでソートできる。
  • erase(インデックス)で指定要素のみ削除できる。
  • 1行でstring型にargvを格納できる。



vectorを使用する前に

vectorを使用するためには、以下ののヘッダファイルをインクルードする必要がある。

 #include <vector>



宣言と初期化

1次元配列

1次元配列のvectorの宣言は以下の通りである。
intやdouble等の基本的な型のみならず、任意で作成したクラスも使用できる。
ここで、Tはデータ型、Nは要素数、dは初期化する値を表すものとする。

 vector<T> v;
 vector<T> v();
 vector<T> v(N);
 vector<T> v(N, d);


2次元配列

2次元配列のvectorの宣言は以下の通りである。
ここで、Mは要素数を表すものとする。

 vector<vector<T>> vv;
 vector<vector<T>> vv();
 vector<vector<T>> vv(N);
 vector<vector<T>> vv(N, vector<T>(M));
 vector<vector<T>> vv(N, vector<T>(M, d));



要素へのアクセス

vectorでは、通常の配列と同様の記述で要素へアクセスすることができる。

1次元配列

v[]のi番目にdを代入して、それを出力する場合は以下となる。

 v[i] = d;
 cout << v[i] << endl;


2次元配列

v[][]のi番目およびj番目にdを代入して、それを出力する場合は以下となる。

 v[i][j] = d;
 cout << v[i][j] << endl;



要素数の変更

vectorでは、配列の要素数を変更することができる。

1次元配列

v[]の要素数をN個に変更する場合は以下の通りである。

 v.resize(N);


2次元配列

vv[][]の要素数をN * Nに変更する場合は以下の通りである。

 // 方法 1
 vv.resize(N);
 for(int i = 0; i < N; i++)
 {
    vv[i].resize(N);
 }
 
 // 方法 2
 vv.resize(N, vector<T>(N));



末尾に要素を追加

1次元配列

v[]の末尾にデータを追加する場合は以下の通りである。

 v.push_back(d);


2次元配列

vv[][]のi番目の末尾にデータを追加する場合は以下の通りである。

 vv[i].push_back(d);



vectorのコピー

vectorをコピーする方法は複数存在する。
ここでは、v1[]をv2[]にコピーする方法を記述する。

 // 方法 1
 v2 = v1
 
 // 方法 2
 v2.resize(v1.size());
 for(int i = 0; i < v1.size(); i++)
 {
    v2[i] = v1[i];
 }
 
 // 方法 3
 copy(v1.begin(), v1.end(), v2.begin());



vectorの全要素を末尾に追加

v1[]をv2[]の末尾に追加する方法は以下の通りである。(方法3が最も簡潔)

 // 方法 1
 int size = v2.size();
 v2.resize(size + v1.size());
 for(int i = 0; i < v1.size(); i++)
 {
    v2[i + size] = v1[i];
 }
 
 // 方法 2
 for(int i = 0; i < v1.size(); i++)
 {
    v2.push_back(v1[i]);
 }
 
 // 方法 3
 copy(v1.begin(), v1.end(), back_inserter(v2));



指定範囲をコピー

v1[]のa番目からb番目をv2[]にコピーする方法は以下の通りである。(方法2が簡潔)

 // 方法 1
 v2.resize(b - a);
 for(int i = 0; i < v2.size(); i++)
 {
    v2[i] = v1[a + i];
 }
 
 // 方法 2
 copy(v1.begin() + a, v1.begin() + b, v2.begin());



vectorを関数の引数にする

vectorは、関数の引数にすることができる。
また、vectorのメンバ関数から要素数を参照することができるため、関数内で簡単にループ数を指定できる。
ここでは、総和を求めるプログラムとvectorの全要素を表示するプログラムを例として挙げる。
ただし、処理時間などの理由から参照渡しを使用して、vectorの内容を変更しない場合はconstを付加する。

 // 配列の総和を求めるプログラム
 T SumVector(const vector<T> &v)
 {
    T sum = 0;
 
    for(int i = 0; i < v.size(); i++)
    {
       sum += v[i];
    }
 
    return sum;
 }
 
 // vectorの全要素を表示するプログラム
 // 一次元vectorの場合
 void view(const vector<T> &v)
 {
    for(int i = 0; i < v.size(); i++)
    {
       cout << v[i] << " ";
    }
    cout << endl;
 }
 
 // 二次元vectorの場合
 void view(const vector<vector<T>> &vv)
 {
    for(int i = 0; i < vv.size(); i++)
    {
       for(int j = 0; j < vv[i].size(); j++)
       {
          cout << vv[i][j] << " ";
       }
       cout << endl;
    }
 }



関数の戻り値にする

vectorは、戻り値にも使用できる。
しかし、戻り値にするとvectorをコピーするために時間が掛かるので、引数として参照渡しする方がよい
以下のサンプルコードでは、ventorの全要素をscale倍している。

 vector<int> ScalarVen(const vector<int> &v, int scale)
 {
    vector<int> mul(v.size());
    for(int i = 0; i < mul.size(); i++)
    {
       mul[i] = v[i] * scale;
    }
 
    return mul;
 }



ソート

vectorでは、sort関数を使用することで昇順ソートおよび降順ソートを行うことができる。

 // 昇順ソート
 sort(v.begin(), v.end());
 
 // 降順ソート
 sort(v.begin(), v.end(), greater<int>());



指定要素の削除

vectorでは、erase関数を使用することで任意の要素を削除することができる。

 // 先頭の要素を削除する
 v.erase(v.begin());
 
 // 末尾を削除する
 v.erase(v.end());
 
 // 先頭からi番目の要素を削除する
 v.erase(v.begin() + i);



コマンドライン引数(argv)をvectorに格納する

コマンドライン引数(int argcとchar *argv[])を取得する。
vector<string>を使用すると良い。

 #include <vector>
 #include <string>
 
 int main(int argc, char *argv[])
 {
    vector<string> args(argv, argv + argc);
 
    return 0;
 }



== Range-Based-for-loopの例 vectorに対するループ文は、インデックスを使用するよりもRange Based Loopを使用した方が良い。
以下のサンプルコードに、Range Based Loopを使用したループ文を記述する。

 // 1次元vectorの場合
 void view(const vector<T> &v)
 {
    for(const auto &element : v)
    {
       cout << e << " ";
    }
 
    cout << endl;
 }
 
 // 2次元vectorの場合
 void view(const vector<vector<T>> &vv)
 {
    for(const auto &v : vv)
    {
       for(const auto &element : v)
       {
          cout << element << " ";
       }
 
       cout << endl;
    }
 }