配列型文字列と比べるとC++ストリング型オブジェクトは使いやすく実行エラーの起こる回数が少ない.これと同じことが配列と標準C++ベクタ型オブジェクトの間でもいえる.つまり,C++ベクタオブジェクトは配列をもっと使いやすくしたものである.vectorクラステンプレートは標準C++ライブラリのコンテナのプロトタイプである.
vectorクラステンプレートはvectorヘッダで定義されている.
#include <iostream>
#include <string> #include <vector> using namespace std; void load(vector<string>&); void print(vector<string>); const int SIZE = 8; int main() { vector<string> v(SIZE); load(v); print(v); } void load(vector<string>& v) { v[0] = "Japan"; v[1] = "America"; v[2] = "Austria"; v[3] = "Germany"; v[4] = "England"; v[5] = "Italy"; v[6] = "Spain"; v[7] = "Korea"; } void print(vector<string> v) { for(int i=0; i < SIZE; i++){ cout << v[i] << endl; } } |
解答 vectorstringv(SIZE)で8個のストリング型のベクタを用意する.load()関数で国名を入力し,print()関数で出力している.
実行結果
解答
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; void load(Strings&); void print(Strings); const int SIZE = 8; int main() { Strings v; load(v); print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(int i=0; i < v.size(); i++){ cout << v[i] << endl; } } |
ここで,ベクトルvは宣言された段階では要素を持っていない.push_back()関数が呼ばれるたびに,ベクトルvの最後に新しい要素を付け加え,そのサイズを増やす.したがって,load()関数が積み終えたときにはベクトルvの値は8になっている.出力は例題14-1と同じである.
ベクタの反復子(Iterators on Vectors)
C++標準ライブラリでコンテナや非数値アルゴリズムは,シーケンス(sequence)と呼ばれる概念に焦点をあて,反復子によってシーケンスを操作する方法を用いている. シーケンスという概念を図で表現すると次のようになる.
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; typedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v; load(v); print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
解答 forループは反復子itをベクタvの始まりに設定することで初期化を行っている.*itは反復子が指している要素を返す.it++で反復子を増加させる.it == v.end()となったら反復子itはベクトルの最後の要素に続く仮の場所に移動したことになる.
実行結果
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; typedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v; load(v); sort(v.begin(),v.end()); print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
実行結果
代入ベクタ(Assignment Vectors)
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; tyoedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v, w; load(v); w = v; sort(v.begin(),v.end()); print(v); print(w); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
実行結果
代入w = vはload(w)と同じ効果がある.つまり,vの8個の要素を複写しwに搭載する.
front()関数はベクタの最初の成分を返す.back()関数はベクタの最後の成分を返す.pop_back()関数はベクタの最後の成分を削除する.
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; tyoedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v; load(v); sort(v.begin(),v.end()); print(v); cout << "v.front() = " << v.front() << endl; cout << "v.back() = " << v.back() << endl; v.pop_back(); cout <<< "v.back() = " << v.back() << endl; print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
実行結果
erase()およびinsert()関数(erase() and insert()Functions)
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; tyoedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v; load(v); sort(v.begin(),v.end()); print(v); v.erase(v.begin()+2); v.erase(v.end()-2); print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
実行結果
v.erase(v.begin()+2)により先頭の反復子から2つ目の成分,つまり,Englandが削除された.また,v.erase(v.end()-2)により末尾の反復子を含めて2つ戻った成分,つまり,Koreaが削除された.
このプログラムではinsert()関数の用い方とerase()関数を用いてあるセグメントを全て削除する仕方を学ぶ.
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; tyoedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v; load(v); sort(v.begin(),v.end()); print(v); v.erase(v.begin()+2,v.end()-2); print(v); v.insert(v.begin()+2), "Swiss"; print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
実行結果
find()関数(find()Function)
find()関数はベクタの成分を探すのに用いられる.
#include <iostream>
#include <string> #include <vector> using namespace std; typedef vector<string> Strings; tyoedef Strings::iterator Sit; void load(Strings&); void print(Strings); int main() { Strings v; load(v); print(v); Sit japan=find(v.begin(),v.end(),"Japan"); Sit spain=find(v.begin(),v.end(),"Spain"); sort(japan,spain); print(v); } void load(Strings& v) { v.push_back("Japan"); v.push_back("America"); v.push_back("Austria"); v.push_back("Germany"); v.push_back("England"); v.push_back("Italy"); v.push_back("Spain"); v.push_back("Korea"); } void print(Strings v) { for(Sit it=v.begin(); it != v.end(); it++){ cout << *it << endl; } cout << endl; } |
実行結果
1. 配列とC++ベクタの主要な違いは何か
2. ベクタの反復子と配列の添え字はどのような点で似ているか
1. find()アルゴリズムを用いて次の関数を実装せよ.
int frequency(vectorint v, int x);
2. find()関数とerase()関数を用いて,次の関数を実装し,vectorとintについてテストせよ.
void remove_duplicates(vectorint& v);
//vにおける繰り返しを削除
この関数は,ベクトルvにおいてxが何回発生したかを調べる.