C++string and vector(二)

9603 ワード

標準ライブラリタイプvectorは、すべてのオブジェクトのタイプが同じオブジェクトのセットを表します.コレクション内の各オブジェクトの各オブジェクトには、オブジェクトにアクセスするためのインデックスが対応しています.vectorは他のオブジェクトを「収容」するため、コンテナ(container)とも呼ばれることが多い.
C++言語にはクラステンプレート(class template)と関数テンプレートがあり、vectorはクラステンプレートです.
vectorの例では、vectorに格納されているオブジェクトのタイプに関する追加情報が提供されます.
ヘッダーファイルを追加してください.
#include <vector>

vector ivec;//ivec intタイプのオブジェクトを保存する
vector file;//file stringタイプのオブジェクトを保存する
       vector> file;//ベクトルの要素はvectorオブジェクト
vectorを使用するには,いわゆる配列習慣とSTL習慣の2つの異なる形式がある.
一、配列慣用法
1.既知の長さのvectorを定義します.
vector< int > ivec( 10 );//類似配列定義int ia[10];
ivec[インデックス番号]で要素にアクセスできます
if(ivec.empty()を用いて空か否かを判断する、ivec.size()は要素の個数を判断する.
 
2.vectorの要素はそのタイプに関連するデフォルト値に初期化されます.算術とポインタタイプのデフォルト値は0です.classタイプの場合、デフォルト値はこのようなデフォルト構造関数を呼び出すことで得ることができます.また、vectorivec(10、-1)などの要素ごとに明示的な初期値を提供して初期化を完了することもできます.ivecを定義します.int型の要素が10個含まれています.各要素は-1に初期化されます.
内蔵配列の場合、配列の要素を定数値のセットに明示的に初期化することができます.例えば、int ia[6]={-2,-1,0,1,2,1024}です.
同様の方法でvectorを明示的に初期化することはできませんが、vectorを既存の配列のすべてまたは一部に初期化することができます.vectorを初期化するために使用される配列の開始アドレスと配列の最下位要素の次の位置を指定するだけで実現できます.たとえば、iaの6つの要素をivecのvectorivec(ia,ia+6)にコピーします.  
ivecに渡された2つのポインタは、オブジェクトの値を初期化するための範囲をマークし、2番目のポインタは常にコピーする末尾要素の次の位置を指し、マークされた要素範囲は配列のサブセットであってもよい.たとえば、次のようにします.
//3要素ia[2],ia[3],ia[4]vectorivec(&ia[2],&ia[5]);
3.内蔵配列とは異なるvectorは、別のvectorによって初期化されるか、または別のvector、例えばvectorsvecに与えられることができる. void init_and_assign(//別のvectorで1つのvector vectoruser_names(svec);//......//別のvector svec=user_namesに1つのvectorをコピーする; }
二、STL慣用法
STL 9ではvectorの習慣的な使い方が全く違います.既知のサイズのvectorを定義するのではなく、空のvector vectortextを定義します.
1.インデックス要素ではなくvectorに要素を挿入し、push_などの要素に値を割り当てます.back()操作は、vectorの後ろに要素を挿入するwhileループが標準入力から文字列シーケンスを読み込み、vectorに1つの文字列を挿入するたびにstring wordを挿入することである. while ( cin >> word ) { text.push_back( word ); // ... }
要素cout<「words read are:」;  for ( int ix = 0; ix < text.size(); ++ix )       cout << text[ ix ] << ' ';  cout << endl;しかし、より典型的な方法はvector操作セットのbegin()とend()を使用して返される反復器iteratorペア:cout<「words read are:」;  for ( vector::iterator it = text.begin();     it != text.end(); ++it )            cout << *it << ' ';cout<*it;反復器を参照解除し、その指向する実際のオブジェクト++itにアクセスします.
反復器itを前に移動して次の要素を指す
2.この2つの習慣的な使い方を混用しないように注意してください.例えば、以下の定義vectorivec;空のvectorを定義してこのような文を書き直すivec[0]=1024;エラーです.ivecには最初の要素がないため、vectorにすでに存在する要素size()操作をインデックスしてvectorに含まれる要素の個数を返すしかありません.
3.同様に、vectorを所定のサイズで定義する場合、例えばvectoria(10);いずれの挿入操作も、既存の要素を上書きするのではなくvectorのサイズを大きくします.これは明らかに見えますが、次のエラーは初心者には少なくありません.const int size=7です. int ia[ size ] = { 0, 1, 1, 2, 3, 5, 8 }; vector< int > ivec( size );  for ( int ix = 0; ix < size; ++ix )     ivec.push_back( ia[ ix ]);プログラム終了時にivecには14個の要素が含まれ,iaの要素は8番目の要素から挿入される.
c++ではvectorは非常に有用な容器であり,以下,この容器についてまとめる.
1基本操作
(1)ヘッダファイルinclude.
(2)vectorオブジェクトを作成し、vectorvec;
(3)末尾挿入数字:vec.push_back(a);
(4)下付きアクセス要素,cout<(5)反復器を用いて要素にアクセスする.
vector<int>::iterator it;for(it=vec.begin();it!=vec.end();it++)
   cout<<*it<<endl;

(6)挿入要素:vec.insert(vec.begin()+i,a);i+1番目の要素の前にaを挿入する.
(7)要素の削除:vec.erase(vec.begin()+2);3番目の要素を削除
vec.erase(vec.begin()+i,vec.end()+j);区間[i,j-1]を削除する.区間は0から
(8)ベクトルサイズ:vec.size();
(9)クリア:vec.clear();
2
vectorの要素はint,double,stringだけでなく,構造体であってもよいが,構造体をグローバルとして定義しないとエラーになることに注意する.以下に、短いプログラムコードを示します.
#include<stdio.h>#include<algorithm>#include<vector>#include<iostream>using namespace std; typedef struct rect {    int id;    int length;    int width;

  // , , id,length,width 。
  bool operator< (const rect &a)  const
    {
        if(id!=a.id)
            return id<a.id;
        else
        {
            if(length!=a.length)
                return length<a.length;
            else
                return width<a.width;
        }
    } }Rect;
int main() {    vector<Rect> vec;    Rect rect;    rect.id=1;    rect.length=2;    rect.width=3;    vec.push_back(rect);    vector<Rect>::iterator it=vec.begin();    cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;    return 0; }

3アルゴリズム
(1)reverseを使用して要素を反転:ヘッダファイル#includeが必要
reverse(vec.begin(),vec.end());要素を反転(vectorで1つの関数に2つの反復器が必要な場合、
一般的には次のいずれも含まれません.)
(2)sortソートを使用する:ヘッダファイル#includeが必要であり、
sort(vec.begin(),vec.end());(デフォルトは昇順、すなわち小さいから大きい)である.
ソート比較関数を書き換えることで、次のように降順に比較できます.
ソート比較関数を定義するには、次の手順に従います.
bool Comp(const int &a,const int &b){    return a>b;}呼び出し時:sort(vec.begin()、vec.end(),Comp),これで降順に並べ替えられる.
#include <vector>
#include <iostream>
#include <string>
using namespace std;

void main()
{
#ifdef LIST_INIT
	// list initialization, articles has 3 elements
	vector<string> articles = { "a", "an", "the" };
#else
	string temp[] = { "a", "an", "the" };
	vector<string> articles(begin(temp), end(temp));
#endif

	vector<string> svec; // default initialization; svec has no elements
	vector<int> ivec;             // ivec holds objects of type int

	vector<vector<string>> file;  // vector whose elements are vectors
	vector<vector<int>> vecOfvec; // each element is itself a vector

	// all five vectors have size 0
	cout << svec.size() << " " << ivec.size() << " "
		<< " "
		<< file.size() << " " << vecOfvec.size() << endl;

	vector<int> ivec2(10);     // ten elements, each initialized to 0
	vector<int> ivec3(10, -1); // ten int elements, each initialized to -1
	vector<string> svec2(10);  // ten elements, each an empty string
	vector<string> svec3(10, "hi!"); // ten strings; each element is "hi!"
	cout << ivec2.size() << " " << ivec3.size() << " "
		<< svec2.size() << " " << svec3.size() << endl;

	// 10 is not a string, so cannot be list initialization
	vector<string> v1(10); // construct v1 with ten value-initialized elements
#ifdef LIST_INIT
	vector<string> v2{ 10 }; // ten elements value-initialized elements
#else
	vector<string> v2(10);
#endif
	vector<string> v3(10, "hi");  // ten elements with value "hi"
#ifdef LIST_INIT
	// again list initialization is not viable, so ordinary construction
	vector<string> v4{ 10, "hi" };  // ten elements with values "hi"
#else
	vector<string> v4(10, "hi");  // ten elements with values "hi"
#endif

	// all four vectors have size ten
	cout << v1.size() << " " << v2.size()
		<< " " << v3.size() << " " << v4.size() << endl;

#ifdef LIST_INIT
	vector<string> vs1{ "hi" }; // list initialization: vs1 has 1 element 
	vector<string> vs2{ 10 };   // ten default-initialized elements
	vector<string> vs3{ 10, "hi" }; // has ten elements with value "hi"
#else
	vector<string> vs1;
	vs1.push_back("hi"); // explicitly add the element; vs1 has 1 element 
	vector<string> vs2(10); // don't use curlies; 
	// vs2 has ten default-initialized elements
	vector<string> vs3(10, "hi"); // don't use curlies; 
	// vs3 has ten elements with value "hi"
#endif
	cout << vs1.size() << " " << vs2.size() << " " << vs3.size() << endl;

	vector<int> v5(10, 1);  // ten elements with value 1
#ifdef LIST_INIT
	vector<int> v6{ 10, 1 };  // two elements with values 10 and 1
#else
	vector<int> v6;
	v6.push_back(10);
	v6.push_back(1);
#endif
	cout << v5.size() << " " << v6.size() << endl;

#ifdef LIST_INIT
	// intention is clearer
	vector<int> alt_v3 = { 10 };    // one element with value 10
	vector<int> alt_v4 = { 10, 1 }; // two elements with values 10 and 1
#else
	vector<int> alt_v3;
	alt_v3.push_back(10);    // one element with value 10

	vector<int> alt_v4;
	alt_v4.push_back(10);
	alt_v4.push_back(1); // two elements with values 10 and 1
#endif
	cout << alt_v3.size() << " " << alt_v4.size() << endl;

	system("pause");
}
0 0  0 0
10 10 10 10
10 10 10 10
1 10 10
10 2
1 2
       . . .