C++Primerノート10---容器常用用法のまとめとまとめ


0反復
  注意点:
  • 反復器の操作は限られている:いずれも自増、自減、==、!=、オブジェクトメンバー(.);
  • シーケンスコンテナvectorに対して反復器プラスマイナス1個の整数をサポートし、その他の常用容器はサポートしていない.

  • 試験手順:
    #include <iostream>
    #include <string>
    #include <vector>
    #include <list>
    #include <queue>
    #include <map>
    #include <set>
    
    
    using namespace std;
    
    int main(int argc,char *argv[])
    {
        vector<string> svec;
        list<string> slist;
        deque<string> sdeque;
        map<string, int> smap;
        set<string> sset;
    
        //vector         ,    ,               
        vector<string>::iterator svec_it = svec.begin() + svec.size()/2;
        //list<string>::iterator slist_it = svec.begin() + svec.size()/2; //error:list         
        //deque<string>::iterator sdeque_it = svec.begin() + svec.size()/2; //error:deque         
        //map<string, int>::iterator smap_it = svec.begin() + svec.size()/2; //error:map         
        //set<string>::iterator sset_it = svec.begin() + svec.size()/2; //error:set         
    
        return 0;
    }

    1シーケンスコンテナ
      注意点:
  • エレメント個数を指定したコンテナ初期化は、シーケンスコンテナにのみ適用されます.例えば、形式がC c(n,t)またはC c(n)の2つの形式の初期化である.
  • あるコンテナを直接別のコンテナにコピーする場合、タイプは一致しなければならない:vector ivec 2(ivec 1)のようなコンテナタイプと要素タイプは同じでなければならない.
  • 反復器を使用する場合、容器タイプが同一であることを要求する、容器内の元素タイプも同一でなくてもよく、互いに互換性がある限り、複製する元素を構築する形容器の元素タイプに変換することができ、list slist(svec.begin()、svec.end());.
  • ポインタは反復器であり、内蔵配列の一対のポインタを使用して容器を初期化することができる.  size_t color_size = sizeof(color)/sizeof(char *);   list color1(color,color + color_size);
  • 参照タイプを除き、すべての組み込みタイプまたは複合タイプが要素タイプとして使用できます.
  • IO標準ライブラリタイプ以外のすべての標準ライブラリタイプが有効なコンテナ要素タイプであり、コンテナ自体も.
  • 容器の容器注意先括弧:vectorlines;区切ってください.そうしないと、コンパイル中にエラーが発生します.
  • listコンテナの反復器は算術演算(加算または減算)も関係演算(<=,<,>=,>>)もサポートせず、前置と後置の自増と自減演算および等和不等演算のみを提供する.
  • 無効な反復器を使用すると、erase関数で要素が削除された場合、その要素を指す反復器が無効になるなど、重大な実行時エラーが発生します.
  • 全ての順番容器がpush_をサポートback操作で、コンテナの尾に要素を挿入する機能.そしてpush_fontはlistとdequeコンテナタイプにのみ適用されます.
  • end操作で返された反復器を格納しないでください.dequeまたはvectorコンテナ内の要素を追加または削除すると、格納された反復器が無効になります.while(fisrt!=v.end(){...}がいいです.
  • 全ての容器に4種類の容器サイズに関する操作を提供:size(),max_size()、empty()、resize(n)、resize(n、t)、関連コンテナを含む.
  • c.back()、c.front()は、それぞれ容器cの最後の要素の参照を返し、cが空の場合、その操作は定義されていない.begin(),end()−1を解参照することに相当する.
  • pop_front()とpop_back()関数は、vectorコンテナがpop_をサポートしていない場合、コンテナ内の最初の要素と最後の要素を削除するために使用されます.front操作で、指定した要素を削除してvoidを返します.もちろんc.erase(p),c.erase(b,e)関数もあります.

  • vector:
      最も一般的なコンテナタイプで、要素への迅速なランダムアクセスをサポートし、効率的にコンテナの末尾に要素を追加および削除できますが、他の任意の場所での挿入または削除演算には高価な代価がかかります.
    list:
      は要素の順序アクセスのみをサポートしますが、list内部の任意の場所での挿入と削除は非常に迅速です.
    deque:
      は、最初と最後の要素の迅速な削除と挿入をサポートします.
    string:
      文字列タイプは、一般的には文字コンテナと見なされ、ほとんどのコンテナ操作をサポートし、vectorとほとんど同じ操作をサポートするが、スタック方式でコンテナを操作することはサポートされていない.すなわち、stringタイプでfont、back、pop_を使用することはできない.back操作. s.substr(pos,n)は、posから始まるn文字のstringを返します. s.substr(pos)は、posからsの末尾までのすべての文字のstringを返します.  s.replace(pos,len,args)は、sの下付きposから始まるlen文字を削除し、argsで指定した文字で置き換え、sの参照を返します. s.replace(b,e,args)、反復器bとeタグ範囲内のすべての文字を削除し、argsで置き換え、sの参照を返します.  s.find(args)、sでargsが初めて現れたposを検索し、なければstring::npos  s.rfind(args)、sでargsが最後に現れたpos s.find_を検索するfirst_of(args)   s.find_first_of(string)、任意の文字、sにstringの文字があるかどうかを検索します.  s.find_first_of(string,pos);   s.find_last_of(args)   s.find_first_not_of(args)   s.find_last_not_of(args)
    2関連コンテナ
      注意点:
  • 関連容器はfront、pushを提供しないfront、pop_front、back、push_backおよびpop_back操作.
  • mapはpairタイプ(対グループタイプ)の集合、キー+値
  • 反復器を使用してmap容器を巡る場合、反復器が指す要素キーの昇順配列.
  • mapのキー値は修正できず、const修飾となり、値メンバーのみ修正できる.
  • map反復器を逆参照するとpairタイプのオブジェクトが生成されます.すなわちfirstまたはsecondを使用してコンテンツを取得できます.
  • 下付き文字を使用してmapにアクセスするのは、下付き文字を使用して配列またはvectorにアクセスするのとは異なり、存在しない要素に下付き文字を使用すると、mapコンテナに新しい要素が追加され、そのキーが下付き文字になります.下付き演算の代わりにinsertを使用すると、この不要な初期化を回避できます.Insertを使用して要素を挿入する場合、キーがすでにコンテナに存在する場合、insertは値の置換を行わない.
  • set下付きオペレータはサポートされておらず、キー値は一意であり、変更はできません.
  • multimapでは、同じキーに複数の値を関連付けることができ、同じキーに関連付けられた要素は必ず隣接して格納される.したがって、ヘッダ反復器が見つかれば、同じキーに関連付けられたすべての値を巡回できます.
  • 関連容器を使用するには対応するヘッダファイルを含める必要がある、例えば#include<map>#include<set>
  • map
     m.count(k)は、mにkが現れる回数を返し、multimapとmapに適用され、mapにkが存在する場合、戻り値は必ず1であることが明らかである. m.find(k)は、mにkインデックスで存在すると、その要素を指す反復器を返します.存在しない場合は、エンド反復器を超えて戻ります.  m.erase(k),  m.erase(p),  m.erase(b,e),  m.insert(e),eはmに使用されるvalue_typeタイプの値.  m.insert(b,e)   m.insert(iter,e)
    set
      insert   count   find   erase
    multimap
      
    multiset
    3アプリケーション:テキストクエリー
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <map>
    #include <set>
    #include <cstdlib>
    #include <stdexcept>
    #include <sstream>
    
    using namespace std;
    
    class TextQuery{
    
    public: 
        typedef vector<string>::size_type line_no;
    
        void read_file(ifstream &is);
    
        set<line_no> run_query(const string&) const;
        string text_line(line_no) const;
    
    private:
        ifstream& open_file(ifstream &,const string &);
        void store_file(ifstream&);
        void build_map();
        vector<string> lines_of_text;
        map< string, set<line_no> > word_map;
    };
    
    void TextQuery::read_file(ifstream &is)
    {
        store_file(is);
        build_map();    
    }
    
    string TextQuery::text_line(line_no line) const
    {
        if(line < lines_of_text.size())
            return lines_of_text[line];
        //out_of_range,c++   ,
        throw out_of_range("line number out of range");
    }
    
    set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const
    {
        map<string, set<line_no> >::const_iterator loc = word_map.find(query_word);
        if(loc == word_map.end())
            //   set  
            return set<line_no>();
        else 
            return loc->second;
    }
    
    ifstream& TextQuery::open_file(ifstream &in,const string &file)
    {
        in.close();
        in.clear();
        in.open(file.c_str());
        return in;
    }
    
    //-----------------------------------------------------------
    //                      vector 
    //-----------------------------------------------------------
    void TextQuery::store_file(ifstream&is)
    {
        string textline;
        while(getline(is,textline))
            lines_of_text.push_back(textline);
    }
    //-----------------------------------------------------------
    //          vector       ,       ,          map< string, set<line_no> > 
    //-----------------------------------------------------------
    void TextQuery::build_map()
    {
        for(line_no line_num = 0; line_num != lines_of_text.size(); ++line_num){
            //       istringstream
            istringstream line(lines_of_text[line_num]);
            string word;
            //            string  word
            while(line >> word){
                //         word,  vector   map 
                word_map[word].insert(line_num);
            }
        }
    }
    
    
    string make_plural(size_t ctr, const string &word,
                                    const string &ending)
    {
        return (ctr == 1) ? word : word + ending;
    }
    
    void print_results(const set<TextQuery::line_no>& locs,
                        const string& sought,const TextQuery &file)
    {
        typedef set<TextQuery::line_no> line_nums;
        line_nums::size_type size = locs.size();
    
        cout << "
    "
    << sought << " occurs " << size << " " << make_plural(size,"time","s") << endl; line_nums::const_iterator it = locs.begin(); for(; it != locs.end(); ++it){ cout << "\t(line " << (*it) + 1 << ") " << file.text_line(*it) <<endl; } } int main(int argc,char *argv[]) { ifstream infile; if(argc < 2 || !open_file(infile,argv[1])){ cerr << "No input file!" << endl; return EXIT_FAILURE; } TextQuery tq; tq.read_file(infile); while(true){ cout << "Enter word to look for,or q to quit: "; string s; cin >> s; if(!cin || s == "q")break; set<TextQuery::line_no> locs = tq.run_query(s); print_results(locs,s,tq); } return EXIT_SUCCESS; }